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