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