]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/Hotkey.c
Code scrub for BdsDxe module.
[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
b30312ba 231 @param KeyOptionNumber Key option number for Key####\r
93e3992d 232\r
b30312ba 233 @retval EFI_SUCCESS Unregister hotkey successfully.\r
234 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
93e3992d 235\r
b30312ba 236**/\r
237EFI_STATUS\r
238UnregisterHotkey (\r
239 IN UINT16 KeyOptionNumber\r
240)\r
93e3992d 241{\r
242 UINT16 KeyOption[10];\r
243 UINTN Index;\r
244 EFI_STATUS Status;\r
245 UINTN Index2Del;\r
246 UINT16 *KeyOrder;\r
247 UINTN KeyOrderSize;\r
248\r
249 //\r
250 // Delete variable Key####\r
251 //\r
252 UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
253 gRT->SetVariable (\r
254 KeyOption,\r
255 &gEfiGlobalVariableGuid,\r
256 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
257 0,\r
258 NULL\r
259 );\r
260\r
261 //\r
262 // Adjust key order array\r
263 //\r
264 KeyOrder = BdsLibGetVariableAndSize (\r
b4489769 265 VAR_KEY_ORDER,\r
93e3992d 266 &gEfiGlobalVariableGuid,\r
267 &KeyOrderSize\r
268 );\r
269 if (KeyOrder == NULL) {\r
270 return EFI_SUCCESS;\r
271 }\r
272\r
273 Index2Del = 0;\r
274 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
275 if (KeyOrder[Index] == KeyOptionNumber) {\r
276 Index2Del = Index;\r
277 break;\r
278 }\r
279 }\r
280\r
281 if (Index != KeyOrderSize / sizeof (UINT16)) {\r
282 //\r
283 // KeyOptionNumber found in "KeyOrder", delete it\r
284 //\r
285 for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
286 KeyOrder[Index] = KeyOrder[Index + 1];\r
287 }\r
288\r
289 KeyOrderSize -= sizeof (UINT16);\r
290 }\r
291\r
292 Status = gRT->SetVariable (\r
b4489769 293 VAR_KEY_ORDER,\r
93e3992d 294 &gEfiGlobalVariableGuid,\r
295 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
296 KeyOrderSize,\r
297 KeyOrder\r
298 );\r
299\r
300 FreePool (KeyOrder);\r
301\r
302 return Status;\r
303}\r
304\r
b30312ba 305/**\r
93e3992d 306\r
307 This is the common notification function for HotKeys, it will be registered\r
308 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
309\r
93e3992d 310\r
b30312ba 311 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
312 information for the key that was pressed.\r
93e3992d 313\r
b30312ba 314 @retval EFI_SUCCESS KeyData is successfully processed.\r
93e3992d 315\r
b30312ba 316**/\r
317EFI_STATUS\r
318HotkeyCallback (\r
319 IN EFI_KEY_DATA *KeyData\r
320)\r
93e3992d 321{\r
322 BOOLEAN HotkeyCatched;\r
323 LIST_ENTRY BootLists;\r
324 LIST_ENTRY *Link;\r
325 BDS_HOTKEY_OPTION *Hotkey;\r
326 UINT16 Buffer[10];\r
327 BDS_COMMON_OPTION *BootOption;\r
328 UINTN ExitDataSize;\r
329 CHAR16 *ExitData;\r
330 EFI_TPL OldTpl;\r
331 EFI_STATUS Status;\r
332 EFI_KEY_DATA *HotkeyData;\r
333\r
334 if (mHotkeyCallbackPending) {\r
335 //\r
336 // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
337 // the current Boot#### load option returned\r
338 //\r
339 return EFI_SUCCESS;\r
340 }\r
341\r
342 Status = EFI_SUCCESS;\r
343 Link = GetFirstNode (&mHotkeyList);\r
344\r
345 while (!IsNull (&mHotkeyList, Link)) {\r
346 HotkeyCatched = FALSE;\r
347 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
348\r
349 //\r
350 // Is this Key Stroke we are waiting for?\r
351 //\r
352 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
353 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
354 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
355 ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
356 //\r
357 // Receive an expecting key stroke\r
358 //\r
359 if (Hotkey->CodeCount > 1) {\r
360 //\r
361 // For hotkey of key combination, transit to next waiting state\r
362 //\r
363 Hotkey->WaitingKey++;\r
364\r
365 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
366 //\r
367 // Received the whole key stroke sequence\r
368 //\r
369 HotkeyCatched = TRUE;\r
370 }\r
371 } else {\r
372 //\r
373 // For hotkey of single key stroke\r
374 //\r
375 HotkeyCatched = TRUE;\r
376 }\r
377 } else {\r
378 //\r
379 // Receive an unexpected key stroke, reset to initial waiting state\r
380 //\r
381 Hotkey->WaitingKey = 0;\r
382 }\r
383\r
384 if (HotkeyCatched) {\r
385 //\r
386 // Reset to initial waiting state\r
387 //\r
388 Hotkey->WaitingKey = 0;\r
389\r
390 //\r
391 // Launch its BootOption\r
392 //\r
393 InitializeListHead (&BootLists);\r
394\r
395 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
396 BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
397 BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
398 BdsLibConnectDevicePath (BootOption->DevicePath);\r
399\r
400 //\r
401 // Clear the screen before launch this BootOption\r
402 //\r
403 gST->ConOut->Reset (gST->ConOut, FALSE);\r
404\r
405 //\r
406 // BdsLibBootViaBootOption() is expected to be invoked at TPL level TPL_APPLICATION,\r
407 // so raise the TPL to TPL_APPLICATION first, then restore it\r
408 //\r
409 OldTpl = gBS->RaiseTPL (TPL_APPLICATION);\r
410\r
411 mHotkeyCallbackPending = TRUE;\r
412 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
413 mHotkeyCallbackPending = FALSE;\r
414\r
415 gBS->RestoreTPL (OldTpl);\r
416\r
417 if (EFI_ERROR (Status)) {\r
418 //\r
419 // Call platform action to indicate the boot fail\r
420 //\r
421 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
422 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
423 } else {\r
424 //\r
425 // Call platform action to indicate the boot success\r
426 //\r
427 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
428 PlatformBdsBootSuccess (BootOption);\r
429 }\r
430 }\r
431\r
432 Link = GetNextNode (&mHotkeyList, Link);\r
433 }\r
434\r
435 return Status;\r
436}\r
437\r
b30312ba 438/**\r
93e3992d 439\r
440 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
441\r
93e3992d 442\r
b30312ba 443 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
93e3992d 444\r
b30312ba 445 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
446 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
93e3992d 447\r
b30312ba 448**/\r
449EFI_STATUS\r
450HotkeyRegisterNotify (\r
451 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
452)\r
93e3992d 453{\r
454 UINTN Index;\r
455 EFI_STATUS Status;\r
456 LIST_ENTRY *Link;\r
457 BDS_HOTKEY_OPTION *Hotkey;\r
458\r
459 //\r
460 // Register notification function for each hotkey\r
461 //\r
462 Link = GetFirstNode (&mHotkeyList);\r
463\r
464 while (!IsNull (&mHotkeyList, Link)) {\r
465 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
466\r
467 Index = 0;\r
468 do {\r
469 Status = SimpleTextInEx->RegisterKeyNotify (\r
470 SimpleTextInEx,\r
471 &Hotkey->KeyData[Index],\r
472 HotkeyCallback,\r
473 &Hotkey->NotifyHandle\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 //\r
477 // some of the hotkey registry failed\r
478 //\r
479 return Status;\r
480 }\r
481 Index ++;\r
482 } while (Index < Hotkey->CodeCount);\r
483\r
484 Link = GetNextNode (&mHotkeyList, Link);\r
485 }\r
486\r
487 return EFI_SUCCESS;\r
488}\r
489\r
b30312ba 490/**\r
491 Callback function for SimpleTextInEx protocol install events\r
492\r
493\r
494 @param Event the event that is signaled.\r
495 @param Context not used here.\r
496\r
497 @return VOID\r
498\r
499**/\r
93e3992d 500VOID\r
501EFIAPI\r
502HotkeyEvent (\r
503 IN EFI_EVENT Event,\r
504 IN VOID *Context\r
505 )\r
93e3992d 506{\r
507 EFI_STATUS Status;\r
508 UINTN BufferSize;\r
509 EFI_HANDLE Handle;\r
510 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
511\r
512 while (TRUE) {\r
513 BufferSize = sizeof (EFI_HANDLE);\r
514 Status = gBS->LocateHandle (\r
515 ByRegisterNotify,\r
516 NULL,\r
517 mHotkeyRegistration,\r
518 &BufferSize,\r
519 &Handle\r
520 );\r
521 if (EFI_ERROR (Status)) {\r
522 //\r
523 // If no more notification events exist\r
524 //\r
525 return ;\r
526 }\r
527\r
528 Status = gBS->HandleProtocol (\r
529 Handle,\r
530 &gEfiSimpleTextInputExProtocolGuid,\r
531 (VOID **) &SimpleTextInEx\r
532 );\r
533 ASSERT_EFI_ERROR (Status);\r
534\r
535 HotkeyRegisterNotify (SimpleTextInEx);\r
536 }\r
537}\r
538\r
b30312ba 539/**\r
93e3992d 540\r
541 Insert Key Option to hotkey list.\r
542\r
93e3992d 543\r
b30312ba 544 @param KeyOption The Hot Key Option to be added to hotkey list.\r
93e3992d 545\r
b30312ba 546 @retval EFI_SUCCESS Add to hotkey list success.\r
93e3992d 547\r
b30312ba 548**/\r
549EFI_STATUS\r
550HotkeyInsertList (\r
551 IN EFI_KEY_OPTION *KeyOption\r
552)\r
93e3992d 553{\r
554 BDS_HOTKEY_OPTION *HotkeyLeft;\r
555 BDS_HOTKEY_OPTION *HotkeyRight;\r
556 UINTN Index;\r
557 UINT32 KeyOptions;\r
558 UINT32 KeyShiftStateLeft;\r
559 UINT32 KeyShiftStateRight;\r
560 EFI_INPUT_KEY *InputKey;\r
561 EFI_KEY_DATA *KeyData;\r
562\r
563 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
564 if (HotkeyLeft == NULL) {\r
565 return EFI_OUT_OF_RESOURCES;\r
566 }\r
567\r
568 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
569 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
570\r
571 KeyOptions = KeyOption->KeyOptions.PackedValue;\r
572\r
573 HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
574\r
575 //\r
576 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
577 //\r
578 KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
579 ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
580 ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
581 ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
582 ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
583 EFI_SHIFT_STATE_VALID;\r
584\r
585 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
586\r
587 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
588\r
589 Index = 0;\r
590 KeyData = &HotkeyLeft->KeyData[0];\r
591 do {\r
592 //\r
593 // If Key CodeCount is 0, then only KeyData[0] is used;\r
594 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
595 //\r
596 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
597 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
598 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
599\r
600 Index++;\r
601 KeyData++;\r
602 } while (Index < HotkeyLeft->CodeCount);\r
603 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
604\r
605 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
606 //\r
607 // Need an extra hotkey for shift key on right\r
608 //\r
609 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
610 if (HotkeyRight == NULL) {\r
611 return EFI_OUT_OF_RESOURCES;\r
612 }\r
613\r
614 Index = 0;\r
615 KeyData = &HotkeyRight->KeyData[0];\r
616 do {\r
617 //\r
618 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
619 // only need to update KeyState.KeyShiftState\r
620 //\r
621 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
622\r
623 Index++;\r
624 KeyData++;\r
625 } while (Index < HotkeyRight->CodeCount);\r
626 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
627 }\r
628\r
629 return EFI_SUCCESS;\r
630}\r
631\r
b30312ba 632/**\r
93e3992d 633\r
634 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
635\r
b30312ba 636 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
30394aa1 637 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
b30312ba 638**/\r
639EFI_STATUS\r
640InitializeHotkeyService (\r
641 VOID\r
642 )\r
93e3992d 643{\r
644 EFI_STATUS Status;\r
645 UINT32 BootOptionSupport;\r
646 UINT16 *KeyOrder;\r
647 UINTN KeyOrderSize;\r
648 UINTN Index;\r
649 UINT16 KeyOptionName[8];\r
650 UINTN KeyOptionSize;\r
651 EFI_KEY_OPTION *KeyOption;\r
652\r
653 //\r
654 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
655 //\r
656 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
657 Status = gRT->SetVariable (\r
658 L"BootOptionSupport",\r
659 &gEfiGlobalVariableGuid,\r
660 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
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
b4489769 669 VAR_KEY_ORDER,\r
93e3992d 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