]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
Add BootlogoOnly feature in BDS for BGRT
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / Hotkey.c
1 /** @file
2 Provides a way for 3rd party applications to register themselves for launch by the
3 Boot Manager based on hot key
4
5 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Hotkey.h"
17
18
19 LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);
20 BDS_COMMON_OPTION *mHotkeyBootOption = NULL;
21 EFI_EVENT mHotkeyEvent;
22 VOID *mHotkeyRegistration;
23
24
25 /**
26 Check if the Key Option is valid or not.
27
28 @param KeyOption The Hot Key Option to be checked.
29
30 @retval TRUE The Hot Key Option is valid.
31 @retval FALSE The Hot Key Option is invalid.
32
33 **/
34 BOOLEAN
35 IsKeyOptionValid (
36 IN EFI_KEY_OPTION *KeyOption
37 )
38 {
39 UINT16 BootOptionName[10];
40 UINT8 *BootOptionVar;
41 UINTN BootOptionSize;
42 UINT32 Crc;
43
44 //
45 // Check whether corresponding Boot Option exist
46 //
47 UnicodeSPrint (BootOptionName, sizeof (BootOptionName), L"Boot%04x", KeyOption->BootOption);
48 BootOptionVar = BdsLibGetVariableAndSize (
49 BootOptionName,
50 &gEfiGlobalVariableGuid,
51 &BootOptionSize
52 );
53
54 if (BootOptionVar == NULL || BootOptionSize == 0) {
55 return FALSE;
56 }
57
58 //
59 // Check CRC for Boot Option
60 //
61 gBS->CalculateCrc32 (BootOptionVar, BootOptionSize, &Crc);
62 FreePool (BootOptionVar);
63
64 return (BOOLEAN) ((KeyOption->BootOptionCrc == Crc) ? TRUE : FALSE);
65 }
66
67 /**
68 Create Key#### for the given hotkey.
69
70 @param KeyOption The Hot Key Option to be added.
71 @param KeyOptionNumber The key option number for Key#### (optional).
72
73 @retval EFI_SUCCESS Register hotkey successfully.
74 @retval EFI_INVALID_PARAMETER The hotkey option is invalid.
75 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
76
77 **/
78 EFI_STATUS
79 RegisterHotkey (
80 IN EFI_KEY_OPTION *KeyOption,
81 OUT UINT16 *KeyOptionNumber
82 )
83 {
84 UINT16 KeyOptionName[10];
85 UINT16 *KeyOrder;
86 UINTN KeyOrderSize;
87 UINT16 *NewKeyOrder;
88 UINTN Index;
89 UINT16 MaxOptionNumber;
90 UINT16 RegisterOptionNumber;
91 EFI_KEY_OPTION *TempOption;
92 UINTN TempOptionSize;
93 EFI_STATUS Status;
94 UINTN KeyOptionSize;
95 BOOLEAN UpdateBootOption;
96
97 //
98 // Validate the given key option
99 //
100 if (!IsKeyOptionValid (KeyOption)) {
101 return EFI_INVALID_PARAMETER;
102 }
103
104 KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);
105 UpdateBootOption = FALSE;
106
107 //
108 // Check whether HotKey conflict with keys used by Setup Browser
109 //
110 KeyOrder = BdsLibGetVariableAndSize (
111 VAR_KEY_ORDER,
112 &gEfiGlobalVariableGuid,
113 &KeyOrderSize
114 );
115 if (KeyOrder == NULL) {
116 KeyOrderSize = 0;
117 }
118
119 //
120 // Find free key option number
121 //
122 MaxOptionNumber = 0;
123 TempOption = NULL;
124 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
125 if (MaxOptionNumber < KeyOrder[Index]) {
126 MaxOptionNumber = KeyOrder[Index];
127 }
128
129 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
130 TempOption = BdsLibGetVariableAndSize (
131 KeyOptionName,
132 &gEfiGlobalVariableGuid,
133 &TempOptionSize
134 );
135 ASSERT (TempOption != NULL);
136
137 if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {
138 //
139 // Got the option, so just return
140 //
141 FreePool (TempOption);
142 FreePool (KeyOrder);
143 return EFI_SUCCESS;
144 }
145
146 if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {
147 if (KeyOption->KeyData.Options.InputKeyCount == 0 ||
148 CompareMem (
149 ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),
150 ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),
151 KeyOptionSize - sizeof (EFI_KEY_OPTION)
152 ) == 0) {
153 //
154 // Hotkey is the same but BootOption changed, need update
155 //
156 UpdateBootOption = TRUE;
157 break;
158 }
159 }
160
161 FreePool (TempOption);
162 }
163
164 if (UpdateBootOption) {
165 RegisterOptionNumber = KeyOrder[Index];
166 FreePool (TempOption);
167 } else {
168 RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);
169 }
170
171 if (KeyOptionNumber != NULL) {
172 *KeyOptionNumber = RegisterOptionNumber;
173 }
174
175 //
176 // Create variable Key####
177 //
178 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);
179 Status = gRT->SetVariable (
180 KeyOptionName,
181 &gEfiGlobalVariableGuid,
182 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
183 KeyOptionSize,
184 KeyOption
185 );
186 if (EFI_ERROR (Status)) {
187 FreePool (KeyOrder);
188 return Status;
189 }
190
191 //
192 // Update the key order variable - "KeyOrder"
193 //
194 if (!UpdateBootOption) {
195 Index = KeyOrderSize / sizeof (UINT16);
196 KeyOrderSize += sizeof (UINT16);
197 }
198
199 NewKeyOrder = AllocatePool (KeyOrderSize);
200 if (NewKeyOrder == NULL) {
201 FreePool (KeyOrder);
202 return EFI_OUT_OF_RESOURCES;
203 }
204
205 if (KeyOrder != NULL) {
206 CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);
207 }
208
209 NewKeyOrder[Index] = RegisterOptionNumber;
210
211 Status = gRT->SetVariable (
212 VAR_KEY_ORDER,
213 &gEfiGlobalVariableGuid,
214 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
215 KeyOrderSize,
216 NewKeyOrder
217 );
218
219 FreePool (KeyOrder);
220 FreePool (NewKeyOrder);
221
222 return Status;
223 }
224
225 /**
226
227 Delete Key#### for the given Key Option number.
228
229 @param KeyOptionNumber Key option number for Key####
230
231 @retval EFI_SUCCESS Unregister hotkey successfully.
232 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.
233
234 **/
235 EFI_STATUS
236 UnregisterHotkey (
237 IN UINT16 KeyOptionNumber
238 )
239 {
240 UINT16 KeyOption[10];
241 UINTN Index;
242 EFI_STATUS Status;
243 UINTN Index2Del;
244 UINT16 *KeyOrder;
245 UINTN KeyOrderSize;
246
247 //
248 // Delete variable Key####
249 //
250 UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);
251 gRT->SetVariable (
252 KeyOption,
253 &gEfiGlobalVariableGuid,
254 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
255 0,
256 NULL
257 );
258
259 //
260 // Adjust key order array
261 //
262 KeyOrder = BdsLibGetVariableAndSize (
263 VAR_KEY_ORDER,
264 &gEfiGlobalVariableGuid,
265 &KeyOrderSize
266 );
267 if (KeyOrder == NULL) {
268 return EFI_SUCCESS;
269 }
270
271 Index2Del = 0;
272 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
273 if (KeyOrder[Index] == KeyOptionNumber) {
274 Index2Del = Index;
275 break;
276 }
277 }
278
279 if (Index != KeyOrderSize / sizeof (UINT16)) {
280 //
281 // KeyOptionNumber found in "KeyOrder", delete it
282 //
283 for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {
284 KeyOrder[Index] = KeyOrder[Index + 1];
285 }
286
287 KeyOrderSize -= sizeof (UINT16);
288 }
289
290 Status = gRT->SetVariable (
291 VAR_KEY_ORDER,
292 &gEfiGlobalVariableGuid,
293 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
294 KeyOrderSize,
295 KeyOrder
296 );
297
298 FreePool (KeyOrder);
299
300 return Status;
301 }
302
303 /**
304 Try to boot the boot option triggered by hotkey.
305 @retval EFI_SUCCESS There is HotkeyBootOption & it is processed
306 @retval EFI_NOT_FOUND There is no HotkeyBootOption
307 **/
308 EFI_STATUS
309 HotkeyBoot (
310 VOID
311 )
312 {
313 EFI_STATUS Status;
314 UINTN ExitDataSize;
315 CHAR16 *ExitData;
316
317 if (mHotkeyBootOption == NULL) {
318 return EFI_NOT_FOUND;
319 }
320
321 BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);
322
323 //
324 // Clear the screen before launch this BootOption
325 //
326 gST->ConOut->Reset (gST->ConOut, FALSE);
327
328 Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);
329
330 if (EFI_ERROR (Status)) {
331 //
332 // Call platform action to indicate the boot fail
333 //
334 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
335 PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);
336 } else {
337 //
338 // Call platform action to indicate the boot success
339 //
340 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
341 PlatformBdsBootSuccess (mHotkeyBootOption);
342 }
343 FreePool (mHotkeyBootOption->Description);
344 FreePool (mHotkeyBootOption->DevicePath);
345 FreePool (mHotkeyBootOption->LoadOptions);
346 FreePool (mHotkeyBootOption);
347
348 mHotkeyBootOption = NULL;
349
350 return EFI_SUCCESS;
351 }
352
353 /**
354
355 This is the common notification function for HotKeys, it will be registered
356 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
357
358 @param KeyData A pointer to a buffer that is filled in with the keystroke
359 information for the key that was pressed.
360
361 @retval EFI_SUCCESS KeyData is successfully processed.
362 @return EFI_NOT_FOUND Fail to find boot option variable.
363 **/
364 EFI_STATUS
365 EFIAPI
366 HotkeyCallback (
367 IN EFI_KEY_DATA *KeyData
368 )
369 {
370 BOOLEAN HotkeyCatched;
371 LIST_ENTRY BootLists;
372 LIST_ENTRY *Link;
373 BDS_HOTKEY_OPTION *Hotkey;
374 UINT16 Buffer[10];
375 EFI_STATUS Status;
376 EFI_KEY_DATA *HotkeyData;
377
378 if (mHotkeyBootOption != NULL) {
379 //
380 // Do not process sequential hotkey stroke until the current boot option returns
381 //
382 return EFI_SUCCESS;
383 }
384
385 Status = EFI_SUCCESS;
386
387 for ( Link = GetFirstNode (&mHotkeyList)
388 ; !IsNull (&mHotkeyList, Link)
389 ; Link = GetNextNode (&mHotkeyList, Link)
390 ) {
391 HotkeyCatched = FALSE;
392 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
393
394 //
395 // Is this Key Stroke we are waiting for?
396 //
397 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
398 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
399 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
400 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
401 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ?
402 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE
403 )
404 ) {
405 //
406 // For hotkey of key combination, transit to next waiting state
407 //
408 Hotkey->WaitingKey++;
409
410 if (Hotkey->WaitingKey == Hotkey->CodeCount) {
411 //
412 // Received the whole key stroke sequence
413 //
414 HotkeyCatched = TRUE;
415 }
416 } else {
417 //
418 // Receive an unexpected key stroke, reset to initial waiting state
419 //
420 Hotkey->WaitingKey = 0;
421 }
422
423 if (HotkeyCatched) {
424 //
425 // Reset to initial waiting state
426 //
427 Hotkey->WaitingKey = 0;
428
429 //
430 // Launch its BootOption
431 //
432 InitializeListHead (&BootLists);
433
434 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
435 mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);
436 }
437 }
438
439 return Status;
440 }
441
442 /**
443 Register the common HotKey notify function to given SimpleTextInEx protocol instance.
444
445 @param SimpleTextInEx Simple Text Input Ex protocol instance
446
447 @retval EFI_SUCCESS Register hotkey notification function successfully.
448 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.
449
450 **/
451 EFI_STATUS
452 HotkeyRegisterNotify (
453 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
454 )
455 {
456 UINTN Index;
457 EFI_STATUS Status;
458 LIST_ENTRY *Link;
459 BDS_HOTKEY_OPTION *Hotkey;
460
461 //
462 // Register notification function for each hotkey
463 //
464 Link = GetFirstNode (&mHotkeyList);
465
466 while (!IsNull (&mHotkeyList, Link)) {
467 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
468
469 Index = 0;
470 do {
471 Status = SimpleTextInEx->RegisterKeyNotify (
472 SimpleTextInEx,
473 &Hotkey->KeyData[Index],
474 HotkeyCallback,
475 &Hotkey->NotifyHandle
476 );
477 if (EFI_ERROR (Status)) {
478 //
479 // some of the hotkey registry failed
480 //
481 return Status;
482 }
483 Index ++;
484 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));
485
486 Link = GetNextNode (&mHotkeyList, Link);
487 }
488
489 return EFI_SUCCESS;
490 }
491
492 /**
493 Callback function for SimpleTextInEx protocol install events
494
495 @param Event the event that is signaled.
496 @param Context not used here.
497
498 **/
499 VOID
500 EFIAPI
501 HotkeyEvent (
502 IN EFI_EVENT Event,
503 IN VOID *Context
504 )
505 {
506 EFI_STATUS Status;
507 UINTN BufferSize;
508 EFI_HANDLE Handle;
509 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
510
511 while (TRUE) {
512 BufferSize = sizeof (EFI_HANDLE);
513 Status = gBS->LocateHandle (
514 ByRegisterNotify,
515 NULL,
516 mHotkeyRegistration,
517 &BufferSize,
518 &Handle
519 );
520 if (EFI_ERROR (Status)) {
521 //
522 // If no more notification events exist
523 //
524 return ;
525 }
526
527 Status = gBS->HandleProtocol (
528 Handle,
529 &gEfiSimpleTextInputExProtocolGuid,
530 (VOID **) &SimpleTextInEx
531 );
532 ASSERT_EFI_ERROR (Status);
533
534 HotkeyRegisterNotify (SimpleTextInEx);
535 }
536 }
537
538 /**
539 Insert Key Option to hotkey list.
540
541 @param KeyOption The Hot Key Option to be added to hotkey list.
542
543 @retval EFI_SUCCESS Add to hotkey list success.
544 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
545 **/
546 EFI_STATUS
547 HotkeyInsertList (
548 IN EFI_KEY_OPTION *KeyOption
549 )
550 {
551 BDS_HOTKEY_OPTION *HotkeyLeft;
552 BDS_HOTKEY_OPTION *HotkeyRight;
553 UINTN Index;
554 EFI_BOOT_KEY_DATA KeyOptions;
555 UINT32 KeyShiftStateLeft;
556 UINT32 KeyShiftStateRight;
557 EFI_INPUT_KEY *InputKey;
558 EFI_KEY_DATA *KeyData;
559
560 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));
561 if (HotkeyLeft == NULL) {
562 return EFI_OUT_OF_RESOURCES;
563 }
564
565 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;
566 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;
567
568 KeyOptions = KeyOption->KeyData;
569
570 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;
571
572 //
573 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState
574 //
575 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;
576 if (KeyOptions.Options.ShiftPressed) {
577 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;
578 }
579 if (KeyOptions.Options.ControlPressed) {
580 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;
581 }
582 if (KeyOptions.Options.AltPressed) {
583 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;
584 }
585 if (KeyOptions.Options.LogoPressed) {
586 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;
587 }
588 if (KeyOptions.Options.MenuPressed) {
589 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;
590 }
591 if (KeyOptions.Options.SysReqPressed) {
592 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;
593 }
594
595
596 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);
597
598 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));
599
600 Index = 0;
601 KeyData = &HotkeyLeft->KeyData[0];
602 do {
603 //
604 // If Key CodeCount is 0, then only KeyData[0] is used;
605 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used
606 //
607 KeyData->Key.ScanCode = InputKey[Index].ScanCode;
608 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;
609 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;
610
611 Index++;
612 KeyData++;
613 } while (Index < HotkeyLeft->CodeCount);
614 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);
615
616 if (KeyShiftStateLeft != KeyShiftStateRight) {
617 //
618 // Need an extra hotkey for shift key on right
619 //
620 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);
621 if (HotkeyRight == NULL) {
622 return EFI_OUT_OF_RESOURCES;
623 }
624
625 Index = 0;
626 KeyData = &HotkeyRight->KeyData[0];
627 do {
628 //
629 // Key.ScanCode and Key.UnicodeChar have already been initialized,
630 // only need to update KeyState.KeyShiftState
631 //
632 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;
633
634 Index++;
635 KeyData++;
636 } while (Index < HotkeyRight->CodeCount);
637 InsertTailList (&mHotkeyList, &HotkeyRight->Link);
638 }
639
640 return EFI_SUCCESS;
641 }
642
643 /**
644
645 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
646
647 @retval EFI_SUCCESS Hotkey services successfully initialized.
648 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable
649 **/
650 EFI_STATUS
651 InitializeHotkeyService (
652 VOID
653 )
654 {
655 EFI_STATUS Status;
656 UINT32 BootOptionSupport;
657 UINT16 *KeyOrder;
658 UINTN KeyOrderSize;
659 UINTN Index;
660 UINT16 KeyOptionName[8];
661 UINTN KeyOptionSize;
662 EFI_KEY_OPTION *KeyOption;
663
664 //
665 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
666 // with maximum number of key presses of 3
667 //
668 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
669 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
670 Status = gRT->SetVariable (
671 L"BootOptionSupport",
672 &gEfiGlobalVariableGuid,
673 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
674 sizeof (UINT32),
675 &BootOptionSupport
676 );
677
678 //
679 // Get valid Key Option List from private EFI variable "KeyOrder"
680 //
681 KeyOrder = BdsLibGetVariableAndSize (
682 VAR_KEY_ORDER,
683 &gEfiGlobalVariableGuid,
684 &KeyOrderSize
685 );
686
687 if (KeyOrder == NULL) {
688 return EFI_NOT_FOUND;
689 }
690
691 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
692 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
693 KeyOption = BdsLibGetVariableAndSize (
694 KeyOptionName,
695 &gEfiGlobalVariableGuid,
696 &KeyOptionSize
697 );
698
699 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
700 UnregisterHotkey (KeyOrder[Index]);
701 } else {
702 HotkeyInsertList (KeyOption);
703 }
704 }
705
706 //
707 // Register Protocol notify for Hotkey service
708 //
709 Status = gBS->CreateEvent (
710 EVT_NOTIFY_SIGNAL,
711 TPL_CALLBACK,
712 HotkeyEvent,
713 NULL,
714 &mHotkeyEvent
715 );
716 ASSERT_EFI_ERROR (Status);
717
718 //
719 // Register for protocol notifications on this event
720 //
721 Status = gBS->RegisterProtocolNotify (
722 &gEfiSimpleTextInputExProtocolGuid,
723 mHotkeyEvent,
724 &mHotkeyRegistration
725 );
726 ASSERT_EFI_ERROR (Status);
727
728 return Status;
729 }
730