]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
72139a8b4da668fd2bfd91bc1ac3a3d1b40df55e
[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 - 2008, Intel Corporation. <BR>
6 All rights reserved. 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
136 if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {
137 //
138 // Got the option, so just return
139 //
140 FreePool (TempOption);
141 FreePool (KeyOrder);
142 return EFI_SUCCESS;
143 }
144
145 if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {
146 if (KeyOption->KeyData.Options.InputKeyCount == 0 ||
147 CompareMem (
148 ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),
149 ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),
150 KeyOptionSize - sizeof (EFI_KEY_OPTION)
151 ) == 0) {
152 //
153 // Hotkey is the same but BootOption changed, need update
154 //
155 UpdateBootOption = TRUE;
156 break;
157 }
158 }
159
160 FreePool (TempOption);
161 }
162
163 if (UpdateBootOption) {
164 RegisterOptionNumber = KeyOrder[Index];
165 FreePool (TempOption);
166 } else {
167 RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);
168 }
169
170 if (KeyOptionNumber != NULL) {
171 *KeyOptionNumber = RegisterOptionNumber;
172 }
173
174 //
175 // Create variable Key####
176 //
177 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);
178 Status = gRT->SetVariable (
179 KeyOptionName,
180 &gEfiGlobalVariableGuid,
181 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
182 KeyOptionSize,
183 KeyOption
184 );
185 if (EFI_ERROR (Status)) {
186 FreePool (KeyOrder);
187 return Status;
188 }
189
190 //
191 // Update the key order variable - "KeyOrder"
192 //
193 if (!UpdateBootOption) {
194 Index = KeyOrderSize / sizeof (UINT16);
195 KeyOrderSize += sizeof (UINT16);
196 }
197
198 NewKeyOrder = AllocatePool (KeyOrderSize);
199 if (NewKeyOrder == NULL) {
200 FreePool (KeyOrder);
201 return EFI_OUT_OF_RESOURCES;
202 }
203
204 if (KeyOrder != NULL) {
205 CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);
206 }
207
208 NewKeyOrder[Index] = RegisterOptionNumber;
209
210 Status = gRT->SetVariable (
211 VAR_KEY_ORDER,
212 &gEfiGlobalVariableGuid,
213 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
214 KeyOrderSize,
215 NewKeyOrder
216 );
217
218 FreePool (KeyOrder);
219 FreePool (NewKeyOrder);
220
221 return Status;
222 }
223
224 /**
225
226 Delete Key#### for the given Key Option number.
227
228 @param KeyOptionNumber Key option number for Key####
229
230 @retval EFI_SUCCESS Unregister hotkey successfully.
231 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.
232
233 **/
234 EFI_STATUS
235 UnregisterHotkey (
236 IN UINT16 KeyOptionNumber
237 )
238 {
239 UINT16 KeyOption[10];
240 UINTN Index;
241 EFI_STATUS Status;
242 UINTN Index2Del;
243 UINT16 *KeyOrder;
244 UINTN KeyOrderSize;
245
246 //
247 // Delete variable Key####
248 //
249 UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);
250 gRT->SetVariable (
251 KeyOption,
252 &gEfiGlobalVariableGuid,
253 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
254 0,
255 NULL
256 );
257
258 //
259 // Adjust key order array
260 //
261 KeyOrder = BdsLibGetVariableAndSize (
262 VAR_KEY_ORDER,
263 &gEfiGlobalVariableGuid,
264 &KeyOrderSize
265 );
266 if (KeyOrder == NULL) {
267 return EFI_SUCCESS;
268 }
269
270 Index2Del = 0;
271 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {
272 if (KeyOrder[Index] == KeyOptionNumber) {
273 Index2Del = Index;
274 break;
275 }
276 }
277
278 if (Index != KeyOrderSize / sizeof (UINT16)) {
279 //
280 // KeyOptionNumber found in "KeyOrder", delete it
281 //
282 for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {
283 KeyOrder[Index] = KeyOrder[Index + 1];
284 }
285
286 KeyOrderSize -= sizeof (UINT16);
287 }
288
289 Status = gRT->SetVariable (
290 VAR_KEY_ORDER,
291 &gEfiGlobalVariableGuid,
292 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
293 KeyOrderSize,
294 KeyOrder
295 );
296
297 FreePool (KeyOrder);
298
299 return Status;
300 }
301
302 /**
303
304 This is the common notification function for HotKeys, it will be registered
305 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.
306
307 @param KeyData A pointer to a buffer that is filled in with the keystroke
308 information for the key that was pressed.
309
310 @retval EFI_SUCCESS KeyData is successfully processed.
311 @return EFI_NOT_FOUND Fail to find boot option variable.
312 **/
313 EFI_STATUS
314 EFIAPI
315 HotkeyCallback (
316 IN EFI_KEY_DATA *KeyData
317 )
318 {
319 BOOLEAN HotkeyCatched;
320 LIST_ENTRY BootLists;
321 LIST_ENTRY *Link;
322 BDS_HOTKEY_OPTION *Hotkey;
323 UINT16 Buffer[10];
324 BDS_COMMON_OPTION *BootOption;
325 UINTN ExitDataSize;
326 CHAR16 *ExitData;
327 EFI_STATUS Status;
328 EFI_KEY_DATA *HotkeyData;
329
330 if (mHotkeyCallbackPending) {
331 //
332 // When responsing to a Hotkey, ignore sequential hotkey stroke until
333 // the current Boot#### load option returned
334 //
335 return EFI_SUCCESS;
336 }
337
338 Status = EFI_SUCCESS;
339 Link = GetFirstNode (&mHotkeyList);
340
341 while (!IsNull (&mHotkeyList, Link)) {
342 HotkeyCatched = FALSE;
343 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
344
345 //
346 // Is this Key Stroke we are waiting for?
347 //
348 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));
349 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];
350 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&
351 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&
352 ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) {
353 //
354 // Receive an expecting key stroke
355 //
356 if (Hotkey->CodeCount > 1) {
357 //
358 // For hotkey of key combination, transit to next waiting state
359 //
360 Hotkey->WaitingKey++;
361
362 if (Hotkey->WaitingKey == Hotkey->CodeCount) {
363 //
364 // Received the whole key stroke sequence
365 //
366 HotkeyCatched = TRUE;
367 }
368 } else {
369 //
370 // For hotkey of single key stroke
371 //
372 HotkeyCatched = TRUE;
373 }
374 } else {
375 //
376 // Receive an unexpected key stroke, reset to initial waiting state
377 //
378 Hotkey->WaitingKey = 0;
379 }
380
381 if (HotkeyCatched) {
382 //
383 // Reset to initial waiting state
384 //
385 Hotkey->WaitingKey = 0;
386
387 //
388 // Launch its BootOption
389 //
390 InitializeListHead (&BootLists);
391
392 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);
393 BootOption = BdsLibVariableToOption (&BootLists, Buffer);
394 if (BootOption == NULL) {
395 return EFI_NOT_FOUND;
396 }
397 BootOption->BootCurrent = Hotkey->BootOptionNumber;
398 BdsLibConnectDevicePath (BootOption->DevicePath);
399
400 //
401 // Clear the screen before launch this BootOption
402 //
403 gST->ConOut->Reset (gST->ConOut, FALSE);
404
405 mHotkeyCallbackPending = TRUE;
406 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);
407 mHotkeyCallbackPending = FALSE;
408
409 if (EFI_ERROR (Status)) {
410 //
411 // Call platform action to indicate the boot fail
412 //
413 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));
414 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);
415 } else {
416 //
417 // Call platform action to indicate the boot success
418 //
419 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));
420 PlatformBdsBootSuccess (BootOption);
421 }
422 }
423
424 Link = GetNextNode (&mHotkeyList, Link);
425 }
426
427 return Status;
428 }
429
430 /**
431 Register the common HotKey notify function to given SimpleTextInEx protocol instance.
432
433 @param SimpleTextInEx Simple Text Input Ex protocol instance
434
435 @retval EFI_SUCCESS Register hotkey notification function successfully.
436 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.
437
438 **/
439 EFI_STATUS
440 HotkeyRegisterNotify (
441 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx
442 )
443 {
444 UINTN Index;
445 EFI_STATUS Status;
446 LIST_ENTRY *Link;
447 BDS_HOTKEY_OPTION *Hotkey;
448
449 //
450 // Register notification function for each hotkey
451 //
452 Link = GetFirstNode (&mHotkeyList);
453
454 while (!IsNull (&mHotkeyList, Link)) {
455 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);
456
457 Index = 0;
458 do {
459 Status = SimpleTextInEx->RegisterKeyNotify (
460 SimpleTextInEx,
461 &Hotkey->KeyData[Index],
462 HotkeyCallback,
463 &Hotkey->NotifyHandle
464 );
465 if (EFI_ERROR (Status)) {
466 //
467 // some of the hotkey registry failed
468 //
469 return Status;
470 }
471 Index ++;
472 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));
473
474 Link = GetNextNode (&mHotkeyList, Link);
475 }
476
477 return EFI_SUCCESS;
478 }
479
480 /**
481 Callback function for SimpleTextInEx protocol install events
482
483 @param Event the event that is signaled.
484 @param Context not used here.
485
486 **/
487 VOID
488 EFIAPI
489 HotkeyEvent (
490 IN EFI_EVENT Event,
491 IN VOID *Context
492 )
493 {
494 EFI_STATUS Status;
495 UINTN BufferSize;
496 EFI_HANDLE Handle;
497 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
498
499 while (TRUE) {
500 BufferSize = sizeof (EFI_HANDLE);
501 Status = gBS->LocateHandle (
502 ByRegisterNotify,
503 NULL,
504 mHotkeyRegistration,
505 &BufferSize,
506 &Handle
507 );
508 if (EFI_ERROR (Status)) {
509 //
510 // If no more notification events exist
511 //
512 return ;
513 }
514
515 Status = gBS->HandleProtocol (
516 Handle,
517 &gEfiSimpleTextInputExProtocolGuid,
518 (VOID **) &SimpleTextInEx
519 );
520 ASSERT_EFI_ERROR (Status);
521
522 HotkeyRegisterNotify (SimpleTextInEx);
523 }
524 }
525
526 /**
527 Insert Key Option to hotkey list.
528
529 @param KeyOption The Hot Key Option to be added to hotkey list.
530
531 @retval EFI_SUCCESS Add to hotkey list success.
532 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.
533 **/
534 EFI_STATUS
535 HotkeyInsertList (
536 IN EFI_KEY_OPTION *KeyOption
537 )
538 {
539 BDS_HOTKEY_OPTION *HotkeyLeft;
540 BDS_HOTKEY_OPTION *HotkeyRight;
541 UINTN Index;
542 EFI_BOOT_KEY_DATA KeyOptions;
543 UINT32 KeyShiftStateLeft;
544 UINT32 KeyShiftStateRight;
545 EFI_INPUT_KEY *InputKey;
546 EFI_KEY_DATA *KeyData;
547
548 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));
549 if (HotkeyLeft == NULL) {
550 return EFI_OUT_OF_RESOURCES;
551 }
552
553 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;
554 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;
555
556 KeyOptions = KeyOption->KeyData;
557
558 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;
559
560 //
561 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState
562 //
563 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;
564 if (KeyOptions.Options.ShiftPressed) {
565 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;
566 }
567 if (KeyOptions.Options.ControlPressed) {
568 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;
569 }
570 if (KeyOptions.Options.AltPressed) {
571 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;
572 }
573 if (KeyOptions.Options.LogoPressed) {
574 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;
575 }
576 if (KeyOptions.Options.MenuPressed) {
577 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;
578 }
579 if (KeyOptions.Options.SysReqPressed) {
580 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;
581 }
582
583
584 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);
585
586 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));
587
588 Index = 0;
589 KeyData = &HotkeyLeft->KeyData[0];
590 do {
591 //
592 // If Key CodeCount is 0, then only KeyData[0] is used;
593 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used
594 //
595 KeyData->Key.ScanCode = InputKey[Index].ScanCode;
596 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;
597 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;
598
599 Index++;
600 KeyData++;
601 } while (Index < HotkeyLeft->CodeCount);
602 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);
603
604 if (KeyShiftStateLeft != KeyShiftStateRight) {
605 //
606 // Need an extra hotkey for shift key on right
607 //
608 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);
609 if (HotkeyRight == NULL) {
610 return EFI_OUT_OF_RESOURCES;
611 }
612
613 Index = 0;
614 KeyData = &HotkeyRight->KeyData[0];
615 do {
616 //
617 // Key.ScanCode and Key.UnicodeChar have already been initialized,
618 // only need to update KeyState.KeyShiftState
619 //
620 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;
621
622 Index++;
623 KeyData++;
624 } while (Index < HotkeyRight->CodeCount);
625 InsertTailList (&mHotkeyList, &HotkeyRight->Link);
626 }
627
628 return EFI_SUCCESS;
629 }
630
631 /**
632
633 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.
634
635 @retval EFI_SUCCESS Hotkey services successfully initialized.
636 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable
637 **/
638 EFI_STATUS
639 InitializeHotkeyService (
640 VOID
641 )
642 {
643 EFI_STATUS Status;
644 UINT32 BootOptionSupport;
645 UINT16 *KeyOrder;
646 UINTN KeyOrderSize;
647 UINTN Index;
648 UINT16 KeyOptionName[8];
649 UINTN KeyOptionSize;
650 EFI_KEY_OPTION *KeyOption;
651
652 //
653 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP
654 // with maximum number of key presses of 3
655 //
656 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;
657 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);
658 Status = gRT->SetVariable (
659 L"BootOptionSupport",
660 &gEfiGlobalVariableGuid,
661 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
662 sizeof (UINT32),
663 &BootOptionSupport
664 );
665
666 //
667 // Get valid Key Option List from private EFI variable "KeyOrder"
668 //
669 KeyOrder = BdsLibGetVariableAndSize (
670 VAR_KEY_ORDER,
671 &gEfiGlobalVariableGuid,
672 &KeyOrderSize
673 );
674
675 if (KeyOrder == NULL) {
676 return EFI_NOT_FOUND;
677 }
678
679 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {
680 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);
681 KeyOption = BdsLibGetVariableAndSize (
682 KeyOptionName,
683 &gEfiGlobalVariableGuid,
684 &KeyOptionSize
685 );
686
687 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {
688 UnregisterHotkey (KeyOrder[Index]);
689 } else {
690 HotkeyInsertList (KeyOption);
691 }
692 }
693
694 //
695 // Register Protocol notify for Hotkey service
696 //
697 Status = gBS->CreateEvent (
698 EVT_NOTIFY_SIGNAL,
699 TPL_CALLBACK,
700 HotkeyEvent,
701 NULL,
702 &mHotkeyEvent
703 );
704 ASSERT_EFI_ERROR (Status);
705
706 //
707 // Register for protocol notifications on this event
708 //
709 Status = gBS->RegisterProtocolNotify (
710 &gEfiSimpleTextInputExProtocolGuid,
711 mHotkeyEvent,
712 &mHotkeyRegistration
713 );
714 ASSERT_EFI_ERROR (Status);
715
716 return Status;
717 }
718