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