]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
d0d9bb077bfb2b6e14d999abb35ca86a7576388a
[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 - 2011, 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 **/
306 VOID
307 HotkeyBoot (
308 VOID
309 )
310 {
311 EFI_STATUS Status;
312 UINTN ExitDataSize;
313 CHAR16 *ExitData;
314
315 if (mHotkeyBootOption != NULL) {
316 BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);
317
318 //
319 // Clear the screen before launch this BootOption
320 //
321 gST->ConOut->Reset (gST->ConOut, FALSE);
322
323 Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);
324
325 if (EFI_ERROR (Status)) {
326 //
327 // Call platform action to indicate the boot fail
328 //
329 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
330 PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);
331 } else {
332 //
333 // Call platform action to indicate the boot success
334 //
335 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
336 PlatformBdsBootSuccess (mHotkeyBootOption);
337 }
338 FreePool (mHotkeyBootOption->Description);
339 FreePool (mHotkeyBootOption->DevicePath);
340 FreePool (mHotkeyBootOption->LoadOptions);
341 FreePool (mHotkeyBootOption);
342
343 mHotkeyBootOption = NULL;
344 }
345 }
346
347 /**
348
349 This is the common notification function for HotKeys, it will be registered
350 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
351
352 @param KeyData A pointer to a buffer that is filled in with the keystroke
353 information for the key that was pressed.
354
355 @retval EFI_SUCCESS KeyData is successfully processed.
356 @return EFI_NOT_FOUND Fail to find boot option variable.
357 **/
358 EFI_STATUS
359 EFIAPI
360 HotkeyCallback (
361 IN EFI_KEY_DATA *KeyData
362 )
363 {
364 BOOLEAN HotkeyCatched;
365 LIST_ENTRY BootLists;
366 LIST_ENTRY *Link;
367 BDS_HOTKEY_OPTION *Hotkey;
368 UINT16 Buffer[10];
369 EFI_STATUS Status;
370 EFI_KEY_DATA *HotkeyData;
371
372 if (mHotkeyBootOption != NULL) {
373 //
374 // Do not process sequential hotkey stroke until the current boot option returns
375 //
376 return EFI_SUCCESS;
377 }
378
379 Status = EFI_SUCCESS;
380
381 for ( Link = GetFirstNode (&mHotkeyList)
382 ; !IsNull (&mHotkeyList, Link)
383 ; Link = GetNextNode (&mHotkeyList, Link)
384 ) {
385 HotkeyCatched = FALSE;
386 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
387
388 //
389 // Is this Key Stroke we are waiting for?
390 //
391 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
392 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
393 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
394 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
395 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ?
396 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE
397 )
398 ) {
399 //
400 // For hotkey of key combination, transit to next waiting state
401 //
402 Hotkey->WaitingKey++;
403
404 if (Hotkey->WaitingKey == Hotkey->CodeCount) {
405 //
406 // Received the whole key stroke sequence
407 //
408 HotkeyCatched = TRUE;
409 }
410 } else {
411 //
412 // Receive an unexpected key stroke, reset to initial waiting state
413 //
414 Hotkey->WaitingKey = 0;
415 }
416
417 if (HotkeyCatched) {
418 //
419 // Reset to initial waiting state
420 //
421 Hotkey->WaitingKey = 0;
422
423 //
424 // Launch its BootOption
425 //
426 InitializeListHead (&BootLists);
427
428 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
429 mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);
430 }
431 }
432
433 return Status;
434 }
435
436 /**
437 Register the common HotKey notify function to given SimpleTextInEx protocol instance.
438
439 @param SimpleTextInEx Simple Text Input Ex protocol instance
440
441 @retval EFI_SUCCESS Register hotkey notification function successfully.
442 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.
443
444 **/
445 EFI_STATUS
446 HotkeyRegisterNotify (
447 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
448 )
449 {
450 UINTN Index;
451 EFI_STATUS Status;
452 LIST_ENTRY *Link;
453 BDS_HOTKEY_OPTION *Hotkey;
454
455 //
456 // Register notification function for each hotkey
457 //
458 Link = GetFirstNode (&mHotkeyList);
459
460 while (!IsNull (&mHotkeyList, Link)) {
461 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
462
463 Index = 0;
464 do {
465 Status = SimpleTextInEx->RegisterKeyNotify (
466 SimpleTextInEx,
467 &Hotkey->KeyData[Index],
468 HotkeyCallback,
469 &Hotkey->NotifyHandle
470 );
471 if (EFI_ERROR (Status)) {
472 //
473 // some of the hotkey registry failed
474 //
475 return Status;
476 }
477 Index ++;
478 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));
479
480 Link = GetNextNode (&mHotkeyList, Link);
481 }
482
483 return EFI_SUCCESS;
484 }
485
486 /**
487 Callback function for SimpleTextInEx protocol install events
488
489 @param Event the event that is signaled.
490 @param Context not used here.
491
492 **/
493 VOID
494 EFIAPI
495 HotkeyEvent (
496 IN EFI_EVENT Event,
497 IN VOID *Context
498 )
499 {
500 EFI_STATUS Status;
501 UINTN BufferSize;
502 EFI_HANDLE Handle;
503 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
504
505 while (TRUE) {
506 BufferSize = sizeof (EFI_HANDLE);
507 Status = gBS->LocateHandle (
508 ByRegisterNotify,
509 NULL,
510 mHotkeyRegistration,
511 &BufferSize,
512 &Handle
513 );
514 if (EFI_ERROR (Status)) {
515 //
516 // If no more notification events exist
517 //
518 return ;
519 }
520
521 Status = gBS->HandleProtocol (
522 Handle,
523 &gEfiSimpleTextInputExProtocolGuid,
524 (VOID **) &SimpleTextInEx
525 );
526 ASSERT_EFI_ERROR (Status);
527
528 HotkeyRegisterNotify (SimpleTextInEx);
529 }
530 }
531
532 /**
533 Insert Key Option to hotkey list.
534
535 @param KeyOption The Hot Key Option to be added to hotkey list.
536
537 @retval EFI_SUCCESS Add to hotkey list success.
538 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
539 **/
540 EFI_STATUS
541 HotkeyInsertList (
542 IN EFI_KEY_OPTION *KeyOption
543 )
544 {
545 BDS_HOTKEY_OPTION *HotkeyLeft;
546 BDS_HOTKEY_OPTION *HotkeyRight;
547 UINTN Index;
548 EFI_BOOT_KEY_DATA KeyOptions;
549 UINT32 KeyShiftStateLeft;
550 UINT32 KeyShiftStateRight;
551 EFI_INPUT_KEY *InputKey;
552 EFI_KEY_DATA *KeyData;
553
554 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));
555 if (HotkeyLeft == NULL) {
556 return EFI_OUT_OF_RESOURCES;
557 }
558
559 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;
560 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;
561
562 KeyOptions = KeyOption->KeyData;
563
564 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;
565
566 //
567 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState
568 //
569 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;
570 if (KeyOptions.Options.ShiftPressed) {
571 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;
572 }
573 if (KeyOptions.Options.ControlPressed) {
574 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;
575 }
576 if (KeyOptions.Options.AltPressed) {
577 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;
578 }
579 if (KeyOptions.Options.LogoPressed) {
580 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;
581 }
582 if (KeyOptions.Options.MenuPressed) {
583 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;
584 }
585 if (KeyOptions.Options.SysReqPressed) {
586 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;
587 }
588
589
590 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);
591
592 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));
593
594 Index = 0;
595 KeyData = &HotkeyLeft->KeyData[0];
596 do {
597 //
598 // If Key CodeCount is 0, then only KeyData[0] is used;
599 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used
600 //
601 KeyData->Key.ScanCode = InputKey[Index].ScanCode;
602 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;
603 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;
604
605 Index++;
606 KeyData++;
607 } while (Index < HotkeyLeft->CodeCount);
608 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);
609
610 if (KeyShiftStateLeft != KeyShiftStateRight) {
611 //
612 // Need an extra hotkey for shift key on right
613 //
614 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);
615 if (HotkeyRight == NULL) {
616 return EFI_OUT_OF_RESOURCES;
617 }
618
619 Index = 0;
620 KeyData = &HotkeyRight->KeyData[0];
621 do {
622 //
623 // Key.ScanCode and Key.UnicodeChar have already been initialized,
624 // only need to update KeyState.KeyShiftState
625 //
626 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;
627
628 Index++;
629 KeyData++;
630 } while (Index < HotkeyRight->CodeCount);
631 InsertTailList (&mHotkeyList, &HotkeyRight->Link);
632 }
633
634 return EFI_SUCCESS;
635 }
636
637 /**
638
639 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
640
641 @retval EFI_SUCCESS Hotkey services successfully initialized.
642 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable
643 **/
644 EFI_STATUS
645 InitializeHotkeyService (
646 VOID
647 )
648 {
649 EFI_STATUS Status;
650 UINT32 BootOptionSupport;
651 UINT16 *KeyOrder;
652 UINTN KeyOrderSize;
653 UINTN Index;
654 UINT16 KeyOptionName[8];
655 UINTN KeyOptionSize;
656 EFI_KEY_OPTION *KeyOption;
657
658 //
659 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
660 // with maximum number of key presses of 3
661 //
662 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
663 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
664 Status = gRT->SetVariable (
665 L"BootOptionSupport",
666 &gEfiGlobalVariableGuid,
667 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
668 sizeof (UINT32),
669 &BootOptionSupport
670 );
671
672 //
673 // Get valid Key Option List from private EFI variable "KeyOrder"
674 //
675 KeyOrder = BdsLibGetVariableAndSize (
676 VAR_KEY_ORDER,
677 &gEfiGlobalVariableGuid,
678 &KeyOrderSize
679 );
680
681 if (KeyOrder == NULL) {
682 return EFI_NOT_FOUND;
683 }
684
685 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
686 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
687 KeyOption = BdsLibGetVariableAndSize (
688 KeyOptionName,
689 &gEfiGlobalVariableGuid,
690 &KeyOptionSize
691 );
692
693 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
694 UnregisterHotkey (KeyOrder[Index]);
695 } else {
696 HotkeyInsertList (KeyOption);
697 }
698 }
699
700 //
701 // Register Protocol notify for Hotkey service
702 //
703 Status = gBS->CreateEvent (
704 EVT_NOTIFY_SIGNAL,
705 TPL_CALLBACK,
706 HotkeyEvent,
707 NULL,
708 &mHotkeyEvent
709 );
710 ASSERT_EFI_ERROR (Status);
711
712 //
713 // Register for protocol notifications on this event
714 //
715 Status = gBS->RegisterProtocolNotify (
716 &gEfiSimpleTextInputExProtocolGuid,
717 mHotkeyEvent,
718 &mHotkeyRegistration
719 );
720 ASSERT_EFI_ERROR (Status);
721
722 return Status;
723 }
724