]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/Hotkey.c
Rollback the change to EFI_BOOT_KEY_DATA structure since UEFI Spec adds the clarifica...
[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
d4468cdf 5Copyright (c) 2007 - 2013, 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
d394581d
RN
67/**\r
68 Try to boot the boot option triggered by hotkey.\r
2df686c6 69 @retval EFI_SUCCESS There is HotkeyBootOption & it is processed\r
70 @retval EFI_NOT_FOUND There is no HotkeyBootOption\r
d394581d 71**/\r
2df686c6 72EFI_STATUS\r
d394581d
RN
73HotkeyBoot (\r
74 VOID\r
75 )\r
2df686c6 76{ \r
d394581d
RN
77 EFI_STATUS Status;\r
78 UINTN ExitDataSize;\r
79 CHAR16 *ExitData;\r
2df686c6 80\r
81 if (mHotkeyBootOption == NULL) {\r
82 return EFI_NOT_FOUND;\r
83 } \r
d394581d 84 \r
2df686c6 85 BdsLibConnectDevicePath (mHotkeyBootOption->DevicePath);\r
86\r
87 //\r
88 // Clear the screen before launch this BootOption\r
89 //\r
90 gST->ConOut->Reset (gST->ConOut, FALSE);\r
91\r
92 Status = BdsLibBootViaBootOption (mHotkeyBootOption, mHotkeyBootOption->DevicePath, &ExitDataSize, &ExitData);\r
d394581d 93\r
2df686c6 94 if (EFI_ERROR (Status)) {\r
d394581d 95 //\r
2df686c6 96 // Call platform action to indicate the boot fail\r
d394581d 97 //\r
2df686c6 98 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_FAILED));\r
99 PlatformBdsBootFail (mHotkeyBootOption, Status, ExitData, ExitDataSize);\r
100 } else {\r
101 //\r
102 // Call platform action to indicate the boot success\r
103 //\r
104 mHotkeyBootOption->StatusString = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED));\r
105 PlatformBdsBootSuccess (mHotkeyBootOption);\r
106 }\r
107 FreePool (mHotkeyBootOption->Description);\r
108 FreePool (mHotkeyBootOption->DevicePath);\r
109 FreePool (mHotkeyBootOption->LoadOptions);\r
110 FreePool (mHotkeyBootOption);\r
d394581d 111\r
2df686c6 112 mHotkeyBootOption = NULL;\r
d394581d 113\r
2df686c6 114 return EFI_SUCCESS;\r
d394581d
RN
115}\r
116\r
5c08e117 117/**\r
118\r
119 This is the common notification function for HotKeys, it will be registered\r
120 with SimpleTextInEx protocol interface - RegisterKeyNotify() of ConIn handle.\r
121\r
122 @param KeyData A pointer to a buffer that is filled in with the keystroke\r
123 information for the key that was pressed.\r
124\r
125 @retval EFI_SUCCESS KeyData is successfully processed.\r
126 @return EFI_NOT_FOUND Fail to find boot option variable.\r
127**/\r
128EFI_STATUS\r
6ba0bc7c 129EFIAPI\r
5c08e117 130HotkeyCallback (\r
131 IN EFI_KEY_DATA *KeyData\r
132)\r
133{\r
134 BOOLEAN HotkeyCatched;\r
135 LIST_ENTRY BootLists;\r
136 LIST_ENTRY *Link;\r
137 BDS_HOTKEY_OPTION *Hotkey;\r
138 UINT16 Buffer[10];\r
5c08e117 139 EFI_STATUS Status;\r
140 EFI_KEY_DATA *HotkeyData;\r
141\r
d394581d 142 if (mHotkeyBootOption != NULL) {\r
5c08e117 143 //\r
d394581d 144 // Do not process sequential hotkey stroke until the current boot option returns\r
5c08e117 145 //\r
146 return EFI_SUCCESS;\r
147 }\r
148\r
d394581d 149 Status = EFI_SUCCESS;\r
5c08e117 150\r
d394581d
RN
151 for ( Link = GetFirstNode (&mHotkeyList)\r
152 ; !IsNull (&mHotkeyList, Link)\r
153 ; Link = GetNextNode (&mHotkeyList, Link)\r
154 ) {\r
5c08e117 155 HotkeyCatched = FALSE;\r
156 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
157\r
158 //\r
159 // Is this Key Stroke we are waiting for?\r
160 //\r
161 ASSERT (Hotkey->WaitingKey < (sizeof (Hotkey->KeyData) / sizeof (Hotkey->KeyData[0])));\r
162 HotkeyData = &Hotkey->KeyData[Hotkey->WaitingKey];\r
163 if ((KeyData->Key.ScanCode == HotkeyData->Key.ScanCode) &&\r
d394581d
RN
164 (KeyData->Key.UnicodeChar == HotkeyData->Key.UnicodeChar) &&\r
165 (((KeyData->KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) ? \r
166 (KeyData->KeyState.KeyShiftState == HotkeyData->KeyState.KeyShiftState) : TRUE\r
167 )\r
168 ) {\r
5c08e117 169 //\r
d394581d 170 // For hotkey of key combination, transit to next waiting state\r
5c08e117 171 //\r
d394581d 172 Hotkey->WaitingKey++;\r
5c08e117 173\r
d394581d 174 if (Hotkey->WaitingKey == Hotkey->CodeCount) {\r
5c08e117 175 //\r
d394581d 176 // Received the whole key stroke sequence\r
5c08e117 177 //\r
178 HotkeyCatched = TRUE;\r
179 }\r
180 } else {\r
181 //\r
182 // Receive an unexpected key stroke, reset to initial waiting state\r
183 //\r
184 Hotkey->WaitingKey = 0;\r
185 }\r
186\r
187 if (HotkeyCatched) {\r
188 //\r
189 // Reset to initial waiting state\r
190 //\r
191 Hotkey->WaitingKey = 0;\r
192\r
193 //\r
194 // Launch its BootOption\r
195 //\r
196 InitializeListHead (&BootLists);\r
197\r
198 UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", Hotkey->BootOptionNumber);\r
d394581d 199 mHotkeyBootOption = BdsLibVariableToOption (&BootLists, Buffer);\r
5c08e117 200 }\r
5c08e117 201 }\r
202\r
203 return Status;\r
204}\r
205\r
206/**\r
207 Register the common HotKey notify function to given SimpleTextInEx protocol instance.\r
208\r
209 @param SimpleTextInEx Simple Text Input Ex protocol instance\r
210\r
211 @retval EFI_SUCCESS Register hotkey notification function successfully.\r
212 @retval EFI_OUT_OF_RESOURCES Unable to allocate necessary data structures.\r
213\r
214**/\r
215EFI_STATUS\r
216HotkeyRegisterNotify (\r
217 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx\r
218)\r
219{\r
220 UINTN Index;\r
221 EFI_STATUS Status;\r
222 LIST_ENTRY *Link;\r
223 BDS_HOTKEY_OPTION *Hotkey;\r
224\r
225 //\r
226 // Register notification function for each hotkey\r
227 //\r
228 Link = GetFirstNode (&mHotkeyList);\r
229\r
230 while (!IsNull (&mHotkeyList, Link)) {\r
231 Hotkey = BDS_HOTKEY_OPTION_FROM_LINK (Link);\r
232\r
233 Index = 0;\r
234 do {\r
235 Status = SimpleTextInEx->RegisterKeyNotify (\r
236 SimpleTextInEx,\r
237 &Hotkey->KeyData[Index],\r
238 HotkeyCallback,\r
239 &Hotkey->NotifyHandle\r
240 );\r
241 if (EFI_ERROR (Status)) {\r
242 //\r
243 // some of the hotkey registry failed\r
244 //\r
245 return Status;\r
246 }\r
247 Index ++;\r
84fa6c17 248 } while ((Index < Hotkey->CodeCount) && (Index < (sizeof (Hotkey->KeyData) / sizeof (EFI_KEY_DATA))));\r
5c08e117 249\r
250 Link = GetNextNode (&mHotkeyList, Link);\r
251 }\r
252\r
253 return EFI_SUCCESS;\r
254}\r
255\r
256/**\r
257 Callback function for SimpleTextInEx protocol install events\r
258\r
259 @param Event the event that is signaled.\r
260 @param Context not used here.\r
261\r
262**/\r
263VOID\r
264EFIAPI\r
265HotkeyEvent (\r
266 IN EFI_EVENT Event,\r
267 IN VOID *Context\r
268 )\r
269{\r
270 EFI_STATUS Status;\r
271 UINTN BufferSize;\r
272 EFI_HANDLE Handle;\r
273 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;\r
274\r
275 while (TRUE) {\r
276 BufferSize = sizeof (EFI_HANDLE);\r
277 Status = gBS->LocateHandle (\r
278 ByRegisterNotify,\r
279 NULL,\r
280 mHotkeyRegistration,\r
281 &BufferSize,\r
282 &Handle\r
283 );\r
284 if (EFI_ERROR (Status)) {\r
285 //\r
286 // If no more notification events exist\r
287 //\r
288 return ;\r
289 }\r
290\r
291 Status = gBS->HandleProtocol (\r
292 Handle,\r
293 &gEfiSimpleTextInputExProtocolGuid,\r
294 (VOID **) &SimpleTextInEx\r
295 );\r
296 ASSERT_EFI_ERROR (Status);\r
297\r
298 HotkeyRegisterNotify (SimpleTextInEx);\r
299 }\r
300}\r
301\r
302/**\r
303 Insert Key Option to hotkey list.\r
304\r
305 @param KeyOption The Hot Key Option to be added to hotkey list.\r
306\r
307 @retval EFI_SUCCESS Add to hotkey list success.\r
308 @retval EFI_OUT_OF_RESOURCES Fail to allocate memory resource.\r
309**/\r
310EFI_STATUS\r
311HotkeyInsertList (\r
312 IN EFI_KEY_OPTION *KeyOption\r
313)\r
314{\r
315 BDS_HOTKEY_OPTION *HotkeyLeft;\r
316 BDS_HOTKEY_OPTION *HotkeyRight;\r
317 UINTN Index;\r
d4468cdf 318 EFI_BOOT_KEY_DATA KeyOptions;\r
5c08e117 319 UINT32 KeyShiftStateLeft;\r
320 UINT32 KeyShiftStateRight;\r
321 EFI_INPUT_KEY *InputKey;\r
322 EFI_KEY_DATA *KeyData;\r
323\r
324 HotkeyLeft = AllocateZeroPool (sizeof (BDS_HOTKEY_OPTION));\r
325 if (HotkeyLeft == NULL) {\r
326 return EFI_OUT_OF_RESOURCES;\r
327 }\r
328\r
329 HotkeyLeft->Signature = BDS_HOTKEY_OPTION_SIGNATURE;\r
330 HotkeyLeft->BootOptionNumber = KeyOption->BootOption;\r
d4468cdf
RN
331\r
332 KeyOptions = KeyOption->KeyData;\r
333\r
334 HotkeyLeft->CodeCount = (UINT8) KeyOptions.Options.InputKeyCount;\r
5c08e117 335\r
336 //\r
337 // Map key shift state from KeyOptions to EFI_KEY_DATA.KeyState\r
338 //\r
a9e7937a 339 KeyShiftStateRight = EFI_SHIFT_STATE_VALID;\r
d4468cdf 340 if (KeyOptions.Options.ShiftPressed) {\r
a9e7937a 341 KeyShiftStateRight |= EFI_RIGHT_SHIFT_PRESSED;\r
342 }\r
d4468cdf 343 if (KeyOptions.Options.ControlPressed) {\r
a9e7937a 344 KeyShiftStateRight |= EFI_RIGHT_CONTROL_PRESSED;\r
345 }\r
d4468cdf 346 if (KeyOptions.Options.AltPressed) {\r
a9e7937a 347 KeyShiftStateRight |= EFI_RIGHT_ALT_PRESSED;\r
348 }\r
d4468cdf 349 if (KeyOptions.Options.LogoPressed) {\r
a9e7937a 350 KeyShiftStateRight |= EFI_RIGHT_LOGO_PRESSED;\r
351 }\r
d4468cdf 352 if (KeyOptions.Options.MenuPressed) {\r
a9e7937a 353 KeyShiftStateRight |= EFI_MENU_KEY_PRESSED;\r
354 }\r
d4468cdf 355 if (KeyOptions.Options.SysReqPressed) {\r
a9e7937a 356 KeyShiftStateRight |= EFI_SYS_REQ_PRESSED;\r
357 }\r
358\r
5c08e117 359 KeyShiftStateLeft = (KeyShiftStateRight & 0xffffff00) | ((KeyShiftStateRight & 0xff) << 1);\r
360\r
361 InputKey = (EFI_INPUT_KEY *) (((UINT8 *) KeyOption) + sizeof (EFI_KEY_OPTION));\r
362\r
363 Index = 0;\r
364 KeyData = &HotkeyLeft->KeyData[0];\r
365 do {\r
366 //\r
367 // If Key CodeCount is 0, then only KeyData[0] is used;\r
368 // if Key CodeCount is n, then KeyData[0]~KeyData[n-1] are used\r
369 //\r
370 KeyData->Key.ScanCode = InputKey[Index].ScanCode;\r
371 KeyData->Key.UnicodeChar = InputKey[Index].UnicodeChar;\r
372 KeyData->KeyState.KeyShiftState = KeyShiftStateLeft;\r
373\r
374 Index++;\r
375 KeyData++;\r
376 } while (Index < HotkeyLeft->CodeCount);\r
377 InsertTailList (&mHotkeyList, &HotkeyLeft->Link);\r
378\r
379 if (KeyShiftStateLeft != KeyShiftStateRight) {\r
380 //\r
381 // Need an extra hotkey for shift key on right\r
382 //\r
383 HotkeyRight = AllocateCopyPool (sizeof (BDS_HOTKEY_OPTION), HotkeyLeft);\r
384 if (HotkeyRight == NULL) {\r
385 return EFI_OUT_OF_RESOURCES;\r
386 }\r
387\r
388 Index = 0;\r
389 KeyData = &HotkeyRight->KeyData[0];\r
390 do {\r
391 //\r
392 // Key.ScanCode and Key.UnicodeChar have already been initialized,\r
393 // only need to update KeyState.KeyShiftState\r
394 //\r
395 KeyData->KeyState.KeyShiftState = KeyShiftStateRight;\r
396\r
397 Index++;\r
398 KeyData++;\r
399 } while (Index < HotkeyRight->CodeCount);\r
400 InsertTailList (&mHotkeyList, &HotkeyRight->Link);\r
401 }\r
402\r
403 return EFI_SUCCESS;\r
404}\r
405\r
ad481b0b
RN
406/**\r
407 Return TRUE when the variable pointed by Name and Guid is a Key#### variable.\r
408\r
409 @param Name The name of the variable.\r
410 @param Guid The GUID of the variable.\r
411 @param OptionNumber Return the option number parsed from the Name.\r
412\r
413 @retval TRUE The variable pointed by Name and Guid is a Key#### variable.\r
414 @retval FALSE The variable pointed by Name and Guid isn't a Key#### variable.\r
415**/\r
416BOOLEAN\r
417IsKeyOptionVariable (\r
418 CHAR16 *Name,\r
419 EFI_GUID *Guid,\r
420 UINT16 *OptionNumber\r
421 )\r
422{\r
423 UINTN Index;\r
424 \r
425 if (!CompareGuid (Guid, &gEfiGlobalVariableGuid) ||\r
39b36547 426 (StrSize (Name) != sizeof (L"Key####")) ||\r
ad481b0b
RN
427 (StrnCmp (Name, L"Key", 3) != 0)\r
428 ) {\r
429 return FALSE;\r
430 }\r
431\r
432 *OptionNumber = 0;\r
433 for (Index = 3; Index < 7; Index++) {\r
434 if ((Name[Index] >= L'0') && (Name[Index] <= L'9')) {\r
435 *OptionNumber = *OptionNumber * 10 + Name[Index] - L'0';\r
436 } else if ((Name[Index] >= L'A') && (Name[Index] <= L'F')) {\r
437 *OptionNumber = *OptionNumber * 10 + Name[Index] - L'A';\r
438 } else {\r
439 return FALSE;\r
440 }\r
441 }\r
442\r
443 return TRUE;\r
444}\r
445\r
446/**\r
447 Return an array of key option numbers.\r
448\r
449 @param Count Return the count of key option numbers.\r
450\r
451 @return UINT16* Pointer to an array of key option numbers;\r
452**/\r
453UINT16 *\r
454EFIAPI\r
455HotkeyGetOptionNumbers (\r
456 OUT UINTN *Count\r
457 )\r
458{\r
459 EFI_STATUS Status;\r
460 UINTN Index;\r
461 CHAR16 *Name;\r
462 EFI_GUID Guid;\r
463 UINTN NameSize;\r
464 UINTN NewNameSize;\r
465 UINT16 *OptionNumbers;\r
466 UINT16 OptionNumber;\r
467\r
468 if (Count == NULL) {\r
469 return NULL;\r
470 }\r
471\r
472 *Count = 0;\r
473 OptionNumbers = NULL;\r
474\r
475 NameSize = sizeof (CHAR16);\r
476 Name = AllocateZeroPool (NameSize);\r
5077d4e5 477 ASSERT (Name != NULL);\r
ad481b0b
RN
478 while (TRUE) {\r
479 NewNameSize = NameSize;\r
480 Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);\r
481 if (Status == EFI_BUFFER_TOO_SMALL) {\r
482 Name = ReallocatePool (NameSize, NewNameSize, Name);\r
5077d4e5 483 ASSERT (Name != NULL);\r
ad481b0b
RN
484 Status = gRT->GetNextVariableName (&NewNameSize, Name, &Guid);\r
485 NameSize = NewNameSize;\r
486 }\r
487\r
488 if (Status == EFI_NOT_FOUND) {\r
489 break;\r
490 }\r
491 ASSERT_EFI_ERROR (Status);\r
492\r
493 if (IsKeyOptionVariable (Name ,&Guid, &OptionNumber)) {\r
494 OptionNumbers = ReallocatePool (\r
495 *Count * sizeof (UINT16),\r
496 (*Count + 1) * sizeof (UINT16),\r
497 OptionNumbers\r
498 );\r
5077d4e5 499 ASSERT (OptionNumbers != NULL);\r
ad481b0b
RN
500 for (Index = 0; Index < *Count; Index++) {\r
501 if (OptionNumber < OptionNumbers[Index]) {\r
502 break;\r
503 }\r
504 }\r
505 CopyMem (&OptionNumbers[Index + 1], &OptionNumbers[Index], (*Count - Index) * sizeof (UINT16));\r
506 OptionNumbers[Index] = OptionNumber;\r
507 (*Count)++;\r
508 }\r
509 }\r
510\r
511 FreePool (Name);\r
512\r
513 return OptionNumbers;\r
514}\r
515\r
5c08e117 516/**\r
517\r
518 Process all the "Key####" variables, associate Hotkeys with corresponding Boot Options.\r
519\r
520 @retval EFI_SUCCESS Hotkey services successfully initialized.\r
5c08e117 521**/\r
522EFI_STATUS\r
523InitializeHotkeyService (\r
524 VOID\r
525 )\r
526{\r
527 EFI_STATUS Status;\r
528 UINT32 BootOptionSupport;\r
ad481b0b
RN
529 UINT16 *KeyOptionNumbers;\r
530 UINTN KeyOptionCount;\r
5c08e117 531 UINTN Index;\r
ad481b0b 532 CHAR16 KeyOptionName[8];\r
5c08e117 533 EFI_KEY_OPTION *KeyOption;\r
534\r
535 //\r
0a57b959 536 // Export our capability - EFI_BOOT_OPTION_SUPPORT_KEY and EFI_BOOT_OPTION_SUPPORT_APP.\r
a9e7937a 537 // with maximum number of key presses of 3\r
0a57b959 538 // Do not report the hotkey capability if PcdConInConnectOnDemand is enabled.\r
5c08e117 539 //\r
0a57b959 540 BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;\r
541 if (!PcdGetBool (PcdConInConnectOnDemand)) {\r
542 BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;\r
543 SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
544 }\r
545\r
5c08e117 546 Status = gRT->SetVariable (\r
547 L"BootOptionSupport",\r
548 &gEfiGlobalVariableGuid,\r
a9e7937a 549 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
5c08e117 550 sizeof (UINT32),\r
551 &BootOptionSupport\r
552 );\r
ad481b0b 553 ASSERT_EFI_ERROR (Status);\r
5c08e117 554\r
ad481b0b
RN
555 KeyOptionNumbers = HotkeyGetOptionNumbers (&KeyOptionCount);\r
556 for (Index = 0; Index < KeyOptionCount; Index ++) {\r
557 UnicodeSPrint (KeyOptionName, sizeof (KeyOptionName), L"Key%04x", KeyOptionNumbers[Index]);\r
f52be04a 558 GetEfiGlobalVariable2 (KeyOptionName, (VOID **) &KeyOption, NULL);\r
ad481b0b
RN
559 ASSERT (KeyOption != NULL);\r
560 if (IsKeyOptionValid (KeyOption)) {\r
5c08e117 561 HotkeyInsertList (KeyOption);\r
562 }\r
ad481b0b
RN
563 FreePool (KeyOption);\r
564 }\r
565\r
566 if (KeyOptionNumbers != NULL) {\r
567 FreePool (KeyOptionNumbers);\r
5c08e117 568 }\r
569\r
570 //\r
571 // Register Protocol notify for Hotkey service\r
572 //\r
573 Status = gBS->CreateEvent (\r
574 EVT_NOTIFY_SIGNAL,\r
575 TPL_CALLBACK,\r
576 HotkeyEvent,\r
577 NULL,\r
578 &mHotkeyEvent\r
579 );\r
580 ASSERT_EFI_ERROR (Status);\r
581\r
582 //\r
583 // Register for protocol notifications on this event\r
584 //\r
585 Status = gBS->RegisterProtocolNotify (\r
586 &gEfiSimpleTextInputExProtocolGuid,\r
587 mHotkeyEvent,\r
588 &mHotkeyRegistration\r
589 );\r
590 ASSERT_EFI_ERROR (Status);\r
591\r
592 return Status;\r
593}\r
594\r