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