]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
update tools_def.template to supply all possible combination of toolchain and ASL
[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
a9e7937a 104 KeyOptionSize = sizeof (EFI_KEY_OPTION) + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
5c08e117 105 UpdateBootOption = FALSE;\r
106\r
107 //\r
a9e7937a 108 // Check whether HotKey conflict with keys used by Setup Browser\r
5c08e117 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
a9e7937a 146 if (KeyOption->KeyData.Options.InputKeyCount == 0 ||\r
5c08e117 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
a9e7937a 351 ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) {\r
5c08e117 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
a9e7937a 541 EFI_BOOT_KEY_DATA KeyOptions;\r
5c08e117 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
a9e7937a 555 KeyOptions = KeyOption->KeyData;\r
5c08e117 556\r
a9e7937a 557 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
5c08e117 558\r
559 //\r
560 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
561 //\r
a9e7937a 562 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
563 if (KeyOptions.Options.ShiftPressed) {\r
564 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
565 }\r
566 if (KeyOptions.Options.ControlPressed) {\r
567 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
568 }\r
569 if (KeyOptions.Options.AltPressed) {\r
570 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
571 }\r
572 if (KeyOptions.Options.LogoPressed) {\r
573 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
574 }\r
575 if (KeyOptions.Options.MenuPressed) {\r
576 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
577 }\r
578 if (KeyOptions.Options.SysReqPressed) {\r
579 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
580 }\r
581\r
5c08e117 582\r
583 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
584\r
585 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
586\r
587 Index = 0;\r
588 KeyData = &HotkeyLeft->KeyData[0];\r
589 do {\r
590 //\r
591 // If Key CodeCount is 0, then only KeyData[0] is used;\r
592 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
593 //\r
594 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
595 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
596 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
597\r
598 Index++;\r
599 KeyData++;\r
600 } while (Index < HotkeyLeft->CodeCount);\r
601 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
602\r
603 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
604 //\r
605 // Need an extra hotkey for shift key on right\r
606 //\r
607 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
608 if (HotkeyRight == NULL) {\r
609 return EFI_OUT_OF_RESOURCES;\r
610 }\r
611\r
612 Index = 0;\r
613 KeyData = &HotkeyRight->KeyData[0];\r
614 do {\r
615 //\r
616 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
617 // only need to update KeyState.KeyShiftState\r
618 //\r
619 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
620\r
621 Index++;\r
622 KeyData++;\r
623 } while (Index < HotkeyRight->CodeCount);\r
624 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
625 }\r
626\r
627 return EFI_SUCCESS;\r
628}\r
629\r
630/**\r
631\r
632 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
633\r
634 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
635 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
636**/\r
637EFI_STATUS\r
638InitializeHotkeyService (\r
639 VOID\r
640 )\r
641{\r
642 EFI_STATUS Status;\r
643 UINT32 BootOptionSupport;\r
644 UINT16 *KeyOrder;\r
645 UINTN KeyOrderSize;\r
646 UINTN Index;\r
647 UINT16 KeyOptionName[8];\r
648 UINTN KeyOptionSize;\r
649 EFI_KEY_OPTION *KeyOption;\r
650\r
651 //\r
652 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
a9e7937a 653 // with maximum number of key presses of 3\r
5c08e117 654 //\r
655 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
a9e7937a 656 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
5c08e117 657 Status = gRT->SetVariable (\r
658 L"BootOptionSupport",\r
659 &gEfiGlobalVariableGuid,\r
a9e7937a 660 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
5c08e117 661 sizeof (UINT32),\r
662 &BootOptionSupport\r
663 );\r
664\r
665 //\r
666 // Get valid Key Option List from private EFI variable "KeyOrder"\r
667 //\r
668 KeyOrder = BdsLibGetVariableAndSize (\r
669 VAR_KEY_ORDER,\r
670 &gEfiGlobalVariableGuid,\r
671 &KeyOrderSize\r
672 );\r
673\r
674 if (KeyOrder == NULL) {\r
675 return EFI_NOT_FOUND;\r
676 }\r
677\r
678 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
679 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
680 KeyOption = BdsLibGetVariableAndSize (\r
681 KeyOptionName,\r
682 &gEfiGlobalVariableGuid,\r
683 &KeyOptionSize\r
684 );\r
685\r
686 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
687 UnregisterHotkey (KeyOrder[Index]);\r
688 } else {\r
689 HotkeyInsertList (KeyOption);\r
690 }\r
691 }\r
692\r
693 //\r
694 // Register Protocol notify for Hotkey service\r
695 //\r
696 Status = gBS->CreateEvent (\r
697 EVT_NOTIFY_SIGNAL,\r
698 TPL_CALLBACK,\r
699 HotkeyEvent,\r
700 NULL,\r
701 &mHotkeyEvent\r
702 );\r
703 ASSERT_EFI_ERROR (Status);\r
704\r
705 //\r
706 // Register for protocol notifications on this event\r
707 //\r
708 Status = gBS->RegisterProtocolNotify (\r
709 &gEfiSimpleTextInputExProtocolGuid,\r
710 mHotkeyEvent,\r
711 &mHotkeyRegistration\r
712 );\r
713 ASSERT_EFI_ERROR (Status);\r
714\r
715 return Status;\r
716}\r
717\r