]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/UefiBootManagerLib/BmHotkey.c
IntelFrameworkPkg UefiLib: Make the event empty function public
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmHotkey.c
CommitLineData
067ed98a
RN
1/** @file\r
2 Hotkey library functions.\r
3\r
2d15a830 4Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
065e587c 5(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
067ed98a
RN
6This 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
14**/\r
15\r
16#include "InternalBm.h"\r
17\r
18//\r
19// Lock for linked list\r
20//\r
21EFI_LOCK mBmHotkeyLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);\r
22LIST_ENTRY mBmHotkeyList = INITIALIZE_LIST_HEAD_VARIABLE (mBmHotkeyList);\r
23EFI_EVENT mBmHotkeyTriggered = NULL;\r
24BOOLEAN mBmHotkeyServiceStarted = FALSE;\r
25UINTN mBmHotkeySupportCount = 0;\r
26\r
27//\r
28// Set OptionNumber as unassigned value to indicate the option isn't initialized\r
29//\r
30EFI_BOOT_MANAGER_LOAD_OPTION mBmHotkeyBootOption = { LoadOptionNumberUnassigned };\r
31\r
32EFI_BOOT_MANAGER_KEY_OPTION *mBmContinueKeyOption = NULL;\r
33VOID *mBmTxtInExRegistration = NULL;\r
34\r
121300c4
RN
35\r
36/**\r
37 Return the buffer size of the EFI_BOOT_MANAGER_KEY_OPTION data.\r
38\r
39 @param KeyOption The input key option info.\r
40\r
41 @retval The buffer size of the key option data.\r
42**/\r
43UINTN\r
44BmSizeOfKeyOption (\r
45 EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
46 )\r
47{\r
48 return OFFSET_OF (EFI_BOOT_MANAGER_KEY_OPTION, Keys)\r
49 + KeyOption->KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY);\r
50}\r
51\r
067ed98a
RN
52/**\r
53\r
54 Check whether the input key option is valid.\r
55\r
121300c4
RN
56 @param KeyOption Key option.\r
57 @param KeyOptionSize Size of the key option.\r
067ed98a
RN
58\r
59 @retval TRUE Input key option is valid.\r
60 @retval FALSE Input key option is not valid.\r
61**/\r
62BOOLEAN\r
63BmIsKeyOptionValid (\r
121300c4
RN
64 IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption,\r
65 IN UINTN KeyOptionSize\r
067ed98a
RN
66)\r
67{\r
f9a24380 68 UINT16 OptionName[BM_OPTION_NAME_LEN];\r
067ed98a
RN
69 UINT8 *BootOption;\r
70 UINTN BootOptionSize;\r
71 UINT32 Crc;\r
72\r
121300c4
RN
73 if (BmSizeOfKeyOption (KeyOption) != KeyOptionSize) {\r
74 return FALSE;\r
75 }\r
76\r
067ed98a
RN
77 //\r
78 // Check whether corresponding Boot Option exist\r
79 //\r
121300c4
RN
80 UnicodeSPrint (\r
81 OptionName, sizeof (OptionName), L"%s%04x",\r
82 mBmLoadOptionName[LoadOptionTypeBoot], KeyOption->BootOption\r
83 );\r
067ed98a
RN
84 GetEfiGlobalVariable2 (OptionName, (VOID **) &BootOption, &BootOptionSize);\r
85\r
86 if (BootOption == NULL) {\r
87 return FALSE;\r
88 }\r
89\r
90 //\r
91 // Check CRC for Boot Option\r
92 //\r
93 gBS->CalculateCrc32 (BootOption, BootOptionSize, &Crc);\r
94 FreePool (BootOption);\r
95\r
96 return (BOOLEAN) (KeyOption->BootOptionCrc == Crc);\r
97}\r
98\r
99/**\r
100\r
101 Check whether the input variable is an key option variable.\r
102\r
103 @param Name Input variable name.\r
104 @param Guid Input variable guid.\r
105 @param OptionNumber The option number of this key option variable.\r
106\r
107 @retval TRUE Input variable is a key option variable.\r
108 @retval FALSE Input variable is not a key option variable.\r
109**/\r
110BOOLEAN\r
111BmIsKeyOptionVariable (\r
112 CHAR16 *Name,\r
113 EFI_GUID *Guid,\r
114 UINT16 *OptionNumber\r
115 )\r
116{\r
117 UINTN Index;\r
418e8cd9 118 UINTN Uint;\r
067ed98a
RN
119 \r
120 if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||\r
121 (StrSize (Name) != sizeof (L"Key####")) ||\r
122 (StrnCmp (Name, L"Key", 3) != 0)\r
123 ) {\r
124 return FALSE;\r
125 }\r
126\r
127 *OptionNumber = 0;\r
128 for (Index = 3; Index < 7; Index++) {\r
418e8cd9
RN
129 Uint = BmCharToUint (Name[Index]);\r
130 if (Uint == -1) {\r
067ed98a 131 return FALSE;\r
418e8cd9
RN
132 } else {\r
133 *OptionNumber = (UINT16) Uint + *OptionNumber * 0x10;\r
067ed98a
RN
134 }\r
135 }\r
136\r
137 return TRUE;\r
138}\r
139\r
121300c4
RN
140typedef struct {\r
141 EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
142 UINTN KeyOptionCount;\r
143} BM_COLLECT_KEY_OPTIONS_PARAM;\r
067ed98a 144\r
121300c4
RN
145/**\r
146 Visitor function to collect the key options from NV storage.\r
067ed98a 147\r
121300c4
RN
148 @param Name Variable name.\r
149 @param Guid Variable GUID.\r
150 @param Context The same context passed to BmForEachVariable.\r
067ed98a 151**/\r
121300c4
RN
152VOID\r
153BmCollectKeyOptions (\r
154 CHAR16 *Name,\r
155 EFI_GUID *Guid,\r
156 VOID *Context\r
067ed98a
RN
157 )\r
158{\r
121300c4
RN
159 UINTN Index;\r
160 BM_COLLECT_KEY_OPTIONS_PARAM *Param;\r
161 EFI_BOOT_MANAGER_KEY_OPTION *KeyOption;\r
162 UINT16 OptionNumber;\r
163 UINTN KeyOptionSize;\r
164\r
165 Param = (BM_COLLECT_KEY_OPTIONS_PARAM *) Context;\r
166\r
167 if (BmIsKeyOptionVariable (Name, Guid, &OptionNumber)) {\r
168 GetEfiGlobalVariable2 (Name, (VOID**) &KeyOption, &KeyOptionSize);\r
169 ASSERT (KeyOption != NULL);\r
170 KeyOption->OptionNumber = OptionNumber;\r
171 if (BmIsKeyOptionValid (KeyOption, KeyOptionSize)) {\r
172 Param->KeyOptions = ReallocatePool (\r
173 Param->KeyOptionCount * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
174 (Param->KeyOptionCount + 1) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION),\r
175 Param->KeyOptions\r
176 );\r
177 ASSERT (Param->KeyOptions != NULL);\r
178 //\r
179 // Insert the key option in order\r
180 //\r
181 for (Index = 0; Index < Param->KeyOptionCount; Index++) {\r
182 if (KeyOption->OptionNumber < Param->KeyOptions[Index].OptionNumber) {\r
183 break;\r
184 }\r
185 }\r
186 CopyMem (&Param->KeyOptions[Index + 1], &Param->KeyOptions[Index], (Param->KeyOptionCount - Index) * sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
187 CopyMem (&Param->KeyOptions[Index], KeyOption, BmSizeOfKeyOption (KeyOption));\r
188 Param->KeyOptionCount++;\r
189 }\r
190 FreePool (KeyOption);\r
191 }\r
067ed98a
RN
192}\r
193\r
194/**\r
195 Return the array of key options.\r
196\r
197 @param Count Return the number of key options.\r
198\r
199 @retval NULL No key option.\r
200 @retval Other Pointer to the key options.\r
201**/\r
202EFI_BOOT_MANAGER_KEY_OPTION *\r
203BmGetKeyOptions (\r
204 OUT UINTN *Count\r
205 )\r
206{\r
121300c4 207 BM_COLLECT_KEY_OPTIONS_PARAM Param;\r
067ed98a
RN
208\r
209 if (Count == NULL) {\r
210 return NULL;\r
211 }\r
212\r
121300c4
RN
213 Param.KeyOptions = NULL;\r
214 Param.KeyOptionCount = 0;\r
067ed98a 215\r
121300c4 216 BmForEachVariable (BmCollectKeyOptions, (VOID *) &Param);\r
067ed98a 217\r
121300c4 218 *Count = Param.KeyOptionCount;\r
067ed98a 219\r
121300c4 220 return Param.KeyOptions;\r
067ed98a
RN
221}\r
222\r
223/**\r
224 Callback function for event.\r
225 \r
226 @param Event Event for this callback function.\r
227 @param Context Context pass to this function.\r
228**/\r
229VOID\r
230EFIAPI\r
231BmEmptyFunction (\r
232 IN EFI_EVENT Event,\r
233 IN VOID *Context\r
234 )\r
235{\r
236}\r
237\r
238/**\r
239 Check whether the bit is set in the value.\r
240\r
241 @param Value The value need to be check.\r
242 @param Bit The bit filed need to be check.\r
243\r
244 @retval TRUE The bit is set.\r
245 @retval FALSE The bit is not set.\r
246**/\r
247BOOLEAN\r
248BmBitSet (\r
249 IN UINT32 Value,\r
250 IN UINT32 Bit\r
251 )\r
252{\r
253 return (BOOLEAN) ((Value & Bit) != 0);\r
254}\r
255\r
256/**\r
257 Initialize the KeyData and Key[] in the EFI_BOOT_MANAGER_KEY_OPTION.\r
258\r
259 @param Modifier Input key info.\r
260 @param Args Va_list info.\r
261 @param KeyOption Key info which need to update.\r
262\r
263 @retval EFI_SUCCESS Succeed to initialize the KeyData and Key[].\r
264 @return EFI_INVALID_PARAMETER Input parameter error.\r
265**/\r
266EFI_STATUS\r
267BmInitializeKeyFields (\r
268 IN UINT32 Modifier,\r
269 IN VA_LIST Args,\r
270 OUT EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
271 )\r
272{\r
273 EFI_INPUT_KEY *Key;\r
274\r
275 if (KeyOption == NULL) {\r
276 return EFI_INVALID_PARAMETER;\r
277 }\r
278\r
279 Key = NULL;\r
280 while (KeyOption->KeyData.Options.InputKeyCount < sizeof (KeyOption->Keys) / sizeof (KeyOption->Keys[0])) {\r
281 Key = VA_ARG (Args, EFI_INPUT_KEY *);\r
282 if (Key == NULL) {\r
283 break;\r
284 }\r
285 CopyMem (\r
286 &KeyOption->Keys[KeyOption->KeyData.Options.InputKeyCount],\r
287 Key,\r
288 sizeof (EFI_INPUT_KEY)\r
289 );\r
290 KeyOption->KeyData.Options.InputKeyCount++;\r
291 }\r
292\r
293 if (Key != NULL) {\r
294 //\r
295 // Too many keys\r
296 //\r
297 return EFI_INVALID_PARAMETER;\r
298 }\r
299\r
300 if ((Modifier & ~(EFI_BOOT_MANAGER_SHIFT_PRESSED\r
301 | EFI_BOOT_MANAGER_CONTROL_PRESSED\r
302 | EFI_BOOT_MANAGER_ALT_PRESSED\r
303 | EFI_BOOT_MANAGER_LOGO_PRESSED\r
304 | EFI_BOOT_MANAGER_MENU_KEY_PRESSED\r
305 | EFI_BOOT_MANAGER_SYS_REQ_PRESSED\r
306 )) != 0) {\r
307 return EFI_INVALID_PARAMETER;\r
308 }\r
309\r
310 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SHIFT_PRESSED)) {\r
311 KeyOption->KeyData.Options.ShiftPressed = 1;\r
312 }\r
313 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_CONTROL_PRESSED)) {\r
314 KeyOption->KeyData.Options.ControlPressed = 1;\r
315 }\r
316 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_ALT_PRESSED)) {\r
317 KeyOption->KeyData.Options.AltPressed = 1;\r
318 }\r
319 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_LOGO_PRESSED)) {\r
320 KeyOption->KeyData.Options.LogoPressed = 1;\r
321 }\r
322 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_MENU_KEY_PRESSED)) {\r
323 KeyOption->KeyData.Options.MenuPressed = 1;\r
324 }\r
325 if (BmBitSet (Modifier, EFI_BOOT_MANAGER_SYS_REQ_PRESSED)) {\r
326 KeyOption->KeyData.Options.SysReqPressed = 1;\r
327 }\r
328\r
329 return EFI_SUCCESS;\r
330}\r
331\r
332/**\r
333 Try to boot the boot option triggered by hot key.\r
334**/\r
335VOID\r
336EFIAPI\r
337EfiBootManagerHotkeyBoot (\r
338 VOID\r
339 )\r
340{\r
341 if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {\r
342 EfiBootManagerBoot (&mBmHotkeyBootOption);\r
343 EfiBootManagerFreeLoadOption (&mBmHotkeyBootOption);\r
344 mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;\r
345 }\r
346}\r
347\r
348/**\r
349 This is the common notification function for HotKeys, it will be registered\r
350 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
351\r
352 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
353 information for the key that was pressed.\r
354\r
355 @retval EFI_SUCCESS KeyData is successfully processed.\r
356 @return EFI_NOT_FOUND Fail to find boot option variable.\r
357**/\r
358EFI_STATUS\r
359EFIAPI\r
360BmHotkeyCallback (\r
361 IN EFI_KEY_DATA *KeyData\r
362)\r
363{\r
364 LIST_ENTRY *Link;\r
365 BM_HOTKEY *Hotkey;\r
f9a24380 366 CHAR16 OptionName[BM_OPTION_NAME_LEN];\r
067ed98a
RN
367 EFI_STATUS Status;\r
368 EFI_KEY_DATA *HotkeyData;\r
369\r
370 if (mBmHotkeyBootOption.OptionNumber != LoadOptionNumberUnassigned) {\r
371 //\r
372 // Do not process sequential hotkey stroke until the current boot option returns\r
373 //\r
374 return EFI_SUCCESS;\r
375 }\r
376\r
377 DEBUG ((EFI_D_INFO, "[Bds]BmHotkeyCallback: %04x:%04x\n", KeyData->Key.ScanCode, KeyData->Key.UnicodeChar));\r
378\r
379 EfiAcquireLock (&mBmHotkeyLock);\r
380 for ( Link = GetFirstNode (&mBmHotkeyList)\r
381 ; !IsNull (&mBmHotkeyList, Link)\r
382 ; Link = GetNextNode (&mBmHotkeyList, Link)\r
383 ) {\r
384 Hotkey = BM_HOTKEY_FROM_LINK (Link);\r
385\r
386 //\r
387 // Is this Key Stroke we are waiting for?\r
388 //\r
389 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
390 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
391 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
392 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
393 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
394 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
395 )\r
396 ) {\r
397\r
398 //\r
399 // Receive an expecting key stroke, transit to next waiting state\r
400 //\r
401 Hotkey->WaitingKey++;\r
402\r
403 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
404 //\r
405 // Reset to initial waiting state\r
406 //\r
407 Hotkey->WaitingKey = 0;\r
408 //\r
409 // Received the whole key stroke sequence\r
410 //\r
411 Status = gBS->SignalEvent (mBmHotkeyTriggered);\r
412 ASSERT_EFI_ERROR (Status);\r
413\r
414 if (!Hotkey->IsContinue) {\r
415 //\r
416 // Launch its BootOption\r
417 //\r
121300c4
RN
418 UnicodeSPrint (\r
419 OptionName, sizeof (OptionName), L"%s%04x",\r
420 mBmLoadOptionName[LoadOptionTypeBoot], Hotkey->BootOption\r
421 );\r
067ed98a
RN
422 Status = EfiBootManagerVariableToLoadOption (OptionName, &mBmHotkeyBootOption);\r
423 DEBUG ((EFI_D_INFO, "[Bds]Hotkey for %s pressed - %r\n", OptionName, Status));\r
424 if (EFI_ERROR (Status)) {\r
425 mBmHotkeyBootOption.OptionNumber = LoadOptionNumberUnassigned;\r
426 }\r
427 } else {\r
428 DEBUG ((EFI_D_INFO, "[Bds]Continue key pressed!\n"));\r
429 }\r
430 }\r
431 } else {\r
432 //\r
433 // Receive an unexpected key stroke, reset to initial waiting state\r
434 //\r
435 Hotkey->WaitingKey = 0;\r
436 }\r
437\r
438 }\r
439 EfiReleaseLock (&mBmHotkeyLock);\r
440\r
441 return EFI_SUCCESS;\r
442}\r
443\r
2d15a830
RN
444/**\r
445 Return the active Simple Text Input Ex handle array.\r
446 If the SystemTable.ConsoleInHandle is NULL, the function returns all\r
447 founded Simple Text Input Ex handles.\r
448 Otherwise, it just returns the ConsoleInHandle.\r
449\r
450 @param Count Return the handle count.\r
451\r
452 @retval The active console handles.\r
453**/\r
454EFI_HANDLE *\r
455BmGetActiveConsoleIn (\r
456 OUT UINTN *Count\r
457 )\r
458{\r
459 EFI_STATUS Status;\r
460 EFI_HANDLE *Handles;\r
461\r
b99e9ca9
RN
462 Handles = NULL;\r
463 *Count = 0;\r
464\r
2d15a830
RN
465 if (gST->ConsoleInHandle != NULL) {\r
466 Status = gBS->OpenProtocol (\r
467 gST->ConsoleInHandle,\r
468 &gEfiSimpleTextInputExProtocolGuid,\r
469 NULL,\r
470 gImageHandle,\r
471 NULL,\r
472 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
473 );\r
474 if (!EFI_ERROR (Status)) {\r
065e587c
TP
475 Handles = AllocateCopyPool (sizeof (EFI_HANDLE), &gST->ConsoleInHandle);\r
476 if (Handles != NULL) {\r
477 *Count = 1;\r
478 }\r
2d15a830
RN
479 }\r
480 } else {\r
481 Status = gBS->LocateHandleBuffer (\r
482 ByProtocol,\r
483 &gEfiSimpleTextInputExProtocolGuid,\r
484 NULL,\r
485 Count,\r
486 &Handles\r
487 );\r
488 }\r
2d15a830
RN
489\r
490 return Handles;\r
491}\r
492\r
067ed98a
RN
493/**\r
494 Unregister hotkey notify list.\r
495\r
496 @param Hotkey Hotkey list.\r
497\r
498 @retval EFI_SUCCESS Unregister hotkey notify success.\r
499 @retval Others Unregister hotkey notify failed.\r
500**/\r
501EFI_STATUS\r
502BmUnregisterHotkeyNotify (\r
503 IN BM_HOTKEY *Hotkey\r
504 )\r
505{\r
506 EFI_STATUS Status;\r
507 UINTN Index;\r
508 UINTN KeyIndex;\r
509 EFI_HANDLE *Handles;\r
510 UINTN HandleCount;\r
511 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;\r
512 VOID *NotifyHandle;\r
513\r
2d15a830 514 Handles = BmGetActiveConsoleIn (&HandleCount);\r
067ed98a
RN
515 for (Index = 0; Index < HandleCount; Index++) {\r
516 Status = gBS->HandleProtocol (Handles[Index], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);\r
517 ASSERT_EFI_ERROR (Status);\r
518 for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {\r
519 Status = TxtInEx->RegisterKeyNotify (\r
520 TxtInEx,\r
521 &Hotkey->KeyData[KeyIndex],\r
522 BmHotkeyCallback,\r
523 &NotifyHandle\r
524 );\r
525 if (!EFI_ERROR (Status)) {\r
526 Status = TxtInEx->UnregisterKeyNotify (TxtInEx, NotifyHandle);\r
527 DEBUG ((EFI_D_INFO, "[Bds]UnregisterKeyNotify: %04x/%04x %r\n", Hotkey->KeyData[KeyIndex].Key.ScanCode, Hotkey->KeyData[KeyIndex].Key.UnicodeChar, Status));\r
528 }\r
529 }\r
530 }\r
531\r
2d15a830
RN
532 if (Handles != NULL) {\r
533 FreePool (Handles);\r
534 }\r
535\r
067ed98a
RN
536 return EFI_SUCCESS;\r
537}\r
538\r
539/**\r
540 Register hotkey notify list.\r
541\r
542 @param TxtInEx Pointer to EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL protocol.\r
543 @param Hotkey Hotkey list.\r
544\r
545 @retval EFI_SUCCESS Register hotkey notify success.\r
546 @retval Others Register hotkey notify failed.\r
547**/\r
548EFI_STATUS\r
549BmRegisterHotkeyNotify (\r
550 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx,\r
551 IN BM_HOTKEY *Hotkey\r
552 )\r
553{\r
554 EFI_STATUS Status;\r
555 UINTN Index;\r
556 VOID *NotifyHandle;\r
557\r
558 for (Index = 0; Index < Hotkey->CodeCount; Index++) {\r
559 Status = TxtInEx->RegisterKeyNotify (\r
560 TxtInEx,\r
561 &Hotkey->KeyData[Index],\r
562 BmHotkeyCallback,\r
563 &NotifyHandle\r
564 );\r
565 DEBUG ((\r
566 EFI_D_INFO,\r
567 "[Bds]RegisterKeyNotify: %04x/%04x %08x/%02x %r\n",\r
568 Hotkey->KeyData[Index].Key.ScanCode,\r
569 Hotkey->KeyData[Index].Key.UnicodeChar,\r
570 Hotkey->KeyData[Index].KeyState.KeyShiftState,\r
571 Hotkey->KeyData[Index].KeyState.KeyToggleState,\r
572 Status\r
573 ));\r
574 if (EFI_ERROR (Status)) {\r
575 //\r
576 // some of the hotkey registry failed\r
577 // do not unregister all in case we have both CTRL-ALT-P and CTRL-ALT-P-R\r
578 //\r
579 break;\r
580 }\r
581 }\r
582\r
583 return EFI_SUCCESS;\r
584}\r
585\r
586/**\r
587 Generate key shift state base on the input key option info.\r
588\r
589 @param Depth Which key is checked.\r
590 @param KeyOption Input key option info.\r
591 @param KeyShiftState Input key shift state.\r
592 @param KeyShiftStates Return possible key shift state array.\r
593 @param KeyShiftStateCount Possible key shift state count.\r
594**/\r
595VOID\r
596BmGenerateKeyShiftState (\r
597 IN UINTN Depth,\r
598 IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption,\r
599 IN UINT32 KeyShiftState,\r
600 IN UINT32 *KeyShiftStates,\r
601 IN UINTN *KeyShiftStateCount\r
602 )\r
603{\r
604 switch (Depth) {\r
605 case 0:\r
606 if (KeyOption->KeyData.Options.ShiftPressed) {\r
607 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
608 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_SHIFT_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
609 } else {\r
610 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);\r
611 }\r
612 break;\r
613\r
614 case 1:\r
615 if (KeyOption->KeyData.Options.ControlPressed) {\r
616 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
617 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_CONTROL_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
618 } else {\r
619 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);\r
620 }\r
621 break;\r
622\r
623 case 2:\r
624 if (KeyOption->KeyData.Options.AltPressed) {\r
625 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
626 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_ALT_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
627 } else {\r
628 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);\r
629 }\r
630 break;\r
631 case 3:\r
632 if (KeyOption->KeyData.Options.LogoPressed) {\r
633 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_RIGHT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
634 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState | EFI_LEFT_LOGO_PRESSED, KeyShiftStates, KeyShiftStateCount);\r
635 } else {\r
636 BmGenerateKeyShiftState (Depth + 1, KeyOption, KeyShiftState, KeyShiftStates, KeyShiftStateCount);\r
637 }\r
638 break;\r
639 case 4:\r
640 if (KeyOption->KeyData.Options.MenuPressed) {\r
641 KeyShiftState |= EFI_MENU_KEY_PRESSED;\r
642 }\r
643 if (KeyOption->KeyData.Options.SysReqPressed) {\r
644 KeyShiftState |= EFI_SYS_REQ_PRESSED;\r
645 }\r
646 KeyShiftStates[*KeyShiftStateCount] = KeyShiftState;\r
647 (*KeyShiftStateCount)++;\r
648 break;\r
649 }\r
650}\r
651\r
652/**\r
653 Add it to hot key database, register it to existing TxtInEx.\r
654 New TxtInEx will be automatically registered with all the hot key in dababase\r
655\r
656 @param KeyOption Input key option info.\r
657**/\r
658EFI_STATUS\r
659BmProcessKeyOption (\r
660 IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOption\r
661 )\r
662{\r
663 EFI_STATUS Status;\r
664 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;\r
665 EFI_HANDLE *Handles;\r
666 UINTN HandleCount;\r
667 UINTN HandleIndex;\r
668 UINTN Index;\r
669 BM_HOTKEY *Hotkey;\r
670 UINTN KeyIndex;\r
671 //\r
672 // 16 is enough to enumerate all the possible combination of LEFT_XXX and RIGHT_XXX\r
673 //\r
674 UINT32 KeyShiftStates[16];\r
675 UINTN KeyShiftStateCount;\r
676\r
677 if (KeyOption->KeyData.Options.InputKeyCount > mBmHotkeySupportCount) {\r
678 return EFI_UNSUPPORTED;\r
679 }\r
680\r
681 KeyShiftStateCount = 0;\r
682 BmGenerateKeyShiftState (0, KeyOption, EFI_SHIFT_STATE_VALID, KeyShiftStates, &KeyShiftStateCount);\r
f0209935 683 ASSERT (KeyShiftStateCount <= ARRAY_SIZE (KeyShiftStates));\r
067ed98a
RN
684\r
685 EfiAcquireLock (&mBmHotkeyLock);\r
686\r
2d15a830
RN
687 Handles = BmGetActiveConsoleIn (&HandleCount);\r
688\r
067ed98a
RN
689 for (Index = 0; Index < KeyShiftStateCount; Index++) {\r
690 Hotkey = AllocateZeroPool (sizeof (BM_HOTKEY));\r
691 ASSERT (Hotkey != NULL);\r
692\r
693 Hotkey->Signature = BM_HOTKEY_SIGNATURE;\r
694 Hotkey->BootOption = KeyOption->BootOption;\r
695 Hotkey->IsContinue = (BOOLEAN) (KeyOption == mBmContinueKeyOption);\r
696 Hotkey->CodeCount = (UINT8) KeyOption->KeyData.Options.InputKeyCount;\r
697\r
698 for (KeyIndex = 0; KeyIndex < Hotkey->CodeCount; KeyIndex++) {\r
699 CopyMem (&Hotkey->KeyData[KeyIndex].Key, &KeyOption->Keys[KeyIndex], sizeof (EFI_INPUT_KEY));\r
700 Hotkey->KeyData[KeyIndex].KeyState.KeyShiftState = KeyShiftStates[Index];\r
701 }\r
702 InsertTailList (&mBmHotkeyList, &Hotkey->Link);\r
703\r
067ed98a
RN
704 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {\r
705 Status = gBS->HandleProtocol (Handles[HandleIndex], &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);\r
706 ASSERT_EFI_ERROR (Status);\r
707 BmRegisterHotkeyNotify (TxtInEx, Hotkey);\r
708 }\r
709 }\r
710\r
2d15a830
RN
711 if (Handles != NULL) {\r
712 FreePool (Handles);\r
713 }\r
067ed98a
RN
714 EfiReleaseLock (&mBmHotkeyLock);\r
715\r
716 return EFI_SUCCESS;\r
717}\r
718\r
719/**\r
720 Callback function for SimpleTextInEx protocol install events\r
721\r
722 @param Event the event that is signaled.\r
723 @param Context not used here.\r
724\r
725**/\r
726VOID\r
727EFIAPI\r
728BmTxtInExCallback (\r
729 IN EFI_EVENT Event,\r
730 IN VOID *Context\r
731 )\r
732{\r
733 EFI_STATUS Status;\r
734 UINTN BufferSize;\r
735 EFI_HANDLE Handle;\r
736 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;\r
737 LIST_ENTRY *Link;\r
738\r
739 while (TRUE) {\r
740 BufferSize = sizeof (EFI_HANDLE);\r
741 Status = gBS->LocateHandle (\r
742 ByRegisterNotify,\r
743 NULL,\r
744 mBmTxtInExRegistration,\r
745 &BufferSize,\r
746 &Handle\r
747 );\r
748 if (EFI_ERROR (Status)) {\r
749 //\r
750 // If no more notification events exist\r
751 //\r
752 return ;\r
753 }\r
754\r
755 Status = gBS->HandleProtocol (\r
756 Handle,\r
757 &gEfiSimpleTextInputExProtocolGuid,\r
758 (VOID **) &TxtInEx\r
759 );\r
760 ASSERT_EFI_ERROR (Status);\r
761\r
762 //\r
763 // Register the hot key notification for the existing items in the list\r
764 //\r
765 EfiAcquireLock (&mBmHotkeyLock);\r
766 for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); Link = GetNextNode (&mBmHotkeyList, Link)) {\r
767 BmRegisterHotkeyNotify (TxtInEx, BM_HOTKEY_FROM_LINK (Link));\r
768 }\r
769 EfiReleaseLock (&mBmHotkeyLock);\r
770 }\r
771}\r
772\r
773/**\r
774 Free the key options returned from BmGetKeyOptions.\r
775\r
776 @param KeyOptions Pointer to the key options.\r
777 @param KeyOptionCount Number of the key options.\r
778\r
779 @retval EFI_SUCCESS The key options are freed.\r
780 @retval EFI_NOT_FOUND KeyOptions is NULL.\r
781**/\r
782EFI_STATUS\r
783BmFreeKeyOptions (\r
784 IN EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions,\r
785 IN UINTN KeyOptionCount\r
786 )\r
787{\r
788 if (KeyOptions != NULL) {\r
789 FreePool (KeyOptions);\r
790 return EFI_SUCCESS;\r
791 } else {\r
792 return EFI_NOT_FOUND;\r
793 }\r
794}\r
795\r
796/**\r
797 Register the key option to exit the waiting of the Boot Manager timeout.\r
798 Platform should ensure that the continue key option isn't conflict with\r
799 other boot key options.\r
800\r
801 @param Modifier Key shift state.\r
802 @param ... Parameter list of pointer of EFI_INPUT_KEY.\r
803\r
804 @retval EFI_SUCCESS Successfully register the continue key option.\r
805 @retval EFI_ALREADY_STARTED The continue key option is already registered.\r
806**/\r
807EFI_STATUS\r
808EFIAPI\r
809EfiBootManagerRegisterContinueKeyOption (\r
810 IN UINT32 Modifier,\r
811 ...\r
812 )\r
813{\r
814 EFI_STATUS Status;\r
815 EFI_BOOT_MANAGER_KEY_OPTION KeyOption;\r
816 VA_LIST Args;\r
817 \r
818 if (mBmContinueKeyOption != NULL) {\r
819 return EFI_ALREADY_STARTED;\r
820 }\r
821\r
822 ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
823 VA_START (Args, Modifier);\r
824 Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);\r
825 VA_END (Args);\r
826\r
827 if (!EFI_ERROR (Status)) {\r
828 mBmContinueKeyOption = AllocateCopyPool (sizeof (EFI_BOOT_MANAGER_KEY_OPTION), &KeyOption);\r
829 ASSERT (mBmContinueKeyOption != NULL);\r
830 if (mBmHotkeyServiceStarted) {\r
831 BmProcessKeyOption (mBmContinueKeyOption);\r
832 }\r
833 }\r
834\r
835 return Status;\r
836}\r
837\r
838/**\r
839 Stop the hotkey processing.\r
840 \r
841 @param Event Event pointer related to hotkey service.\r
842 @param Context Context pass to this function.\r
843**/\r
844VOID\r
845EFIAPI\r
846BmStopHotkeyService (\r
847 IN EFI_EVENT Event,\r
848 IN VOID *Context\r
849 )\r
850{\r
851 LIST_ENTRY *Link;\r
852 BM_HOTKEY *Hotkey;\r
853\r
854 DEBUG ((EFI_D_INFO, "[Bds]Stop Hotkey Service!\n"));\r
855 gBS->CloseEvent (Event);\r
856\r
857 EfiAcquireLock (&mBmHotkeyLock);\r
858 for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {\r
859 Hotkey = BM_HOTKEY_FROM_LINK (Link);\r
860 BmUnregisterHotkeyNotify (Hotkey);\r
861 Link = RemoveEntryList (Link);\r
862 FreePool (Hotkey);\r
863 }\r
864 EfiReleaseLock (&mBmHotkeyLock);\r
865}\r
866\r
867/**\r
868 Start the hot key service so that the key press can trigger the boot option.\r
869\r
870 @param HotkeyTriggered Return the waitable event and it will be signaled \r
871 when a valid hot key is pressed.\r
872\r
873 @retval EFI_SUCCESS The hot key service is started.\r
874**/\r
875EFI_STATUS\r
876EFIAPI\r
877EfiBootManagerStartHotkeyService (\r
878 IN EFI_EVENT *HotkeyTriggered\r
879 )\r
880{\r
881 EFI_STATUS Status;\r
882 EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
883 UINTN KeyOptionCount;\r
884 UINTN Index;\r
885 EFI_EVENT Event;\r
886 UINT32 *BootOptionSupport;\r
887\r
888 Status = GetEfiGlobalVariable2 (EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME, (VOID **) &BootOptionSupport, NULL);\r
889 ASSERT (BootOptionSupport != NULL);\r
890\r
891 if ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_KEY) != 0) {\r
892 mBmHotkeySupportCount = ((*BootOptionSupport & EFI_BOOT_OPTION_SUPPORT_COUNT) >> LowBitSet32 (EFI_BOOT_OPTION_SUPPORT_COUNT));\r
893 }\r
894 FreePool (BootOptionSupport);\r
895\r
896 if (mBmHotkeySupportCount == 0) {\r
897 DEBUG ((EFI_D_INFO, "Bds: BootOptionSupport NV variable forbids starting the hotkey service.\n"));\r
898 return EFI_UNSUPPORTED;\r
899 }\r
900\r
901 Status = gBS->CreateEvent (\r
902 EVT_NOTIFY_WAIT,\r
903 TPL_CALLBACK,\r
904 BmEmptyFunction,\r
905 NULL,\r
906 &mBmHotkeyTriggered\r
907 );\r
908 ASSERT_EFI_ERROR (Status);\r
909\r
910 if (HotkeyTriggered != NULL) {\r
911 *HotkeyTriggered = mBmHotkeyTriggered;\r
912 }\r
913\r
914 KeyOptions = BmGetKeyOptions (&KeyOptionCount);\r
915 for (Index = 0; Index < KeyOptionCount; Index ++) {\r
916 BmProcessKeyOption (&KeyOptions[Index]);\r
917 }\r
918 BmFreeKeyOptions (KeyOptions, KeyOptionCount);\r
919\r
920 if (mBmContinueKeyOption != NULL) {\r
921 BmProcessKeyOption (mBmContinueKeyOption);\r
922 }\r
923\r
2d15a830
RN
924 //\r
925 // Hook hotkey on every future SimpleTextInputEx instance when\r
926 // SystemTable.ConsoleInHandle == NULL, which means the console\r
927 // manager (ConSplitter) is absent.\r
928 //\r
929 if (gST->ConsoleInHandle == NULL) {\r
930 EfiCreateProtocolNotifyEvent (\r
931 &gEfiSimpleTextInputExProtocolGuid,\r
932 TPL_CALLBACK,\r
933 BmTxtInExCallback,\r
934 NULL,\r
935 &mBmTxtInExRegistration\r
936 );\r
937 }\r
067ed98a
RN
938\r
939 Status = EfiCreateEventReadyToBootEx (\r
940 TPL_CALLBACK,\r
941 BmStopHotkeyService,\r
942 NULL,\r
943 &Event\r
944 );\r
945 ASSERT_EFI_ERROR (Status);\r
946\r
067ed98a
RN
947 mBmHotkeyServiceStarted = TRUE;\r
948 return Status;\r
949}\r
950\r
951/**\r
952 Add the key option.\r
953 It adds the key option variable and the key option takes affect immediately.\r
954\r
955 @param AddedOption Return the added key option.\r
956 @param BootOptionNumber The boot option number for the key option.\r
957 @param Modifier Key shift state.\r
958 @param ... Parameter list of pointer of EFI_INPUT_KEY.\r
959\r
960 @retval EFI_SUCCESS The key option is added.\r
961 @retval EFI_ALREADY_STARTED The hot key is already used by certain key option.\r
962**/\r
963EFI_STATUS\r
964EFIAPI\r
965EfiBootManagerAddKeyOptionVariable (\r
966 OUT EFI_BOOT_MANAGER_KEY_OPTION *AddedOption, OPTIONAL\r
967 IN UINT16 BootOptionNumber,\r
968 IN UINT32 Modifier,\r
969 ...\r
970 )\r
971{\r
972 EFI_STATUS Status;\r
973 VA_LIST Args;\r
974 VOID *BootOption;\r
975 UINTN BootOptionSize;\r
f9a24380 976 CHAR16 BootOptionName[BM_OPTION_NAME_LEN];\r
067ed98a
RN
977 EFI_BOOT_MANAGER_KEY_OPTION KeyOption;\r
978 EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
979 UINTN KeyOptionCount;\r
980 UINTN Index;\r
981 UINTN KeyOptionNumber;\r
f9a24380 982 CHAR16 KeyOptionName[sizeof ("Key####")];\r
067ed98a 983\r
121300c4
RN
984 UnicodeSPrint (\r
985 BootOptionName, sizeof (BootOptionName), L"%s%04x",\r
986 mBmLoadOptionName[LoadOptionTypeBoot], BootOptionNumber\r
987 );\r
067ed98a
RN
988 GetEfiGlobalVariable2 (BootOptionName, &BootOption, &BootOptionSize);\r
989\r
990 if (BootOption == NULL) {\r
991 return EFI_NOT_FOUND;\r
992 }\r
993\r
994 ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
995 KeyOption.BootOption = BootOptionNumber;\r
996 Status = gBS->CalculateCrc32 (BootOption, BootOptionSize, &KeyOption.BootOptionCrc);\r
997 ASSERT_EFI_ERROR (Status);\r
998 FreePool (BootOption);\r
999\r
1000 VA_START (Args, Modifier);\r
1001 Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);\r
1002 VA_END (Args);\r
1003 if (EFI_ERROR (Status)) {\r
1004 return Status;\r
1005 }\r
1006\r
1007 KeyOptionNumber = LoadOptionNumberUnassigned;\r
1008 //\r
1009 // Check if the hot key sequence was defined already\r
1010 //\r
1011 KeyOptions = BmGetKeyOptions (&KeyOptionCount);\r
1012 for (Index = 0; Index < KeyOptionCount; Index++) {\r
1013 if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&\r
1014 (CompareMem (KeyOptions[Index].Keys, KeyOption.Keys, KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)) {\r
1015 break;\r
1016 }\r
1017\r
1018 if ((KeyOptionNumber == LoadOptionNumberUnassigned) &&\r
1019 (KeyOptions[Index].OptionNumber > Index)\r
1020 ){\r
1021 KeyOptionNumber = Index;\r
1022 }\r
1023 }\r
1024 BmFreeKeyOptions (KeyOptions, KeyOptionCount);\r
1025\r
1026 if (Index < KeyOptionCount) {\r
1027 return EFI_ALREADY_STARTED;\r
1028 }\r
1029\r
1030 if (KeyOptionNumber == LoadOptionNumberUnassigned) {\r
1031 KeyOptionNumber = KeyOptionCount;\r
1032 }\r
1033\r
1034 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumber);\r
1035\r
1036 Status = gRT->SetVariable (\r
1037 KeyOptionName,\r
1038 &gEfiGlobalVariableGuid,\r
1039 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1040 BmSizeOfKeyOption (&KeyOption),\r
1041 &KeyOption\r
1042 );\r
1043 if (!EFI_ERROR (Status)) {\r
1044 //\r
1045 // Return the Key Option in case needed by caller\r
1046 //\r
1047 if (AddedOption != NULL) {\r
1048 CopyMem (AddedOption, &KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
1049 }\r
1050\r
1051 //\r
1052 // Register the newly added hot key\r
1053 // Calling this function before EfiBootManagerStartHotkeyService doesn't\r
1054 // need to call BmProcessKeyOption\r
1055 //\r
1056 if (mBmHotkeyServiceStarted) {\r
1057 BmProcessKeyOption (&KeyOption);\r
1058 }\r
1059 }\r
1060\r
1061 return Status;\r
1062}\r
1063\r
1064/**\r
1065 Delete the Key Option variable and unregister the hot key\r
1066\r
1067 @param DeletedOption Return the deleted key options.\r
1068 @param Modifier Key shift state.\r
1069 @param ... Parameter list of pointer of EFI_INPUT_KEY.\r
1070\r
1071 @retval EFI_SUCCESS The key option is deleted.\r
1072 @retval EFI_NOT_FOUND The key option cannot be found.\r
1073**/\r
1074EFI_STATUS\r
1075EFIAPI\r
1076EfiBootManagerDeleteKeyOptionVariable (\r
1077 IN EFI_BOOT_MANAGER_KEY_OPTION *DeletedOption, OPTIONAL\r
1078 IN UINT32 Modifier,\r
1079 ...\r
1080 )\r
1081{\r
1082 EFI_STATUS Status;\r
1083 UINTN Index;\r
1084 VA_LIST Args;\r
1085 EFI_BOOT_MANAGER_KEY_OPTION KeyOption;\r
1086 EFI_BOOT_MANAGER_KEY_OPTION *KeyOptions;\r
1087 UINTN KeyOptionCount;\r
1088 LIST_ENTRY *Link;\r
1089 BM_HOTKEY *Hotkey;\r
1090 UINT32 ShiftState;\r
1091 BOOLEAN Match;\r
f9a24380 1092 CHAR16 KeyOptionName[sizeof ("Key####")];\r
067ed98a
RN
1093\r
1094 ZeroMem (&KeyOption, sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
1095 VA_START (Args, Modifier);\r
1096 Status = BmInitializeKeyFields (Modifier, Args, &KeyOption);\r
1097 VA_END (Args);\r
1098\r
1099 if (EFI_ERROR (Status)) {\r
1100 return Status;\r
1101 }\r
1102\r
1103 EfiAcquireLock (&mBmHotkeyLock);\r
1104 //\r
1105 // Delete the key option from active hot key list\r
1106 // Could have multiple entries when modifier isn't 0 because we map the ShiftPressed to RIGHT_SHIFT and RIGHT_SHIFT\r
1107 //\r
1108 for (Link = GetFirstNode (&mBmHotkeyList); !IsNull (&mBmHotkeyList, Link); ) {\r
1109 Hotkey = BM_HOTKEY_FROM_LINK (Link);\r
1110 Match = (BOOLEAN) (Hotkey->CodeCount == KeyOption.KeyData.Options.InputKeyCount);\r
1111\r
1112 for (Index = 0; Match && (Index < Hotkey->CodeCount); Index++) {\r
1113 ShiftState = Hotkey->KeyData[Index].KeyState.KeyShiftState;\r
1114 if (\r
1115 (BmBitSet (ShiftState, EFI_RIGHT_SHIFT_PRESSED | EFI_LEFT_SHIFT_PRESSED) != KeyOption.KeyData.Options.ShiftPressed) ||\r
1116 (BmBitSet (ShiftState, EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) != KeyOption.KeyData.Options.ControlPressed) ||\r
1117 (BmBitSet (ShiftState, EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) != KeyOption.KeyData.Options.AltPressed) ||\r
1118 (BmBitSet (ShiftState, EFI_RIGHT_LOGO_PRESSED | EFI_LEFT_LOGO_PRESSED) != KeyOption.KeyData.Options.LogoPressed) ||\r
1119 (BmBitSet (ShiftState, EFI_MENU_KEY_PRESSED) != KeyOption.KeyData.Options.MenuPressed) ||\r
1120 (BmBitSet (ShiftState, EFI_SYS_REQ_PRESSED) != KeyOption.KeyData.Options.SysReqPressed) ||\r
1121 (CompareMem (&Hotkey->KeyData[Index].Key, &KeyOption.Keys[Index], sizeof (EFI_INPUT_KEY)) != 0)\r
1122 ) {\r
1123 //\r
1124 // Break when any field doesn't match\r
1125 //\r
1126 Match = FALSE;\r
1127 break;\r
1128 }\r
1129 }\r
1130\r
1131 if (Match) {\r
1132 Link = RemoveEntryList (Link);\r
1133 FreePool (Hotkey);\r
1134 } else {\r
1135 Link = GetNextNode (&mBmHotkeyList, Link);\r
1136 }\r
1137 }\r
1138\r
1139 //\r
1140 // Delete the key option from the variable\r
1141 //\r
1142 Status = EFI_NOT_FOUND;\r
1143 KeyOptions = BmGetKeyOptions (&KeyOptionCount);\r
1144 for (Index = 0; Index < KeyOptionCount; Index++) {\r
1145 if ((KeyOptions[Index].KeyData.PackedValue == KeyOption.KeyData.PackedValue) &&\r
1146 (CompareMem (\r
1147 KeyOptions[Index].Keys, KeyOption.Keys,\r
1148 KeyOption.KeyData.Options.InputKeyCount * sizeof (EFI_INPUT_KEY)) == 0)\r
1149 ) {\r
1150 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptions[Index].OptionNumber);\r
1151 Status = gRT->SetVariable (\r
1152 KeyOptionName,\r
1153 &gEfiGlobalVariableGuid,\r
1154 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1155 0,\r
1156 NULL\r
1157 );\r
1158 //\r
1159 // Return the deleted key option in case needed by caller\r
1160 //\r
1161 if (DeletedOption != NULL) {\r
1162 CopyMem (DeletedOption, &KeyOptions[Index], sizeof (EFI_BOOT_MANAGER_KEY_OPTION));\r
1163 }\r
1164 break;\r
1165 }\r
1166 }\r
1167 BmFreeKeyOptions (KeyOptions, KeyOptionCount);\r
1168\r
1169 EfiReleaseLock (&mBmHotkeyLock);\r
1170\r
1171 return Status;\r
1172}\r