]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
Add BootlogoOnly feature in BDS for BGRT
[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
2df686c6 5Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>\r
180a5a35 6This program and the accompanying materials\r
5c08e117 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
d394581d
RN
19LIST_ENTRY mHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mHotkeyList);\r
20BDS_COMMON_OPTION *mHotkeyBootOption = NULL;\r
21EFI_EVENT mHotkeyEvent;\r
22VOID *mHotkeyRegistration;\r
5c08e117 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
ce5fad41 135 ASSERT (TempOption != NULL);\r
5c08e117 136\r
137 if (CompareMem (TempOption, KeyOption, TempOptionSize) == 0) {\r
138 //\r
139 // Got the option, so just return\r
140 //\r
141 FreePool (TempOption);\r
142 FreePool (KeyOrder);\r
143 return EFI_SUCCESS;\r
144 }\r
145\r
146 if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
a9e7937a 147 if (KeyOption->KeyData.Options.InputKeyCount == 0 ||\r
5c08e117 148 CompareMem (\r
149 ((UINT8 *) TempOption) + sizeof (EFI_KEY_OPTION),\r
150 ((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION),\r
151 KeyOptionSize - sizeof (EFI_KEY_OPTION)\r
152 ) == 0) {\r
153 //\r
154 // Hotkey is the same but BootOption changed, need update\r
155 //\r
156 UpdateBootOption = TRUE;\r
157 break;\r
158 }\r
159 }\r
160\r
161 FreePool (TempOption);\r
162 }\r
163\r
164 if (UpdateBootOption) {\r
165 RegisterOptionNumber = KeyOrder[Index];\r
166 FreePool (TempOption);\r
167 } else {\r
168 RegisterOptionNumber = (UINT16) (MaxOptionNumber + 1);\r
169 }\r
170\r
171 if (KeyOptionNumber != NULL) {\r
172 *KeyOptionNumber = RegisterOptionNumber;\r
173 }\r
174\r
175 //\r
176 // Create variable Key####\r
177 //\r
178 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", RegisterOptionNumber);\r
179 Status = gRT->SetVariable (\r
180 KeyOptionName,\r
181 &gEfiGlobalVariableGuid,\r
182 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
183 KeyOptionSize,\r
184 KeyOption\r
185 );\r
186 if (EFI_ERROR (Status)) {\r
187 FreePool (KeyOrder);\r
188 return Status;\r
189 }\r
190\r
191 //\r
192 // Update the key order variable - "KeyOrder"\r
193 //\r
194 if (!UpdateBootOption) {\r
195 Index = KeyOrderSize / sizeof (UINT16);\r
196 KeyOrderSize += sizeof (UINT16);\r
197 }\r
198\r
199 NewKeyOrder = AllocatePool (KeyOrderSize);\r
200 if (NewKeyOrder == NULL) {\r
201 FreePool (KeyOrder);\r
202 return EFI_OUT_OF_RESOURCES;\r
203 }\r
204\r
205 if (KeyOrder != NULL) {\r
206 CopyMem (NewKeyOrder, KeyOrder, KeyOrderSize);\r
207 }\r
208\r
209 NewKeyOrder[Index] = RegisterOptionNumber;\r
210\r
211 Status = gRT->SetVariable (\r
212 VAR_KEY_ORDER,\r
213 &gEfiGlobalVariableGuid,\r
214 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
215 KeyOrderSize,\r
216 NewKeyOrder\r
217 );\r
218\r
219 FreePool (KeyOrder);\r
220 FreePool (NewKeyOrder);\r
221\r
222 return Status;\r
223}\r
224\r
225/**\r
226\r
227 Delete Key#### for the given Key Option number.\r
228\r
229 @param KeyOptionNumber Key option number for Key####\r
230\r
231 @retval EFI_SUCCESS Unregister hotkey successfully.\r
232 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
233\r
234**/\r
235EFI_STATUS\r
236UnregisterHotkey (\r
237 IN UINT16 KeyOptionNumber\r
238)\r
239{\r
240 UINT16 KeyOption[10];\r
241 UINTN Index;\r
242 EFI_STATUS Status;\r
243 UINTN Index2Del;\r
244 UINT16 *KeyOrder;\r
245 UINTN KeyOrderSize;\r
246\r
247 //\r
248 // Delete variable Key####\r
249 //\r
250 UnicodeSPrint (KeyOption, sizeof (KeyOption), L"Key%04x", KeyOptionNumber);\r
251 gRT->SetVariable (\r
252 KeyOption,\r
253 &gEfiGlobalVariableGuid,\r
254 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
255 0,\r
256 NULL\r
257 );\r
258\r
259 //\r
260 // Adjust key order array\r
261 //\r
262 KeyOrder = BdsLibGetVariableAndSize (\r
263 VAR_KEY_ORDER,\r
264 &gEfiGlobalVariableGuid,\r
265 &KeyOrderSize\r
266 );\r
267 if (KeyOrder == NULL) {\r
268 return EFI_SUCCESS;\r
269 }\r
270\r
271 Index2Del = 0;\r
272 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index++) {\r
273 if (KeyOrder[Index] == KeyOptionNumber) {\r
274 Index2Del = Index;\r
275 break;\r
276 }\r
277 }\r
278\r
279 if (Index != KeyOrderSize / sizeof (UINT16)) {\r
280 //\r
281 // KeyOptionNumber found in "KeyOrder", delete it\r
282 //\r
283 for (Index = Index2Del; Index < KeyOrderSize / sizeof (UINT16) - 1; Index++) {\r
284 KeyOrder[Index] = KeyOrder[Index + 1];\r
285 }\r
286\r
287 KeyOrderSize -= sizeof (UINT16);\r
288 }\r
289\r
290 Status = gRT->SetVariable (\r
291 VAR_KEY_ORDER,\r
292 &gEfiGlobalVariableGuid,\r
293 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
294 KeyOrderSize,\r
295 KeyOrder\r
296 );\r
297\r
298 FreePool (KeyOrder);\r
299\r
300 return Status;\r
301}\r
302\r
d394581d
RN
303/**\r
304 Try to boot the boot option triggered by hotkey.\r
2df686c6 305 @retval EFI_SUCCESS There is HotkeyBootOption & it is processed\r
306 @retval EFI_NOT_FOUND There is no HotkeyBootOption\r
d394581d 307**/\r
2df686c6 308EFI_STATUS\r
d394581d
RN
309HotkeyBoot (\r
310 VOID\r
311 )\r
2df686c6 312{ \r
d394581d
RN
313 EFI_STATUS Status;\r
314 UINTN ExitDataSize;\r
315 CHAR16 *ExitData;\r
2df686c6 316\r
317 if (mHotkeyBootOption == NULL) {\r
318 return EFI_NOT_FOUND;\r
319 } \r
d394581d 320 \r
2df686c6 321 BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
322\r
323 //\r
324 // Clear the screen before launch this BootOption\r
325 //\r
326 gST->ConOut->Reset (gST->ConOut, FALSE);\r
327\r
328 Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\r
d394581d 329\r
2df686c6 330 if (EFI_ERROR (Status)) {\r
d394581d 331 //\r
2df686c6 332 // Call platform action to indicate the boot fail\r
d394581d 333 //\r
2df686c6 334 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
335 PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);\r
336 } else {\r
337 //\r
338 // Call platform action to indicate the boot success\r
339 //\r
340 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
341 PlatformBdsBootSuccess (mHotkeyBootOption);\r
342 }\r
343 FreePool (mHotkeyBootOption->Description);\r
344 FreePool (mHotkeyBootOption->DevicePath);\r
345 FreePool (mHotkeyBootOption->LoadOptions);\r
346 FreePool (mHotkeyBootOption);\r
d394581d 347\r
2df686c6 348 mHotkeyBootOption = NULL;\r
d394581d 349\r
2df686c6 350 return EFI_SUCCESS;\r
d394581d
RN
351}\r
352\r
5c08e117 353/**\r
354\r
355 This is the common notification function for HotKeys, it will be registered\r
356 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
357\r
358 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
359 information for the key that was pressed.\r
360\r
361 @retval EFI_SUCCESS KeyData is successfully processed.\r
362 @return EFI_NOT_FOUND Fail to find boot option variable.\r
363**/\r
364EFI_STATUS\r
6ba0bc7c 365EFIAPI\r
5c08e117 366HotkeyCallback (\r
367 IN EFI_KEY_DATA *KeyData\r
368)\r
369{\r
370 BOOLEAN HotkeyCatched;\r
371 LIST_ENTRY BootLists;\r
372 LIST_ENTRY *Link;\r
373 BDS_HOTKEY_OPTION *Hotkey;\r
374 UINT16 Buffer[10];\r
5c08e117 375 EFI_STATUS Status;\r
376 EFI_KEY_DATA *HotkeyData;\r
377\r
d394581d 378 if (mHotkeyBootOption != NULL) {\r
5c08e117 379 //\r
d394581d 380 // Do not process sequential hotkey stroke until the current boot option returns\r
5c08e117 381 //\r
382 return EFI_SUCCESS;\r
383 }\r
384\r
d394581d 385 Status = EFI_SUCCESS;\r
5c08e117 386\r
d394581d
RN
387 for ( Link = GetFirstNode (&mHotkeyList)\r
388 ; !IsNull (&mHotkeyList, Link)\r
389 ; Link = GetNextNode (&mHotkeyList, Link)\r
390 ) {\r
5c08e117 391 HotkeyCatched = FALSE;\r
392 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
393\r
394 //\r
395 // Is this Key Stroke we are waiting for?\r
396 //\r
397 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
398 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
399 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
d394581d
RN
400 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
401 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
402 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
403 )\r
404 ) {\r
5c08e117 405 //\r
d394581d 406 // For hotkey of key combination, transit to next waiting state\r
5c08e117 407 //\r
d394581d 408 Hotkey->WaitingKey++;\r
5c08e117 409\r
d394581d 410 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
5c08e117 411 //\r
d394581d 412 // Received the whole key stroke sequence\r
5c08e117 413 //\r
414 HotkeyCatched = TRUE;\r
415 }\r
416 } else {\r
417 //\r
418 // Receive an unexpected key stroke, reset to initial waiting state\r
419 //\r
420 Hotkey->WaitingKey = 0;\r
421 }\r
422\r
423 if (HotkeyCatched) {\r
424 //\r
425 // Reset to initial waiting state\r
426 //\r
427 Hotkey->WaitingKey = 0;\r
428\r
429 //\r
430 // Launch its BootOption\r
431 //\r
432 InitializeListHead (&BootLists);\r
433\r
434 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
d394581d 435 mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
5c08e117 436 }\r
5c08e117 437 }\r
438\r
439 return Status;\r
440}\r
441\r
442/**\r
443 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
444\r
445 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
446\r
447 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
448 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
449\r
450**/\r
451EFI_STATUS\r
452HotkeyRegisterNotify (\r
453 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
454)\r
455{\r
456 UINTN Index;\r
457 EFI_STATUS Status;\r
458 LIST_ENTRY *Link;\r
459 BDS_HOTKEY_OPTION *Hotkey;\r
460\r
461 //\r
462 // Register notification function for each hotkey\r
463 //\r
464 Link = GetFirstNode (&mHotkeyList);\r
465\r
466 while (!IsNull (&mHotkeyList, Link)) {\r
467 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
468\r
469 Index = 0;\r
470 do {\r
471 Status = SimpleTextInEx->RegisterKeyNotify (\r
472 SimpleTextInEx,\r
473 &Hotkey->KeyData[Index],\r
474 HotkeyCallback,\r
475 &Hotkey->NotifyHandle\r
476 );\r
477 if (EFI_ERROR (Status)) {\r
478 //\r
479 // some of the hotkey registry failed\r
480 //\r
481 return Status;\r
482 }\r
483 Index ++;\r
84fa6c17 484 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));\r
5c08e117 485\r
486 Link = GetNextNode (&mHotkeyList, Link);\r
487 }\r
488\r
489 return EFI_SUCCESS;\r
490}\r
491\r
492/**\r
493 Callback function for SimpleTextInEx protocol install events\r
494\r
495 @param Event the event that is signaled.\r
496 @param Context not used here.\r
497\r
498**/\r
499VOID\r
500EFIAPI\r
501HotkeyEvent (\r
502 IN EFI_EVENT Event,\r
503 IN VOID *Context\r
504 )\r
505{\r
506 EFI_STATUS Status;\r
507 UINTN BufferSize;\r
508 EFI_HANDLE Handle;\r
509 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
510\r
511 while (TRUE) {\r
512 BufferSize = sizeof (EFI_HANDLE);\r
513 Status = gBS->LocateHandle (\r
514 ByRegisterNotify,\r
515 NULL,\r
516 mHotkeyRegistration,\r
517 &BufferSize,\r
518 &Handle\r
519 );\r
520 if (EFI_ERROR (Status)) {\r
521 //\r
522 // If no more notification events exist\r
523 //\r
524 return ;\r
525 }\r
526\r
527 Status = gBS->HandleProtocol (\r
528 Handle,\r
529 &gEfiSimpleTextInputExProtocolGuid,\r
530 (VOID **) &SimpleTextInEx\r
531 );\r
532 ASSERT_EFI_ERROR (Status);\r
533\r
534 HotkeyRegisterNotify (SimpleTextInEx);\r
535 }\r
536}\r
537\r
538/**\r
539 Insert Key Option to hotkey list.\r
540\r
541 @param KeyOption The Hot Key Option to be added to hotkey list.\r
542\r
543 @retval EFI_SUCCESS Add to hotkey list success.\r
544 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
545**/\r
546EFI_STATUS\r
547HotkeyInsertList (\r
548 IN EFI_KEY_OPTION *KeyOption\r
549)\r
550{\r
551 BDS_HOTKEY_OPTION *HotkeyLeft;\r
552 BDS_HOTKEY_OPTION *HotkeyRight;\r
553 UINTN Index;\r
a9e7937a 554 EFI_BOOT_KEY_DATA KeyOptions;\r
5c08e117 555 UINT32 KeyShiftStateLeft;\r
556 UINT32 KeyShiftStateRight;\r
557 EFI_INPUT_KEY *InputKey;\r
558 EFI_KEY_DATA *KeyData;\r
559\r
560 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
561 if (HotkeyLeft == NULL) {\r
562 return EFI_OUT_OF_RESOURCES;\r
563 }\r
564\r
565 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
566 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
567\r
a9e7937a 568 KeyOptions = KeyOption->KeyData;\r
5c08e117 569\r
a9e7937a 570 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
5c08e117 571\r
572 //\r
573 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
574 //\r
a9e7937a 575 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
576 if (KeyOptions.Options.ShiftPressed) {\r
577 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
578 }\r
579 if (KeyOptions.Options.ControlPressed) {\r
580 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
581 }\r
582 if (KeyOptions.Options.AltPressed) {\r
583 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
584 }\r
585 if (KeyOptions.Options.LogoPressed) {\r
586 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
587 }\r
588 if (KeyOptions.Options.MenuPressed) {\r
589 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
590 }\r
591 if (KeyOptions.Options.SysReqPressed) {\r
592 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
593 }\r
594\r
5c08e117 595\r
596 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
597\r
598 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
599\r
600 Index = 0;\r
601 KeyData = &HotkeyLeft->KeyData[0];\r
602 do {\r
603 //\r
604 // If Key CodeCount is 0, then only KeyData[0] is used;\r
605 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
606 //\r
607 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
608 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
609 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
610\r
611 Index++;\r
612 KeyData++;\r
613 } while (Index < HotkeyLeft->CodeCount);\r
614 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
615\r
616 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
617 //\r
618 // Need an extra hotkey for shift key on right\r
619 //\r
620 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
621 if (HotkeyRight == NULL) {\r
622 return EFI_OUT_OF_RESOURCES;\r
623 }\r
624\r
625 Index = 0;\r
626 KeyData = &HotkeyRight->KeyData[0];\r
627 do {\r
628 //\r
629 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
630 // only need to update KeyState.KeyShiftState\r
631 //\r
632 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
633\r
634 Index++;\r
635 KeyData++;\r
636 } while (Index < HotkeyRight->CodeCount);\r
637 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
638 }\r
639\r
640 return EFI_SUCCESS;\r
641}\r
642\r
643/**\r
644\r
645 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
646\r
647 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
648 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
649**/\r
650EFI_STATUS\r
651InitializeHotkeyService (\r
652 VOID\r
653 )\r
654{\r
655 EFI_STATUS Status;\r
656 UINT32 BootOptionSupport;\r
657 UINT16 *KeyOrder;\r
658 UINTN KeyOrderSize;\r
659 UINTN Index;\r
660 UINT16 KeyOptionName[8];\r
661 UINTN KeyOptionSize;\r
662 EFI_KEY_OPTION *KeyOption;\r
663\r
664 //\r
665 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
a9e7937a 666 // with maximum number of key presses of 3\r
5c08e117 667 //\r
668 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
a9e7937a 669 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
5c08e117 670 Status = gRT->SetVariable (\r
671 L"BootOptionSupport",\r
672 &gEfiGlobalVariableGuid,\r
a9e7937a 673 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
5c08e117 674 sizeof (UINT32),\r
675 &BootOptionSupport\r
676 );\r
677\r
678 //\r
679 // Get valid Key Option List from private EFI variable "KeyOrder"\r
680 //\r
681 KeyOrder = BdsLibGetVariableAndSize (\r
682 VAR_KEY_ORDER,\r
683 &gEfiGlobalVariableGuid,\r
684 &KeyOrderSize\r
685 );\r
686\r
687 if (KeyOrder == NULL) {\r
688 return EFI_NOT_FOUND;\r
689 }\r
690\r
691 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
692 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
693 KeyOption = BdsLibGetVariableAndSize (\r
694 KeyOptionName,\r
695 &gEfiGlobalVariableGuid,\r
696 &KeyOptionSize\r
697 );\r
698\r
699 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
700 UnregisterHotkey (KeyOrder[Index]);\r
701 } else {\r
702 HotkeyInsertList (KeyOption);\r
703 }\r
704 }\r
705\r
706 //\r
707 // Register Protocol notify for Hotkey service\r
708 //\r
709 Status = gBS->CreateEvent (\r
710 EVT_NOTIFY_SIGNAL,\r
711 TPL_CALLBACK,\r
712 HotkeyEvent,\r
713 NULL,\r
714 &mHotkeyEvent\r
715 );\r
716 ASSERT_EFI_ERROR (Status);\r
717\r
718 //\r
719 // Register for protocol notifications on this event\r
720 //\r
721 Status = gBS->RegisterProtocolNotify (\r
722 &gEfiSimpleTextInputExProtocolGuid,\r
723 mHotkeyEvent,\r
724 &mHotkeyRegistration\r
725 );\r
726 ASSERT_EFI_ERROR (Status);\r
727\r
728 return Status;\r
729}\r
730\r