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