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