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