18BOOLEAN mBmHotkeyServiceStarted =
FALSE;
19UINTN mBmHotkeySupportCount = 0;
27VOID *mBmTxtInExRegistration =
NULL;
42 + KeyOption->KeyData.Options.InputKeyCount *
sizeof (
EFI_INPUT_KEY);
61 UINT16 OptionName[BM_OPTION_NAME_LEN];
77 mBmLoadOptionName[LoadOptionTypeBoot],
82 if (BootOption ==
NULL) {
89 gBS->CalculateCrc32 (BootOption, BootOptionSize, &Crc);
92 return (BOOLEAN)(KeyOption->BootOptionCrc == Crc);
116 if (!
CompareGuid (Guid, &gEfiGlobalVariableGuid) ||
117 (
StrSize (Name) !=
sizeof (L
"Key####")) ||
118 (
StrnCmp (Name, L
"Key", 3) != 0)
125 for (Index = 3; Index < 7; Index++) {
130 *OptionNumber = (UINT16)Uint + *OptionNumber * 0x10;
139 UINTN KeyOptionCount;
166 ASSERT (KeyOption !=
NULL);
173 ASSERT (Param->KeyOptions !=
NULL);
177 for (Index = 0; Index < Param->KeyOptionCount; Index++) {
178 if (OptionNumber < Param->KeyOptions[Index].OptionNumber) {
184 CopyMem (&Param->KeyOptions[Index], KeyOption, KeyOptionSize);
185 Param->KeyOptions[Index].OptionNumber = OptionNumber;
186 Param->KeyOptionCount++;
212 Param.KeyOptions =
NULL;
213 Param.KeyOptionCount = 0;
217 *Count = Param.KeyOptionCount;
219 return Param.KeyOptions;
237 return (BOOLEAN)((Value & Bit) != 0);
259 if (KeyOption ==
NULL) {
260 return EFI_INVALID_PARAMETER;
264 while (KeyOption->KeyData.Options.InputKeyCount < sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0])) {
271 &KeyOption->Keys[KeyOption->KeyData.Options.InputKeyCount],
275 KeyOption->KeyData.Options.InputKeyCount++;
282 return EFI_INVALID_PARAMETER;
285 if ((Modifier & ~(EFI_BOOT_MANAGER_SHIFT_PRESSED
286 | EFI_BOOT_MANAGER_CONTROL_PRESSED
287 | EFI_BOOT_MANAGER_ALT_PRESSED
288 | EFI_BOOT_MANAGER_LOGO_PRESSED
289 | EFI_BOOT_MANAGER_MENU_KEY_PRESSED
290 | EFI_BOOT_MANAGER_SYS_REQ_PRESSED
293 return EFI_INVALID_PARAMETER;
296 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_SHIFT_PRESSED)) {
297 KeyOption->KeyData.Options.ShiftPressed = 1;
300 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_CONTROL_PRESSED)) {
301 KeyOption->KeyData.Options.ControlPressed = 1;
304 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_ALT_PRESSED)) {
305 KeyOption->KeyData.Options.AltPressed = 1;
308 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_LOGO_PRESSED)) {
309 KeyOption->KeyData.Options.LogoPressed = 1;
312 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_MENU_KEY_PRESSED)) {
313 KeyOption->KeyData.Options.MenuPressed = 1;
316 if (
BmBitSet (Modifier, EFI_BOOT_MANAGER_SYS_REQ_PRESSED)) {
317 KeyOption->KeyData.Options.SysReqPressed = 1;
332 if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
335 mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
357 CHAR16 OptionName[BM_OPTION_NAME_LEN];
361 if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {
368 DEBUG ((DEBUG_INFO,
"[Bds]BmHotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar));
372 ; !
IsNull (&mBmHotkeyList, Link)
376 Hotkey = BM_HOTKEY_FROM_LINK (Link);
381 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
382 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
383 if ((KeyData->Key.ScanCode == HotkeyData->
Key.ScanCode) &&
384 (KeyData->Key.UnicodeChar == HotkeyData->
Key.UnicodeChar) &&
385 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ?
393 Hotkey->WaitingKey++;
395 if (Hotkey->WaitingKey == Hotkey->CodeCount) {
399 Hotkey->WaitingKey = 0;
403 Status =
gBS->SignalEvent (mBmHotkeyTriggered);
406 if (!Hotkey->IsContinue) {
414 mBmLoadOptionName[LoadOptionTypeBoot],
418 DEBUG ((DEBUG_INFO,
"[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));
419 if (EFI_ERROR (Status)) {
420 mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;
423 DEBUG ((DEBUG_INFO,
"[Bds]Continue key pressed!\n"));
430 Hotkey->WaitingKey = 0;
461 Status =
gBS->OpenProtocol (
463 &gEfiSimpleTextInputExProtocolGuid,
467 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
469 if (!EFI_ERROR (Status)) {
471 if (Handles !=
NULL) {
476 Status =
gBS->LocateHandleBuffer (
478 &gEfiSimpleTextInputExProtocolGuid,
510 for (Index = 0; Index < HandleCount; Index++) {
511 Status =
gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **)&TxtInEx);
513 for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
514 Status = TxtInEx->RegisterKeyNotify (
516 &Hotkey->KeyData[KeyIndex],
520 if (!EFI_ERROR (Status)) {
521 Status = TxtInEx->UnregisterKeyNotify (TxtInEx, NotifyHandle);
522 DEBUG ((DEBUG_INFO,
"[Bds]UnregisterKeyNotify: %04x/%04x %r\n", Hotkey->KeyData[KeyIndex].Key.ScanCode, Hotkey->KeyData[KeyIndex].Key.UnicodeChar, Status));
527 if (Handles !=
NULL) {
553 for (Index = 0; Index < Hotkey->CodeCount; Index++) {
554 Status = TxtInEx->RegisterKeyNotify (
556 &Hotkey->KeyData[Index],
562 "[Bds]RegisterKeyNotify: %04x/%04x %08x/%02x %r\n",
563 Hotkey->KeyData[Index].Key.ScanCode,
564 Hotkey->KeyData[Index].Key.UnicodeChar,
565 Hotkey->KeyData[Index].KeyState.KeyShiftState,
566 Hotkey->KeyData[Index].KeyState.KeyToggleState,
569 if (EFI_ERROR (Status)) {
594 IN UINT32 KeyShiftState,
595 IN UINT32 *KeyShiftStates,
601 if (KeyOption->KeyData.Options.ShiftPressed) {
602 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
603 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);
611 if (KeyOption->KeyData.Options.ControlPressed) {
612 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
613 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);
621 if (KeyOption->KeyData.Options.AltPressed) {
622 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
623 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);
630 if (KeyOption->KeyData.Options.LogoPressed) {
631 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
632 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);
639 if (KeyOption->KeyData.Options.MenuPressed) {
640 KeyShiftState |= EFI_MENU_KEY_PRESSED;
643 if (KeyOption->KeyData.Options.SysReqPressed) {
644 KeyShiftState |= EFI_SYS_REQ_PRESSED;
647 KeyShiftStates[*KeyShiftStateCount] = KeyShiftState;
648 (*KeyShiftStateCount)++;
675 UINT32 KeyShiftStates[16];
676 UINTN KeyShiftStateCount;
678 if (KeyOption->KeyData.Options.InputKeyCount > mBmHotkeySupportCount) {
679 return EFI_UNSUPPORTED;
682 KeyShiftStateCount = 0;
684 ASSERT (KeyShiftStateCount <=
ARRAY_SIZE (KeyShiftStates));
690 for (Index = 0; Index < KeyShiftStateCount; Index++) {
692 ASSERT (Hotkey !=
NULL);
694 Hotkey->Signature = BM_HOTKEY_SIGNATURE;
695 Hotkey->BootOption = KeyOption->BootOption;
696 Hotkey->IsContinue = (BOOLEAN)(KeyOption == mBmContinueKeyOption);
697 Hotkey->CodeCount = (UINT8)KeyOption->KeyData.Options.InputKeyCount;
699 for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {
706 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
707 Status =
gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **)&TxtInEx);
713 if (Handles !=
NULL) {
744 Status =
gBS->LocateHandle (
747 mBmTxtInExRegistration,
751 if (EFI_ERROR (Status)) {
758 Status =
gBS->HandleProtocol (
760 &gEfiSimpleTextInputExProtocolGuid,
792 if (KeyOptions !=
NULL) {
796 return EFI_NOT_FOUND;
822 if (mBmContinueKeyOption !=
NULL) {
823 return EFI_ALREADY_STARTED;
831 if (!EFI_ERROR (Status)) {
833 ASSERT (mBmContinueKeyOption !=
NULL);
834 if (mBmHotkeyServiceStarted) {
858 DEBUG ((DEBUG_INFO,
"[Bds]Stop Hotkey Service!\n"));
859 gBS->CloseEvent (Event);
863 Hotkey = BM_HOTKEY_FROM_LINK (Link);
888 UINTN KeyOptionCount;
891 UINT32 *BootOptionSupport;
894 if (BootOptionSupport !=
NULL) {
895 if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY) != 0) {
896 mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >>
LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));
902 if (mBmHotkeySupportCount == 0) {
903 DEBUG ((DEBUG_INFO,
"Bds: BootOptionSupport NV variable forbids starting the hotkey service.\n"));
904 return EFI_UNSUPPORTED;
907 Status =
gBS->CreateEvent (
916 if (HotkeyTriggered !=
NULL) {
917 *HotkeyTriggered = mBmHotkeyTriggered;
921 for (Index = 0; Index < KeyOptionCount; Index++) {
927 if (mBmContinueKeyOption !=
NULL) {
938 &gEfiSimpleTextInputExProtocolGuid,
942 &mBmTxtInExRegistration
954 mBmHotkeyServiceStarted =
TRUE;
974 IN UINT16 BootOptionNumber,
982 UINTN BootOptionSize;
983 CHAR16 BootOptionName[BM_OPTION_NAME_LEN];
986 UINTN KeyOptionCount;
988 UINTN KeyOptionNumber;
989 CHAR16 KeyOptionName[
sizeof (
"Key####")];
993 sizeof (BootOptionName),
995 mBmLoadOptionName[LoadOptionTypeBoot],
1000 if (BootOption ==
NULL) {
1001 return EFI_NOT_FOUND;
1006 Status =
gBS->CalculateCrc32 (BootOption, BootOptionSize, &KeyOption.
BootOptionCrc);
1013 if (EFI_ERROR (Status)) {
1017 KeyOptionNumber = LoadOptionNumberUnassigned;
1022 for (Index = 0; Index < KeyOptionCount; Index++) {
1023 if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.
KeyData.PackedValue) &&
1029 if ((KeyOptionNumber == LoadOptionNumberUnassigned) &&
1030 (KeyOptions[Index].OptionNumber > Index)
1033 KeyOptionNumber = Index;
1039 if (Index < KeyOptionCount) {
1040 return EFI_ALREADY_STARTED;
1043 if (KeyOptionNumber == LoadOptionNumberUnassigned) {
1044 KeyOptionNumber = KeyOptionCount;
1047 UnicodeSPrint (KeyOptionName,
sizeof (KeyOptionName), L
"Key%04x", KeyOptionNumber);
1049 Status =
gRT->SetVariable (
1051 &gEfiGlobalVariableGuid,
1056 if (!EFI_ERROR (Status)) {
1060 if (AddedOption !=
NULL) {
1069 if (mBmHotkeyServiceStarted) {
1100 UINTN KeyOptionCount;
1105 CHAR16 KeyOptionName[
sizeof (
"Key####")];
1112 if (EFI_ERROR (Status)) {
1122 Hotkey = BM_HOTKEY_FROM_LINK (Link);
1125 for (Index = 0;
Match && (Index < Hotkey->CodeCount); Index++) {
1156 Status = EFI_NOT_FOUND;
1158 for (Index = 0; Index < KeyOptionCount; Index++) {
1159 if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.
KeyData.PackedValue) &&
1161 KeyOptions[Index].Keys,
1167 UnicodeSPrint (KeyOptionName,
sizeof (KeyOptionName), L
"Key%04x", KeyOptions[Index].OptionNumber);
1168 Status =
gRT->SetVariable (
1170 &gEfiGlobalVariableGuid,
1178 if (DeletedOption !=
NULL) {
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
INTN EFIAPI LowBitSet32(IN UINT32 Operand)
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
INTN EFIAPI StrnCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString, IN UINTN Length)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS BmInitializeKeyFields(IN UINT32 Modifier, IN VA_LIST Args, OUT EFI_BOOT_MANAGER_KEY_OPTION *KeyOption)
BOOLEAN BmIsKeyOptionVariable(CHAR16 *Name, EFI_GUID *Guid, UINT16 *OptionNumber)
BOOLEAN BmBitSet(IN UINT32 Value, IN UINT32 Bit)
BOOLEAN BmIsKeyOptionValid(IN CONST EFI_BOOT_MANAGER_KEY_OPTION *KeyOption, IN UINTN KeyOptionSize)
EFI_STATUS EFIAPI EfiBootManagerStartHotkeyService(IN EFI_EVENT *HotkeyTriggered)
VOID BmGenerateKeyShiftState(IN UINTN Depth, IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption, IN UINT32 KeyShiftState, IN UINT32 *KeyShiftStates, IN UINTN *KeyShiftStateCount)
EFI_STATUS BmFreeKeyOptions(IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions, IN UINTN KeyOptionCount)
EFI_STATUS EFIAPI BmHotkeyCallback(IN EFI_KEY_DATA *KeyData)
VOID EFIAPI EfiBootManagerHotkeyBoot(VOID)
VOID EFIAPI BmTxtInExCallback(IN EFI_EVENT Event, IN VOID *Context)
UINTN BmSizeOfKeyOption(IN CONST EFI_BOOT_MANAGER_KEY_OPTION *KeyOption)
EFI_STATUS EFIAPI EfiBootManagerRegisterContinueKeyOption(IN UINT32 Modifier,...)
EFI_HANDLE * BmGetActiveConsoleIn(OUT UINTN *Count)
EFI_BOOT_MANAGER_KEY_OPTION * BmGetKeyOptions(OUT UINTN *Count)
VOID BmCollectKeyOptions(CHAR16 *Name, EFI_GUID *Guid, VOID *Context)
EFI_STATUS EFIAPI EfiBootManagerDeleteKeyOptionVariable(IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption OPTIONAL, IN UINT32 Modifier,...)
EFI_STATUS BmRegisterHotkeyNotify(IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx, IN BM_HOTKEY *Hotkey)
EFI_STATUS BmProcessKeyOption(IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption)
VOID EFIAPI BmStopHotkeyService(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS BmUnregisterHotkeyNotify(IN BM_HOTKEY *Hotkey)
EFI_STATUS EFIAPI EfiBootManagerAddKeyOptionVariable(OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption OPTIONAL, IN UINT16 BootOptionNumber, IN UINT32 Modifier,...)
VOID BmForEachVariable(BM_VARIABLE_VISITOR Visitor, VOID *Context)
UINTN BmCharToUint(IN CHAR16 Char)
VOID *EFIAPI ReallocatePool(IN UINTN OldSize, IN UINTN NewSize, IN VOID *OldBuffer OPTIONAL)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME
UINTN EFIAPI UnicodeSPrint(OUT CHAR16 *StartOfBuffer, IN UINTN BufferSize, IN CONST CHAR16 *FormatString,...)
EFI_RUNTIME_SERVICES * gRT
#define VA_ARG(Marker, TYPE)
#define VA_START(Marker, Parameter)
#define ARRAY_SIZE(Array)
#define OFFSET_OF(TYPE, Field)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
STATIC BOOLEAN Match(IN CONST CHAR16 *Translated, IN UINTN TranslatedLength, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath)
VOID EFIAPI EfiBootManagerBoot(IN EFI_BOOT_MANAGER_LOAD_OPTION *BootOption)
EFI_STATUS EFIAPI EfiBootManagerFreeLoadOption(IN EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
EFI_STATUS EFIAPI EfiBootManagerVariableToLoadOption(IN CHAR16 *VariableName, IN OUT EFI_BOOT_MANAGER_LOAD_OPTION *LoadOption)
#define EFI_INITIALIZE_LOCK_VARIABLE(Priority)
VOID EFIAPI EfiReleaseLock(IN EFI_LOCK *Lock)
EFI_STATUS EFIAPI GetEfiGlobalVariable2(IN CONST CHAR16 *Name, OUT VOID **Value, OUT UINTN *Size OPTIONAL)
VOID EFIAPI EfiEventEmptyFunction(IN EFI_EVENT Event, IN VOID *Context)
VOID EFIAPI EfiAcquireLock(IN EFI_LOCK *Lock)
EFI_STATUS EFIAPI EfiCreateEventReadyToBootEx(IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, IN VOID *NotifyContext OPTIONAL, OUT EFI_EVENT *ReadyToBootEvent)
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
#define EFI_VARIABLE_NON_VOLATILE
EFI_BOOT_KEY_DATA KeyData
EFI_HANDLE ConsoleInHandle