]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
In PcdBootlogoOnlyEnable case, Clear cursor & screen when key rather than Hotkey or
[mirror_edk2.git] / IntelFrameworkModulePkg / 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 - 2012, Intel Corporation. All rights reserved.<BR>\r
6This 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
20BDS_COMMON_OPTION *mHotkeyBootOption = NULL;\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) + KeyOption->KeyData.Options.InputKeyCount * 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 ASSERT (TempOption != NULL);\r
136\r
137 if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
138 //\r
139 // Got the option, so just return\r
140 //\r
141 FreePool (TempOption);\r
142 FreePool (KeyOrder);\r
143 return EFI_SUCCESS;\r
144 }\r
145\r
146 if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
147 if (KeyOption->KeyData.Options.InputKeyCount == 0 ||\r
148 CompareMem (\r
149 ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
150 ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
151 KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
152 ) == 0) {\r
153 //\r
154 // Hotkey is the same but BootOption changed, need update\r
155 //\r
156 UpdateBootOption = TRUE;\r
157 break;\r
158 }\r
159 }\r
160\r
161 FreePool (TempOption);\r
162 }\r
163\r
164 if (UpdateBootOption) {\r
165 RegisterOptionNumber = KeyOrder[Index];\r
166 FreePool (TempOption);\r
167 } else {\r
168 RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
169 }\r
170\r
171 if (KeyOptionNumber != NULL) {\r
172 *KeyOptionNumber = RegisterOptionNumber;\r
173 }\r
174\r
175 //\r
176 // Create variable Key####\r
177 //\r
178 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
179 Status = gRT->SetVariable (\r
180 KeyOptionName,\r
181 &gEfiGlobalVariableGuid,\r
182 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
183 KeyOptionSize,\r
184 KeyOption\r
185 );\r
186 if (EFI_ERROR (Status)) {\r
187 FreePool (KeyOrder);\r
188 return Status;\r
189 }\r
190\r
191 //\r
192 // Update the key order variable - "KeyOrder"\r
193 //\r
194 if (!UpdateBootOption) {\r
195 Index = KeyOrderSize / sizeof (UINT16);\r
196 KeyOrderSize += sizeof (UINT16);\r
197 }\r
198\r
199 NewKeyOrder = AllocatePool (KeyOrderSize);\r
200 if (NewKeyOrder == NULL) {\r
201 FreePool (KeyOrder);\r
202 return EFI_OUT_OF_RESOURCES;\r
203 }\r
204\r
205 if (KeyOrder != NULL) {\r
206 CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
207 }\r
208\r
209 NewKeyOrder[Index] = RegisterOptionNumber;\r
210\r
211 Status = gRT->SetVariable (\r
212 VAR_KEY_ORDER,\r
213 &gEfiGlobalVariableGuid,\r
214 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
215 KeyOrderSize,\r
216 NewKeyOrder\r
217 );\r
218\r
219 FreePool (KeyOrder);\r
220 FreePool (NewKeyOrder);\r
221\r
222 return Status;\r
223}\r
224\r
225/**\r
226\r
227 Delete Key#### for the given Key Option number.\r
228\r
229 @param KeyOptionNumber Key option number for Key####\r
230\r
231 @retval EFI_SUCCESS Unregister hotkey successfully.\r
232 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
233\r
234**/\r
235EFI_STATUS\r
236UnregisterHotkey (\r
237 IN UINT16 KeyOptionNumber\r
238)\r
239{\r
240 UINT16 KeyOption[10];\r
241 UINTN Index;\r
242 EFI_STATUS Status;\r
243 UINTN Index2Del;\r
244 UINT16 *KeyOrder;\r
245 UINTN KeyOrderSize;\r
246\r
247 //\r
248 // Delete variable Key####\r
249 //\r
250 UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
251 gRT->SetVariable (\r
252 KeyOption,\r
253 &gEfiGlobalVariableGuid,\r
254 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
255 0,\r
256 NULL\r
257 );\r
258\r
259 //\r
260 // Adjust key order array\r
261 //\r
262 KeyOrder = BdsLibGetVariableAndSize (\r
263 VAR_KEY_ORDER,\r
264 &gEfiGlobalVariableGuid,\r
265 &KeyOrderSize\r
266 );\r
267 if (KeyOrder == NULL) {\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
271 Index2Del = 0;\r
272 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
273 if (KeyOrder[Index] == KeyOptionNumber) {\r
274 Index2Del = Index;\r
275 break;\r
276 }\r
277 }\r
278\r
279 if (Index != KeyOrderSize / sizeof (UINT16)) {\r
280 //\r
281 // KeyOptionNumber found in "KeyOrder", delete it\r
282 //\r
283 for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
284 KeyOrder[Index] = KeyOrder[Index + 1];\r
285 }\r
286\r
287 KeyOrderSize -= sizeof (UINT16);\r
288 }\r
289\r
290 Status = gRT->SetVariable (\r
291 VAR_KEY_ORDER,\r
292 &gEfiGlobalVariableGuid,\r
293 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
294 KeyOrderSize,\r
295 KeyOrder\r
296 );\r
297\r
298 FreePool (KeyOrder);\r
299\r
300 return Status;\r
301}\r
302\r
303/**\r
304 Try to boot the boot option triggered by hotkey.\r
305 @retval EFI_SUCCESS There is HotkeyBootOption & it is processed\r
306 @retval EFI_NOT_FOUND There is no HotkeyBootOption\r
307**/\r
308EFI_STATUS\r
309HotkeyBoot (\r
310 VOID\r
311 )\r
312{ \r
313 EFI_STATUS Status;\r
314 UINTN ExitDataSize;\r
315 CHAR16 *ExitData;\r
316\r
317 if (mHotkeyBootOption == NULL) {\r
318 return EFI_NOT_FOUND;\r
319 } \r
320 \r
321 BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
322\r
323 //\r
324 // Clear the screen before launch this BootOption\r
325 //\r
326 gST->ConOut->Reset (gST->ConOut, FALSE);\r
327\r
328 Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\r
329\r
330 if (EFI_ERROR (Status)) {\r
331 //\r
332 // Call platform action to indicate the boot fail\r
333 //\r
334 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
335 PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);\r
336 } else {\r
337 //\r
338 // Call platform action to indicate the boot success\r
339 //\r
340 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
341 PlatformBdsBootSuccess (mHotkeyBootOption);\r
342 }\r
343 FreePool (mHotkeyBootOption->Description);\r
344 FreePool (mHotkeyBootOption->DevicePath);\r
345 FreePool (mHotkeyBootOption->LoadOptions);\r
346 FreePool (mHotkeyBootOption);\r
347\r
348 mHotkeyBootOption = NULL;\r
349\r
350 return EFI_SUCCESS;\r
351}\r
352\r
353/**\r
354\r
355 This is the common notification function for HotKeys, it will be registered\r
356 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
357\r
358 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
359 information for the key that was pressed.\r
360\r
361 @retval EFI_SUCCESS KeyData is successfully processed.\r
362 @return EFI_NOT_FOUND Fail to find boot option variable.\r
363**/\r
364EFI_STATUS\r
365EFIAPI\r
366HotkeyCallback (\r
367 IN EFI_KEY_DATA *KeyData\r
368)\r
369{\r
370 BOOLEAN HotkeyCatched;\r
371 LIST_ENTRY BootLists;\r
372 LIST_ENTRY *Link;\r
373 BDS_HOTKEY_OPTION *Hotkey;\r
374 UINT16 Buffer[10];\r
375 EFI_STATUS Status;\r
376 EFI_KEY_DATA *HotkeyData;\r
377\r
378 if (mHotkeyBootOption != NULL) {\r
379 //\r
380 // Do not process sequential hotkey stroke until the current boot option returns\r
381 //\r
382 return EFI_SUCCESS;\r
383 }\r
384\r
385 Status = EFI_SUCCESS;\r
386\r
387 for ( Link = GetFirstNode (&mHotkeyList)\r
388 ; !IsNull (&mHotkeyList, Link)\r
389 ; Link = GetNextNode (&mHotkeyList, Link)\r
390 ) {\r
391 HotkeyCatched = FALSE;\r
392 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
393\r
394 //\r
395 // Is this Key Stroke we are waiting for?\r
396 //\r
397 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
398 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
399 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
400 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
401 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
402 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
403 )\r
404 ) {\r
405 //\r
406 // For hotkey of key combination, transit to next waiting state\r
407 //\r
408 Hotkey->WaitingKey++;\r
409\r
410 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
411 //\r
412 // Received the whole key stroke sequence\r
413 //\r
414 HotkeyCatched = TRUE;\r
415 }\r
416 } else {\r
417 //\r
418 // Receive an unexpected key stroke, reset to initial waiting state\r
419 //\r
420 Hotkey->WaitingKey = 0;\r
421 }\r
422\r
423 if (HotkeyCatched) {\r
424 //\r
425 // Reset to initial waiting state\r
426 //\r
427 Hotkey->WaitingKey = 0;\r
428\r
429 //\r
430 // Launch its BootOption\r
431 //\r
432 InitializeListHead (&BootLists);\r
433\r
434 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
435 mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
436 }\r
437 }\r
438\r
439 return Status;\r
440}\r
441\r
442/**\r
443 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
444\r
445 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
446\r
447 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
448 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
449\r
450**/\r
451EFI_STATUS\r
452HotkeyRegisterNotify (\r
453 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
454)\r
455{\r
456 UINTN Index;\r
457 EFI_STATUS Status;\r
458 LIST_ENTRY *Link;\r
459 BDS_HOTKEY_OPTION *Hotkey;\r
460\r
461 //\r
462 // Register notification function for each hotkey\r
463 //\r
464 Link = GetFirstNode (&mHotkeyList);\r
465\r
466 while (!IsNull (&mHotkeyList, Link)) {\r
467 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
468\r
469 Index = 0;\r
470 do {\r
471 Status = SimpleTextInEx->RegisterKeyNotify (\r
472 SimpleTextInEx,\r
473 &Hotkey->KeyData[Index],\r
474 HotkeyCallback,\r
475 &Hotkey->NotifyHandle\r
476 );\r
477 if (EFI_ERROR (Status)) {\r
478 //\r
479 // some of the hotkey registry failed\r
480 //\r
481 return Status;\r
482 }\r
483 Index ++;\r
484 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));\r
485\r
486 Link = GetNextNode (&mHotkeyList, Link);\r
487 }\r
488\r
489 return EFI_SUCCESS;\r
490}\r
491\r
492/**\r
493 Callback function for SimpleTextInEx protocol install events\r
494\r
495 @param Event the event that is signaled.\r
496 @param Context not used here.\r
497\r
498**/\r
499VOID\r
500EFIAPI\r
501HotkeyEvent (\r
502 IN EFI_EVENT Event,\r
503 IN VOID *Context\r
504 )\r
505{\r
506 EFI_STATUS Status;\r
507 UINTN BufferSize;\r
508 EFI_HANDLE Handle;\r
509 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
510\r
511 while (TRUE) {\r
512 BufferSize = sizeof (EFI_HANDLE);\r
513 Status = gBS->LocateHandle (\r
514 ByRegisterNotify,\r
515 NULL,\r
516 mHotkeyRegistration,\r
517 &BufferSize,\r
518 &Handle\r
519 );\r
520 if (EFI_ERROR (Status)) {\r
521 //\r
522 // If no more notification events exist\r
523 //\r
524 return ;\r
525 }\r
526\r
527 Status = gBS->HandleProtocol (\r
528 Handle,\r
529 &gEfiSimpleTextInputExProtocolGuid,\r
530 (VOID **) &SimpleTextInEx\r
531 );\r
532 ASSERT_EFI_ERROR (Status);\r
533\r
534 HotkeyRegisterNotify (SimpleTextInEx);\r
535 }\r
536}\r
537\r
538/**\r
539 Insert Key Option to hotkey list.\r
540\r
541 @param KeyOption The Hot Key Option to be added to hotkey list.\r
542\r
543 @retval EFI_SUCCESS Add to hotkey list success.\r
544 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
545**/\r
546EFI_STATUS\r
547HotkeyInsertList (\r
548 IN EFI_KEY_OPTION *KeyOption\r
549)\r
550{\r
551 BDS_HOTKEY_OPTION *HotkeyLeft;\r
552 BDS_HOTKEY_OPTION *HotkeyRight;\r
553 UINTN Index;\r
554 EFI_BOOT_KEY_DATA KeyOptions;\r
555 UINT32 KeyShiftStateLeft;\r
556 UINT32 KeyShiftStateRight;\r
557 EFI_INPUT_KEY *InputKey;\r
558 EFI_KEY_DATA *KeyData;\r
559\r
560 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
561 if (HotkeyLeft == NULL) {\r
562 return EFI_OUT_OF_RESOURCES;\r
563 }\r
564\r
565 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
566 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
567\r
568 KeyOptions = KeyOption->KeyData;\r
569\r
570 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
571\r
572 //\r
573 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
574 //\r
575 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
576 if (KeyOptions.Options.ShiftPressed) {\r
577 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
578 }\r
579 if (KeyOptions.Options.ControlPressed) {\r
580 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
581 }\r
582 if (KeyOptions.Options.AltPressed) {\r
583 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
584 }\r
585 if (KeyOptions.Options.LogoPressed) {\r
586 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
587 }\r
588 if (KeyOptions.Options.MenuPressed) {\r
589 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
590 }\r
591 if (KeyOptions.Options.SysReqPressed) {\r
592 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
593 }\r
594\r
595\r
596 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
597\r
598 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
599\r
600 Index = 0;\r
601 KeyData = &HotkeyLeft->KeyData[0];\r
602 do {\r
603 //\r
604 // If Key CodeCount is 0, then only KeyData[0] is used;\r
605 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
606 //\r
607 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
608 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
609 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
610\r
611 Index++;\r
612 KeyData++;\r
613 } while (Index < HotkeyLeft->CodeCount);\r
614 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
615\r
616 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
617 //\r
618 // Need an extra hotkey for shift key on right\r
619 //\r
620 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
621 if (HotkeyRight == NULL) {\r
622 return EFI_OUT_OF_RESOURCES;\r
623 }\r
624\r
625 Index = 0;\r
626 KeyData = &HotkeyRight->KeyData[0];\r
627 do {\r
628 //\r
629 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
630 // only need to update KeyState.KeyShiftState\r
631 //\r
632 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
633\r
634 Index++;\r
635 KeyData++;\r
636 } while (Index < HotkeyRight->CodeCount);\r
637 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
638 }\r
639\r
640 return EFI_SUCCESS;\r
641}\r
642\r
643/**\r
644\r
645 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
646\r
647 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
648 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
649**/\r
650EFI_STATUS\r
651InitializeHotkeyService (\r
652 VOID\r
653 )\r
654{\r
655 EFI_STATUS Status;\r
656 UINT32 BootOptionSupport;\r
657 UINT16 *KeyOrder;\r
658 UINTN KeyOrderSize;\r
659 UINTN Index;\r
660 UINT16 KeyOptionName[8];\r
661 UINTN KeyOptionSize;\r
662 EFI_KEY_OPTION *KeyOption;\r
663\r
664 //\r
665 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
666 // with maximum number of key presses of 3\r
667 //\r
668 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
669 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
670 Status = gRT->SetVariable (\r
671 L"BootOptionSupport",\r
672 &gEfiGlobalVariableGuid,\r
673 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
674 sizeof (UINT32),\r
675 &BootOptionSupport\r
676 );\r
677\r
678 //\r
679 // Get valid Key Option List from private EFI variable "KeyOrder"\r
680 //\r
681 KeyOrder = BdsLibGetVariableAndSize (\r
682 VAR_KEY_ORDER,\r
683 &gEfiGlobalVariableGuid,\r
684 &KeyOrderSize\r
685 );\r
686\r
687 if (KeyOrder == NULL) {\r
688 return EFI_NOT_FOUND;\r
689 }\r
690\r
691 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
692 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
693 KeyOption = BdsLibGetVariableAndSize (\r
694 KeyOptionName,\r
695 &gEfiGlobalVariableGuid,\r
696 &KeyOptionSize\r
697 );\r
698\r
699 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
700 UnregisterHotkey (KeyOrder[Index]);\r
701 } else {\r
702 HotkeyInsertList (KeyOption);\r
703 }\r
704 }\r
705\r
706 //\r
707 // Register Protocol notify for Hotkey service\r
708 //\r
709 Status = gBS->CreateEvent (\r
710 EVT_NOTIFY_SIGNAL,\r
711 TPL_CALLBACK,\r
712 HotkeyEvent,\r
713 NULL,\r
714 &mHotkeyEvent\r
715 );\r
716 ASSERT_EFI_ERROR (Status);\r
717\r
718 //\r
719 // Register for protocol notifications on this event\r
720 //\r
721 Status = gBS->RegisterProtocolNotify (\r
722 &gEfiSimpleTextInputExProtocolGuid,\r
723 mHotkeyEvent,\r
724 &mHotkeyRegistration\r
725 );\r
726 ASSERT_EFI_ERROR (Status);\r
727\r
728 return Status;\r
729}\r
730\r