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