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