From 1cd8811ef9cf4121b34810d703f8687a21abc4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 14 Dec 2024 19:17:23 +0100 Subject: [PATCH] ** WIP ** [I8042PRT] Add support for SysRq debugging key For reference, see https://reactos.org/wiki/I8042prt.sys#Support_for_the_Kernel_Debugger --- drivers/input/i8042prt/i8042prt.h | 6 + drivers/input/i8042prt/keyboard.c | 46 +++++- drivers/input/i8042prt/registry.c | 250 ++++++++++++++++-------------- 3 files changed, 184 insertions(+), 118 deletions(-) diff --git a/drivers/input/i8042prt/i8042prt.h b/drivers/input/i8042prt/i8042prt.h index 2e67059990c41..798601d9e8543 100644 --- a/drivers/input/i8042prt/i8042prt.h +++ b/drivers/input/i8042prt/i8042prt.h @@ -37,6 +37,8 @@ typedef struct _I8042_SETTINGS ULONG PollingIterationsMaximum; ULONG ResendIterations; /* done */ ULONG SampleRate; + ULONG BreakOnSysRq; /* done */ + ULONG KdEnableOnCtrlSysRq; /* done */ ULONG CrashOnCtrlScroll; /* done */ } I8042_SETTINGS, *PI8042_SETTINGS; @@ -210,6 +212,10 @@ typedef struct _I8042_HOOK_WORKITEM #define MAX(a, b) ((a) >= (b) ? (a) : (b)) +// #define KEYBOARD_BREAK_CODE 0xF0 +#define KEYBOARD_DEBUG_HOTKEY_ENH 0x37 // SysReq (Alt+PrtSc) scan code for Enhanced Keyboard +#define KEYBOARD_DEBUG_HOTKEY_AT 0x54 // SysReq scan code for 84-key Keyboard + #define KEYBOARD_POWER_CODE 0x5E #define KEYBOARD_SLEEP_CODE 0x5F #define KEYBOARD_WAKE_CODE 0x63 diff --git a/drivers/input/i8042prt/keyboard.c b/drivers/input/i8042prt/keyboard.c index 68f2a366c817c..c42efbb329286 100644 --- a/drivers/input/i8042prt/keyboard.c +++ b/drivers/input/i8042prt/keyboard.c @@ -836,10 +836,38 @@ i8042KbdInterruptService( INFO_(I8042PRT, "Got: 0x%02x\n", Output); + + /* Check for SysRq debugging support */ + if (!(InputData->Flags & KEY_BREAK) && + PortDeviceExtension->Settings.BreakOnSysRq && + !KD_DEBUGGER_NOT_PRESENT && KD_DEBUGGER_ENABLED) + { + BOOLEAN isEnh = ENHANCED_KEYBOARD(DeviceExtension->KeyboardAttributes.KeyboardIdentifier); + + /* On Enhanced 101 keyboard, SysReq key is 0xE0 0x37 + * On 84-key AT keyboard, SysReq key is 0xE0 0x54. */ + if ((InputData->Flags & KEY_E0) && + (InputData->MakeCode == isEnh ? KEYBOARD_DEBUG_HOTKEY_ENH : KEYBOARD_DEBUG_HOTKEY_AT)) + { + /* Wrap in SEH so we don't crash if there is + * no debugger or it gets disconnected. */ + _SEH2_TRY + { + DbgBreakPointWithStatus(DBG_STATUS_SYSRQ); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; + } + } + + + // See commit cba6f25d3 (r44743) if (PortDeviceExtension->Settings.CrashOnCtrlScroll) { /* Test for CTRL + SCROLL LOCK twice */ - static const UCHAR ScanCodes[] = { 0x1d, 0x46, 0xc6, 0x46, 0 }; + static const UCHAR ScanCodes[] = { /*0xe0,*/ 0x1d, 0x46, 0xc6, 0x46, 0 }; if (Output == ScanCodes[DeviceExtension->ComboPosition]) { @@ -861,6 +889,8 @@ i8042KbdInterruptService( } /* Test for TAB + key combination */ + // HISTORICAL NOTE: TAB + key was introduced in commit + // 3273c9317 (r2469) in replacement of SysRq + key. if (InputData->MakeCode == 0x0F) { DeviceExtension->TabPressed = !(InputData->Flags & KEY_BREAK); @@ -870,10 +900,20 @@ i8042KbdInterruptService( DeviceExtension->TabPressed = FALSE; /* Check which action to do */ - if (InputData->MakeCode == 0x25) + if (!KD_DEBUGGER_NOT_PRESENT && (InputData->MakeCode == 0x25)) { /* k - Breakpoint */ - DbgBreakPointWithStatus(DBG_STATUS_SYSRQ); + + /* Wrap in SEH so we don't crash if there is + * no debugger or it gets disconnected. */ + _SEH2_TRY + { + DbgBreakPointWithStatus(DBG_STATUS_SYSRQ); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + } + _SEH2_END; } else if (InputData->MakeCode == 0x30) { diff --git a/drivers/input/i8042prt/registry.c b/drivers/input/i8042prt/registry.c index bf1e4fa928cc8..4d57a166a7f3e 100644 --- a/drivers/input/i8042prt/registry.c +++ b/drivers/input/i8042prt/registry.c @@ -22,8 +22,9 @@ ReadRegistryEntries( IN PUNICODE_STRING RegistryPath, OUT PI8042_SETTINGS Settings) { - RTL_QUERY_REGISTRY_TABLE Parameters[17]; NTSTATUS Status; + ULONG i; + RTL_QUERY_REGISTRY_TABLE Parameters[19]; ULONG DefaultKeyboardDataQueueSize = 0x64; PCWSTR DefaultKeyboardDeviceBaseName = L"KeyboardPort"; @@ -39,126 +40,143 @@ ReadRegistryEntries( ULONG DefaultPollingIterationsMaximum = 12000; ULONG DefaultResendIterations = 0x3; ULONG DefaultSampleRate = 60; - ULONG DefaultCrashOnCtrlScroll; - /* Default value for CrashOnCtrlScroll depends if we're - * running a debug build or a normal build. - */ + ULONG DefaultBreakOnSysRq = 1; + + /* Default values depending on whether we are + * running a debug build or a normal build. */ #if DBG - DefaultCrashOnCtrlScroll = 1; + ULONG DefaultKdEnableOnCtrlSysRq = 1; + ULONG DefaultCrashOnCtrlScroll = 1; #else - DefaultCrashOnCtrlScroll = 0; + ULONG DefaultKdEnableOnCtrlSysRq = 0; + ULONG DefaultCrashOnCtrlScroll = 0; #endif RtlZeroMemory(Parameters, sizeof(Parameters)); - - Parameters[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; - Parameters[0].Name = L"Parameters"; - - Parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[1].Name = L"KeyboardDataQueueSize"; - Parameters[1].EntryContext = &Settings->KeyboardDataQueueSize; - Parameters[1].DefaultType = REG_DWORD; - Parameters[1].DefaultData = &DefaultKeyboardDataQueueSize; - Parameters[1].DefaultLength = sizeof(ULONG); - - Parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[2].Name = L"KeyboardDeviceBaseName"; - Parameters[2].EntryContext = &Settings->KeyboardDeviceBaseName; - Parameters[2].DefaultType = REG_SZ; - Parameters[2].DefaultData = (PVOID)DefaultKeyboardDeviceBaseName; - Parameters[2].DefaultLength = 0; - - Parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[3].Name = L"MouseDataQueueSize"; - Parameters[3].EntryContext = &Settings->MouseDataQueueSize; - Parameters[3].DefaultType = REG_DWORD; - Parameters[3].DefaultData = &DefaultMouseDataQueueSize; - Parameters[3].DefaultLength = sizeof(ULONG); - - Parameters[4].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[4].Name = L"MouseResolution"; - Parameters[4].EntryContext = &Settings->MouseResolution; - Parameters[4].DefaultType = REG_DWORD; - Parameters[4].DefaultData = &DefaultMouseResolution; - Parameters[4].DefaultLength = sizeof(ULONG); - - Parameters[5].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[5].Name = L"MouseSynchIn100ns"; - Parameters[5].EntryContext = &Settings->MouseSynchIn100ns; - Parameters[5].DefaultType = REG_DWORD; - Parameters[5].DefaultData = &DefaultMouseSynchIn100ns; - Parameters[5].DefaultLength = sizeof(ULONG); - - Parameters[6].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[6].Name = L"NumberOfButtons"; - Parameters[6].EntryContext = &Settings->NumberOfButtons; - Parameters[6].DefaultType = REG_DWORD; - Parameters[6].DefaultData = &DefaultNumberOfButtons; - Parameters[6].DefaultLength = sizeof(ULONG); - - Parameters[7].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[7].Name = L"PointerDeviceBaseName"; - Parameters[7].EntryContext = &Settings->PointerDeviceBaseName; - Parameters[7].DefaultType = REG_SZ; - Parameters[7].DefaultData = (PVOID)DefaultPointerDeviceBaseName; - Parameters[7].DefaultLength = 0; - - Parameters[8].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[8].Name = L"PollStatusIterations"; - Parameters[8].EntryContext = &Settings->PollStatusIterations; - Parameters[8].DefaultType = REG_DWORD; - Parameters[8].DefaultData = &DefaultPollStatusIterations; - Parameters[8].DefaultLength = sizeof(ULONG); - - Parameters[9].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[9].Name = L"OverrideKeyboardType"; - Parameters[9].EntryContext = &Settings->OverrideKeyboardType; - Parameters[9].DefaultType = REG_DWORD; - Parameters[9].DefaultData = &DefaultOverrideKeyboardType; - Parameters[9].DefaultLength = sizeof(ULONG); - - Parameters[10].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[10].Name = L"OverrideKeyboardSubtype"; - Parameters[10].EntryContext = &Settings->OverrideKeyboardSubtype; - Parameters[10].DefaultType = REG_DWORD; - Parameters[10].DefaultData = &DefaultOverrideKeyboardSubtype; - Parameters[10].DefaultLength = sizeof(ULONG); - - Parameters[11].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[11].Name = L"PollingIterations"; - Parameters[11].EntryContext = &Settings->PollingIterations; - Parameters[11].DefaultType = REG_DWORD; - Parameters[11].DefaultData = &DefaultPollingIterations; - Parameters[11].DefaultLength = sizeof(ULONG); - - Parameters[12].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[12].Name = L"PollingIterationsMaximum"; - Parameters[12].EntryContext = &Settings->PollingIterationsMaximum; - Parameters[12].DefaultType = REG_DWORD; - Parameters[12].DefaultData = &DefaultPollingIterationsMaximum; - Parameters[12].DefaultLength = sizeof(ULONG); - - Parameters[13].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[13].Name = L"ResendIterations"; - Parameters[13].EntryContext = &Settings->ResendIterations; - Parameters[13].DefaultType = REG_DWORD; - Parameters[13].DefaultData = &DefaultResendIterations; - Parameters[13].DefaultLength = sizeof(ULONG); - - Parameters[14].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[14].Name = L"SampleRate"; - Parameters[14].EntryContext = &Settings->SampleRate; - Parameters[14].DefaultType = REG_DWORD; - Parameters[14].DefaultData = &DefaultSampleRate; - Parameters[14].DefaultLength = sizeof(ULONG); - - Parameters[15].Flags = RTL_QUERY_REGISTRY_DIRECT; - Parameters[15].Name = L"CrashOnCtrlScroll"; - Parameters[15].EntryContext = &Settings->CrashOnCtrlScroll; - Parameters[15].DefaultType = REG_DWORD; - Parameters[15].DefaultData = &DefaultCrashOnCtrlScroll; - Parameters[15].DefaultLength = sizeof(ULONG); + i = 0; + + Parameters[i].Flags = RTL_QUERY_REGISTRY_SUBKEY; + Parameters[i].Name = L"Parameters"; + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"KeyboardDataQueueSize"; + Parameters[i].EntryContext = &Settings->KeyboardDataQueueSize; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultKeyboardDataQueueSize; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"KeyboardDeviceBaseName"; + Parameters[i].EntryContext = &Settings->KeyboardDeviceBaseName; + Parameters[i].DefaultType = REG_SZ; + Parameters[i].DefaultData = (PVOID)DefaultKeyboardDeviceBaseName; + Parameters[i].DefaultLength = 0; + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"MouseDataQueueSize"; + Parameters[i].EntryContext = &Settings->MouseDataQueueSize; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultMouseDataQueueSize; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"MouseResolution"; + Parameters[i].EntryContext = &Settings->MouseResolution; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultMouseResolution; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"MouseSynchIn100ns"; + Parameters[i].EntryContext = &Settings->MouseSynchIn100ns; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultMouseSynchIn100ns; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"NumberOfButtons"; + Parameters[i].EntryContext = &Settings->NumberOfButtons; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultNumberOfButtons; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"PointerDeviceBaseName"; + Parameters[i].EntryContext = &Settings->PointerDeviceBaseName; + Parameters[i].DefaultType = REG_SZ; + Parameters[i].DefaultData = (PVOID)DefaultPointerDeviceBaseName; + Parameters[i].DefaultLength = 0; + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"PollStatusIterations"; + Parameters[i].EntryContext = &Settings->PollStatusIterations; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultPollStatusIterations; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"OverrideKeyboardType"; + Parameters[i].EntryContext = &Settings->OverrideKeyboardType; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultOverrideKeyboardType; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"OverrideKeyboardSubtype"; + Parameters[i].EntryContext = &Settings->OverrideKeyboardSubtype; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultOverrideKeyboardSubtype; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"PollingIterations"; + Parameters[i].EntryContext = &Settings->PollingIterations; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultPollingIterations; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"PollingIterationsMaximum"; + Parameters[i].EntryContext = &Settings->PollingIterationsMaximum; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultPollingIterationsMaximum; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"ResendIterations"; + Parameters[i].EntryContext = &Settings->ResendIterations; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultResendIterations; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"SampleRate"; + Parameters[i].EntryContext = &Settings->SampleRate; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultSampleRate; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"BreakOnSysRq"; + Parameters[i].EntryContext = &Settings->BreakOnSysRq; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultBreakOnSysRq; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"KdEnableOnCtrlSysRq"; + Parameters[i].EntryContext = &Settings->KdEnableOnCtrlSysRq; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultKdEnableOnCtrlSysRq; + Parameters[i].DefaultLength = sizeof(ULONG); + + Parameters[++i].Flags = RTL_QUERY_REGISTRY_DIRECT; + Parameters[i].Name = L"CrashOnCtrlScroll"; + Parameters[i].EntryContext = &Settings->CrashOnCtrlScroll; + Parameters[i].DefaultType = REG_DWORD; + Parameters[i].DefaultData = &DefaultCrashOnCtrlScroll; + Parameters[i].DefaultLength = sizeof(ULONG); Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, RegistryPath->Buffer, @@ -196,6 +214,8 @@ ReadRegistryEntries( Settings->PollingIterationsMaximum = DefaultPollingIterationsMaximum; Settings->ResendIterations = DefaultResendIterations; Settings->SampleRate = DefaultSampleRate; + Settings->BreakOnSysRq = DefaultBreakOnSysRq; + Settings->KdEnableOnCtrlSysRq = DefaultKdEnableOnCtrlSysRq; Settings->CrashOnCtrlScroll = DefaultCrashOnCtrlScroll; if (!RtlCreateUnicodeString(&Settings->KeyboardDeviceBaseName, DefaultKeyboardDeviceBaseName) || !RtlCreateUnicodeString(&Settings->PointerDeviceBaseName, DefaultPointerDeviceBaseName))