]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
Fix the potential issue that using integrate as BOOLEAN value in judgment.
[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
6ba0bc7c 314EFIAPI\r
5c08e117 315HotkeyCallback (\r
316 IN EFI_KEY_DATA *KeyData\r
317)\r
318{\r
319 BOOLEAN HotkeyCatched;\r
320 LIST_ENTRY BootLists;\r
321 LIST_ENTRY *Link;\r
322 BDS_HOTKEY_OPTION *Hotkey;\r
323 UINT16 Buffer[10];\r
324 BDS_COMMON_OPTION *BootOption;\r
325 UINTN ExitDataSize;\r
326 CHAR16 *ExitData;\r
327 EFI_STATUS Status;\r
328 EFI_KEY_DATA *HotkeyData;\r
329\r
330 if (mHotkeyCallbackPending) {\r
331 //\r
332 // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
333 // the current Boot#### load option returned\r
334 //\r
335 return EFI_SUCCESS;\r
336 }\r
337\r
338 Status = EFI_SUCCESS;\r
339 Link = GetFirstNode (&mHotkeyList);\r
340\r
341 while (!IsNull (&mHotkeyList, Link)) {\r
342 HotkeyCatched = FALSE;\r
343 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
344\r
345 //\r
346 // Is this Key Stroke we are waiting for?\r
347 //\r
348 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
349 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
350 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
351 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
7ec9caab 352 (((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE)) {\r
5c08e117 353 //\r
354 // Receive an expecting key stroke\r
355 //\r
356 if (Hotkey->CodeCount > 1) {\r
357 //\r
358 // For hotkey of key combination, transit to next waiting state\r
359 //\r
360 Hotkey->WaitingKey++;\r
361\r
362 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
363 //\r
364 // Received the whole key stroke sequence\r
365 //\r
366 HotkeyCatched = TRUE;\r
367 }\r
368 } else {\r
369 //\r
370 // For hotkey of single key stroke\r
371 //\r
372 HotkeyCatched = TRUE;\r
373 }\r
374 } else {\r
375 //\r
376 // Receive an unexpected key stroke, reset to initial waiting state\r
377 //\r
378 Hotkey->WaitingKey = 0;\r
379 }\r
380\r
381 if (HotkeyCatched) {\r
382 //\r
383 // Reset to initial waiting state\r
384 //\r
385 Hotkey->WaitingKey = 0;\r
386\r
387 //\r
388 // Launch its BootOption\r
389 //\r
390 InitializeListHead (&BootLists);\r
391\r
392 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
393 BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
394 if (BootOption == NULL) {\r
395 return EFI_NOT_FOUND;\r
396 }\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 mHotkeyCallbackPending = TRUE;\r
406 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
407 mHotkeyCallbackPending = FALSE;\r
408\r
409 if (EFI_ERROR (Status)) {\r
410 //\r
411 // Call platform action to indicate the boot fail\r
412 //\r
413 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
414 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
415 } else {\r
416 //\r
417 // Call platform action to indicate the boot success\r
418 //\r
419 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
420 PlatformBdsBootSuccess (BootOption);\r
421 }\r
422 }\r
423\r
424 Link = GetNextNode (&mHotkeyList, Link);\r
425 }\r
426\r
427 return Status;\r
428}\r
429\r
430/**\r
431 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
432\r
433 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
434\r
435 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
436 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
437\r
438**/\r
439EFI_STATUS\r
440HotkeyRegisterNotify (\r
441 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
442)\r
443{\r
444 UINTN Index;\r
445 EFI_STATUS Status;\r
446 LIST_ENTRY *Link;\r
447 BDS_HOTKEY_OPTION *Hotkey;\r
448\r
449 //\r
450 // Register notification function for each hotkey\r
451 //\r
452 Link = GetFirstNode (&mHotkeyList);\r
453\r
454 while (!IsNull (&mHotkeyList, Link)) {\r
455 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
456\r
457 Index = 0;\r
458 do {\r
459 Status = SimpleTextInEx->RegisterKeyNotify (\r
460 SimpleTextInEx,\r
461 &Hotkey->KeyData[Index],\r
462 HotkeyCallback,\r
463 &Hotkey->NotifyHandle\r
464 );\r
465 if (EFI_ERROR (Status)) {\r
466 //\r
467 // some of the hotkey registry failed\r
468 //\r
469 return Status;\r
470 }\r
471 Index ++;\r
84fa6c17 472 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));\r
5c08e117 473\r
474 Link = GetNextNode (&mHotkeyList, Link);\r
475 }\r
476\r
477 return EFI_SUCCESS;\r
478}\r
479\r
480/**\r
481 Callback function for SimpleTextInEx protocol install events\r
482\r
483 @param Event the event that is signaled.\r
484 @param Context not used here.\r
485\r
486**/\r
487VOID\r
488EFIAPI\r
489HotkeyEvent (\r
490 IN EFI_EVENT Event,\r
491 IN VOID *Context\r
492 )\r
493{\r
494 EFI_STATUS Status;\r
495 UINTN BufferSize;\r
496 EFI_HANDLE Handle;\r
497 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
498\r
499 while (TRUE) {\r
500 BufferSize = sizeof (EFI_HANDLE);\r
501 Status = gBS->LocateHandle (\r
502 ByRegisterNotify,\r
503 NULL,\r
504 mHotkeyRegistration,\r
505 &BufferSize,\r
506 &Handle\r
507 );\r
508 if (EFI_ERROR (Status)) {\r
509 //\r
510 // If no more notification events exist\r
511 //\r
512 return ;\r
513 }\r
514\r
515 Status = gBS->HandleProtocol (\r
516 Handle,\r
517 &gEfiSimpleTextInputExProtocolGuid,\r
518 (VOID **) &SimpleTextInEx\r
519 );\r
520 ASSERT_EFI_ERROR (Status);\r
521\r
522 HotkeyRegisterNotify (SimpleTextInEx);\r
523 }\r
524}\r
525\r
526/**\r
527 Insert Key Option to hotkey list.\r
528\r
529 @param KeyOption The Hot Key Option to be added to hotkey list.\r
530\r
531 @retval EFI_SUCCESS Add to hotkey list success.\r
532 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
533**/\r
534EFI_STATUS\r
535HotkeyInsertList (\r
536 IN EFI_KEY_OPTION *KeyOption\r
537)\r
538{\r
539 BDS_HOTKEY_OPTION *HotkeyLeft;\r
540 BDS_HOTKEY_OPTION *HotkeyRight;\r
541 UINTN Index;\r
a9e7937a 542 EFI_BOOT_KEY_DATA KeyOptions;\r
5c08e117 543 UINT32 KeyShiftStateLeft;\r
544 UINT32 KeyShiftStateRight;\r
545 EFI_INPUT_KEY *InputKey;\r
546 EFI_KEY_DATA *KeyData;\r
547\r
548 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
549 if (HotkeyLeft == NULL) {\r
550 return EFI_OUT_OF_RESOURCES;\r
551 }\r
552\r
553 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
554 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
555\r
a9e7937a 556 KeyOptions = KeyOption->KeyData;\r
5c08e117 557\r
a9e7937a 558 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
5c08e117 559\r
560 //\r
561 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
562 //\r
a9e7937a 563 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
564 if (KeyOptions.Options.ShiftPressed) {\r
565 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
566 }\r
567 if (KeyOptions.Options.ControlPressed) {\r
568 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
569 }\r
570 if (KeyOptions.Options.AltPressed) {\r
571 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
572 }\r
573 if (KeyOptions.Options.LogoPressed) {\r
574 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
575 }\r
576 if (KeyOptions.Options.MenuPressed) {\r
577 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
578 }\r
579 if (KeyOptions.Options.SysReqPressed) {\r
580 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
581 }\r
582\r
5c08e117 583\r
584 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
585\r
586 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
587\r
588 Index = 0;\r
589 KeyData = &HotkeyLeft->KeyData[0];\r
590 do {\r
591 //\r
592 // If Key CodeCount is 0, then only KeyData[0] is used;\r
593 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
594 //\r
595 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
596 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
597 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
598\r
599 Index++;\r
600 KeyData++;\r
601 } while (Index < HotkeyLeft->CodeCount);\r
602 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
603\r
604 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
605 //\r
606 // Need an extra hotkey for shift key on right\r
607 //\r
608 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
609 if (HotkeyRight == NULL) {\r
610 return EFI_OUT_OF_RESOURCES;\r
611 }\r
612\r
613 Index = 0;\r
614 KeyData = &HotkeyRight->KeyData[0];\r
615 do {\r
616 //\r
617 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
618 // only need to update KeyState.KeyShiftState\r
619 //\r
620 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
621\r
622 Index++;\r
623 KeyData++;\r
624 } while (Index < HotkeyRight->CodeCount);\r
625 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
626 }\r
627\r
628 return EFI_SUCCESS;\r
629}\r
630\r
631/**\r
632\r
633 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
634\r
635 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
636 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
637**/\r
638EFI_STATUS\r
639InitializeHotkeyService (\r
640 VOID\r
641 )\r
642{\r
643 EFI_STATUS Status;\r
644 UINT32 BootOptionSupport;\r
645 UINT16 *KeyOrder;\r
646 UINTN KeyOrderSize;\r
647 UINTN Index;\r
648 UINT16 KeyOptionName[8];\r
649 UINTN KeyOptionSize;\r
650 EFI_KEY_OPTION *KeyOption;\r
651\r
652 //\r
653 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
a9e7937a 654 // with maximum number of key presses of 3\r
5c08e117 655 //\r
656 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
a9e7937a 657 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
5c08e117 658 Status = gRT->SetVariable (\r
659 L"BootOptionSupport",\r
660 &gEfiGlobalVariableGuid,\r
a9e7937a 661 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
5c08e117 662 sizeof (UINT32),\r
663 &BootOptionSupport\r
664 );\r
665\r
666 //\r
667 // Get valid Key Option List from private EFI variable "KeyOrder"\r
668 //\r
669 KeyOrder = BdsLibGetVariableAndSize (\r
670 VAR_KEY_ORDER,\r
671 &gEfiGlobalVariableGuid,\r
672 &KeyOrderSize\r
673 );\r
674\r
675 if (KeyOrder == NULL) {\r
676 return EFI_NOT_FOUND;\r
677 }\r
678\r
679 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
680 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
681 KeyOption = BdsLibGetVariableAndSize (\r
682 KeyOptionName,\r
683 &gEfiGlobalVariableGuid,\r
684 &KeyOptionSize\r
685 );\r
686\r
687 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
688 UnregisterHotkey (KeyOrder[Index]);\r
689 } else {\r
690 HotkeyInsertList (KeyOption);\r
691 }\r
692 }\r
693\r
694 //\r
695 // Register Protocol notify for Hotkey service\r
696 //\r
697 Status = gBS->CreateEvent (\r
698 EVT_NOTIFY_SIGNAL,\r
699 TPL_CALLBACK,\r
700 HotkeyEvent,\r
701 NULL,\r
702 &mHotkeyEvent\r
703 );\r
704 ASSERT_EFI_ERROR (Status);\r
705\r
706 //\r
707 // Register for protocol notifications on this event\r
708 //\r
709 Status = gBS->RegisterProtocolNotify (\r
710 &gEfiSimpleTextInputExProtocolGuid,\r
711 mHotkeyEvent,\r
712 &mHotkeyRegistration\r
713 );\r
714 ASSERT_EFI_ERROR (Status);\r
715\r
716 return Status;\r
717}\r
718\r