]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/Hotkey.c
Fixed OPTIONAL/comma issue
[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 Check if the Key Option is valid or not.\r
27\r
b30312ba 28 @param KeyOption The Hot Key Option to be checked.\r
93e3992d 29\r
b30312ba 30 @retval TRUE The Hot Key Option is valid.\r
31 @retval FALSE The Hot Key Option is invalid.\r
93e3992d 32\r
b30312ba 33**/\r
34BOOLEAN\r
35IsKeyOptionValid (\r
36 IN EFI_KEY_OPTION *KeyOption\r
37)\r
93e3992d 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
b30312ba 67/**\r
93e3992d 68 Create Key#### for the given hotkey.\r
69\r
b30312ba 70 @param KeyOption The Hot Key Option to be added.\r
71 @param KeyOptionNumber The key option number for Key#### (optional).\r
93e3992d 72\r
b30312ba 73 @retval EFI_SUCCESS Register hotkey successfully.\r
74 @retval EFI_INVALID_PARAMETER The hotkey option is invalid.\r
98cf9347 75 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
93e3992d 76\r
b30312ba 77**/\r
78EFI_STATUS\r
79RegisterHotkey (\r
80 IN EFI_KEY_OPTION *KeyOption,\r
81 OUT UINT16 *KeyOptionNumber\r
82)\r
93e3992d 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
9614285e 104 KeyOptionSize = sizeof (EFI_KEY_OPTION) + GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) * sizeof (EFI_INPUT_KEY);\r
93e3992d 105 UpdateBootOption = FALSE;\r
106\r
107 //\r
108 // check whether HotKey conflict with keys used by Setup Browser\r
109 //\r
93e3992d 110 KeyOrder = BdsLibGetVariableAndSize (\r
b4489769 111 VAR_KEY_ORDER,\r
93e3992d 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
9614285e
LG
145 if (KeyOption->KeyData.PackedValue == TempOption->KeyData.PackedValue) {\r
146 if (GET_KEY_CODE_COUNT (KeyOption->KeyData.PackedValue) == 0 ||\r
93e3992d 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
98cf9347 186 FreePool (KeyOrder);\r
93e3992d 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
98cf9347 200 FreePool (KeyOrder);\r
93e3992d 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
b4489769 211 VAR_KEY_ORDER,\r
93e3992d 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
b30312ba 224/**\r
93e3992d 225\r
226 Delete Key#### for the given Key Option number.\r
227\r
b30312ba 228 @param KeyOptionNumber Key option number for Key####\r
93e3992d 229\r
b30312ba 230 @retval EFI_SUCCESS Unregister hotkey successfully.\r
231 @retval EFI_NOT_FOUND No Key#### is found for the given Key Option number.\r
93e3992d 232\r
b30312ba 233**/\r
234EFI_STATUS\r
235UnregisterHotkey (\r
236 IN UINT16 KeyOptionNumber\r
237)\r
93e3992d 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
b4489769 262 VAR_KEY_ORDER,\r
93e3992d 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
b4489769 290 VAR_KEY_ORDER,\r
93e3992d 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
b30312ba 302/**\r
93e3992d 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
b30312ba 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
93e3992d 309\r
98cf9347 310 @retval EFI_SUCCESS KeyData is successfully processed.\r
93e3992d 311\r
b30312ba 312**/\r
313EFI_STATUS\r
314HotkeyCallback (\r
315 IN EFI_KEY_DATA *KeyData\r
316)\r
93e3992d 317{\r
318 BOOLEAN HotkeyCatched;\r
319 LIST_ENTRY BootLists;\r
320 LIST_ENTRY *Link;\r
321 BDS_HOTKEY_OPTION *Hotkey;\r
322 UINT16 Buffer[10];\r
323 BDS_COMMON_OPTION *BootOption;\r
324 UINTN ExitDataSize;\r
325 CHAR16 *ExitData;\r
93e3992d 326 EFI_STATUS Status;\r
327 EFI_KEY_DATA *HotkeyData;\r
328\r
329 if (mHotkeyCallbackPending) {\r
330 //\r
331 // When responsing to a Hotkey, ignore sequential hotkey stroke until\r
332 // the current Boot#### load option returned\r
333 //\r
334 return EFI_SUCCESS;\r
335 }\r
336\r
337 Status = EFI_SUCCESS;\r
338 Link = GetFirstNode (&mHotkeyList);\r
339\r
340 while (!IsNull (&mHotkeyList, Link)) {\r
341 HotkeyCatched = FALSE;\r
342 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
343\r
344 //\r
345 // Is this Key Stroke we are waiting for?\r
346 //\r
347 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
348 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
349 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
350 ((HotkeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) ? (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : 1)) {\r
351 //\r
352 // Receive an expecting key stroke\r
353 //\r
354 if (Hotkey->CodeCount > 1) {\r
355 //\r
356 // For hotkey of key combination, transit to next waiting state\r
357 //\r
358 Hotkey->WaitingKey++;\r
359\r
360 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
361 //\r
362 // Received the whole key stroke sequence\r
363 //\r
364 HotkeyCatched = TRUE;\r
365 }\r
366 } else {\r
367 //\r
368 // For hotkey of single key stroke\r
369 //\r
370 HotkeyCatched = TRUE;\r
371 }\r
372 } else {\r
373 //\r
374 // Receive an unexpected key stroke, reset to initial waiting state\r
375 //\r
376 Hotkey->WaitingKey = 0;\r
377 }\r
378\r
379 if (HotkeyCatched) {\r
380 //\r
381 // Reset to initial waiting state\r
382 //\r
383 Hotkey->WaitingKey = 0;\r
384\r
385 //\r
386 // Launch its BootOption\r
387 //\r
388 InitializeListHead (&BootLists);\r
389\r
390 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
391 BootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
392 BootOption->BootCurrent = Hotkey->BootOptionNumber;\r
393 BdsLibConnectDevicePath (BootOption->DevicePath);\r
394\r
395 //\r
396 // Clear the screen before launch this BootOption\r
397 //\r
398 gST->ConOut->Reset (gST->ConOut, FALSE);\r
399\r
93e3992d 400 mHotkeyCallbackPending = TRUE;\r
401 Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData);\r
402 mHotkeyCallbackPending = FALSE;\r
403\r
93e3992d 404 if (EFI_ERROR (Status)) {\r
405 //\r
406 // Call platform action to indicate the boot fail\r
407 //\r
408 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
409 PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize);\r
410 } else {\r
411 //\r
412 // Call platform action to indicate the boot success\r
413 //\r
414 BootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
415 PlatformBdsBootSuccess (BootOption);\r
416 }\r
417 }\r
418\r
419 Link = GetNextNode (&mHotkeyList, Link);\r
420 }\r
421\r
422 return Status;\r
423}\r
424\r
b30312ba 425/**\r
93e3992d 426 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
427\r
b30312ba 428 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
93e3992d 429\r
b30312ba 430 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
431 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
93e3992d 432\r
b30312ba 433**/\r
434EFI_STATUS\r
435HotkeyRegisterNotify (\r
436 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
437)\r
93e3992d 438{\r
439 UINTN Index;\r
440 EFI_STATUS Status;\r
441 LIST_ENTRY *Link;\r
442 BDS_HOTKEY_OPTION *Hotkey;\r
443\r
444 //\r
445 // Register notification function for each hotkey\r
446 //\r
447 Link = GetFirstNode (&mHotkeyList);\r
448\r
449 while (!IsNull (&mHotkeyList, Link)) {\r
450 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
451\r
452 Index = 0;\r
453 do {\r
454 Status = SimpleTextInEx->RegisterKeyNotify (\r
455 SimpleTextInEx,\r
456 &Hotkey->KeyData[Index],\r
457 HotkeyCallback,\r
458 &Hotkey->NotifyHandle\r
459 );\r
460 if (EFI_ERROR (Status)) {\r
461 //\r
462 // some of the hotkey registry failed\r
463 //\r
464 return Status;\r
465 }\r
466 Index ++;\r
467 } while (Index < Hotkey->CodeCount);\r
468\r
469 Link = GetNextNode (&mHotkeyList, Link);\r
470 }\r
471\r
472 return EFI_SUCCESS;\r
473}\r
474\r
b30312ba 475/**\r
476 Callback function for SimpleTextInEx protocol install events\r
477\r
b30312ba 478 @param Event the event that is signaled.\r
479 @param Context not used here.\r
480\r
b30312ba 481**/\r
93e3992d 482VOID\r
483EFIAPI\r
484HotkeyEvent (\r
485 IN EFI_EVENT Event,\r
486 IN VOID *Context\r
487 )\r
93e3992d 488{\r
489 EFI_STATUS Status;\r
490 UINTN BufferSize;\r
491 EFI_HANDLE Handle;\r
492 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
493\r
494 while (TRUE) {\r
495 BufferSize = sizeof (EFI_HANDLE);\r
496 Status = gBS->LocateHandle (\r
497 ByRegisterNotify,\r
498 NULL,\r
499 mHotkeyRegistration,\r
500 &BufferSize,\r
501 &Handle\r
502 );\r
503 if (EFI_ERROR (Status)) {\r
504 //\r
505 // If no more notification events exist\r
506 //\r
507 return ;\r
508 }\r
509\r
510 Status = gBS->HandleProtocol (\r
511 Handle,\r
512 &gEfiSimpleTextInputExProtocolGuid,\r
513 (VOID **) &SimpleTextInEx\r
514 );\r
515 ASSERT_EFI_ERROR (Status);\r
516\r
517 HotkeyRegisterNotify (SimpleTextInEx);\r
518 }\r
519}\r
520\r
b30312ba 521/**\r
93e3992d 522 Insert Key Option to hotkey list.\r
523\r
b30312ba 524 @param KeyOption The Hot Key Option to be added to hotkey list.\r
93e3992d 525\r
98cf9347 526 @retval EFI_SUCCESS Add to hotkey list success.\r
527 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
b30312ba 528**/\r
529EFI_STATUS\r
530HotkeyInsertList (\r
531 IN EFI_KEY_OPTION *KeyOption\r
532)\r
93e3992d 533{\r
534 BDS_HOTKEY_OPTION *HotkeyLeft;\r
535 BDS_HOTKEY_OPTION *HotkeyRight;\r
536 UINTN Index;\r
537 UINT32 KeyOptions;\r
538 UINT32 KeyShiftStateLeft;\r
539 UINT32 KeyShiftStateRight;\r
540 EFI_INPUT_KEY *InputKey;\r
541 EFI_KEY_DATA *KeyData;\r
542\r
543 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
544 if (HotkeyLeft == NULL) {\r
545 return EFI_OUT_OF_RESOURCES;\r
546 }\r
547\r
548 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
549 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
550\r
9614285e 551 KeyOptions = KeyOption->KeyData.PackedValue;\r
93e3992d 552\r
553 HotkeyLeft->CodeCount = (UINT8) GET_KEY_CODE_COUNT (KeyOptions);\r
554\r
555 //\r
556 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
557 //\r
558 KeyShiftStateRight = (KeyOptions & EFI_KEY_OPTION_SHIFT) |\r
559 ((KeyOptions & EFI_KEY_OPTION_CONTROL) << 1) |\r
560 ((KeyOptions & EFI_KEY_OPTION_ALT) << 2) |\r
561 ((KeyOptions & EFI_KEY_OPTION_LOGO) << 3) |\r
562 ((KeyOptions & (EFI_KEY_OPTION_MENU | EFI_KEY_OPTION_SYSREQ)) << 4) |\r
563 EFI_SHIFT_STATE_VALID;\r
564\r
565 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
566\r
567 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
568\r
569 Index = 0;\r
570 KeyData = &HotkeyLeft->KeyData[0];\r
571 do {\r
572 //\r
573 // If Key CodeCount is 0, then only KeyData[0] is used;\r
574 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
575 //\r
576 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
577 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
578 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
579\r
580 Index++;\r
581 KeyData++;\r
582 } while (Index < HotkeyLeft->CodeCount);\r
583 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
584\r
585 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
586 //\r
587 // Need an extra hotkey for shift key on right\r
588 //\r
589 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
590 if (HotkeyRight == NULL) {\r
591 return EFI_OUT_OF_RESOURCES;\r
592 }\r
593\r
594 Index = 0;\r
595 KeyData = &HotkeyRight->KeyData[0];\r
596 do {\r
597 //\r
598 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
599 // only need to update KeyState.KeyShiftState\r
600 //\r
601 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
602\r
603 Index++;\r
604 KeyData++;\r
605 } while (Index < HotkeyRight->CodeCount);\r
606 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
607 }\r
608\r
609 return EFI_SUCCESS;\r
610}\r
611\r
b30312ba 612/**\r
93e3992d 613\r
614 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
615\r
b30312ba 616 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
30394aa1 617 @retval EFI_NOT_FOUND Can not find the "KeyOrder" variable\r
b30312ba 618**/\r
619EFI_STATUS\r
620InitializeHotkeyService (\r
621 VOID\r
622 )\r
93e3992d 623{\r
624 EFI_STATUS Status;\r
625 UINT32 BootOptionSupport;\r
626 UINT16 *KeyOrder;\r
627 UINTN KeyOrderSize;\r
628 UINTN Index;\r
629 UINT16 KeyOptionName[8];\r
630 UINTN KeyOptionSize;\r
631 EFI_KEY_OPTION *KeyOption;\r
632\r
633 //\r
634 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP\r
635 //\r
636 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_KEY | EFI_BOOT_OPTION_SUPPORT_APP;\r
637 Status = gRT->SetVariable (\r
638 L"BootOptionSupport",\r
639 &gEfiGlobalVariableGuid,\r
640 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
641 sizeof (UINT32),\r
642 &BootOptionSupport\r
643 );\r
644\r
645 //\r
646 // Get valid Key Option List from private EFI variable "KeyOrder"\r
647 //\r
648 KeyOrder = BdsLibGetVariableAndSize (\r
b4489769 649 VAR_KEY_ORDER,\r
93e3992d 650 &gEfiGlobalVariableGuid,\r
651 &KeyOrderSize\r
652 );\r
653\r
654 if (KeyOrder == NULL) {\r
655 return EFI_NOT_FOUND;\r
656 }\r
657\r
658 for (Index = 0; Index < KeyOrderSize / sizeof (UINT16); Index ++) {\r
659 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOrder[Index]);\r
660 KeyOption = BdsLibGetVariableAndSize (\r
661 KeyOptionName,\r
662 &gEfiGlobalVariableGuid,\r
663 &KeyOptionSize\r
664 );\r
665\r
666 if (KeyOption == NULL || !IsKeyOptionValid (KeyOption)) {\r
667 UnregisterHotkey (KeyOrder[Index]);\r
668 } else {\r
669 HotkeyInsertList (KeyOption);\r
670 }\r
671 }\r
672\r
673 //\r
674 // Register Protocol notify for Hotkey service\r
675 //\r
676 Status = gBS->CreateEvent (\r
677 EVT_NOTIFY_SIGNAL,\r
678 TPL_CALLBACK,\r
679 HotkeyEvent,\r
680 NULL,\r
681 &mHotkeyEvent\r
682 );\r
683 ASSERT_EFI_ERROR (Status);\r
684\r
685 //\r
686 // Register for protocol notifications on this event\r
687 //\r
688 Status = gBS->RegisterProtocolNotify (\r
689 &gEfiSimpleTextInputExProtocolGuid,\r
690 mHotkeyEvent,\r
691 &mHotkeyRegistration\r
692 );\r
693 ASSERT_EFI_ERROR (Status);\r
694\r
695 return Status;\r
696}\r
697\r