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