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