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