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