]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2Keyboard.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Bus / Isa / Ps2KeyboardDxe / Ps2Keyboard.c
1 /** @file
2
3 PS/2 Keyboard driver. Routines that interacts with callers,
4 conforming to EFI driver model
5
6 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "Ps2Keyboard.h"
12
13 //
14 // Function prototypes
15 //
16
17 /**
18 Test controller is a keyboard Controller.
19
20 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
21 @param Controller driver's controller
22 @param RemainingDevicePath children device path
23
24 @retval EFI_UNSUPPORTED controller is not floppy disk
25 @retval EFI_SUCCESS controller is floppy disk
26 **/
27 EFI_STATUS
28 EFIAPI
29 KbdControllerDriverSupported (
30 IN EFI_DRIVER_BINDING_PROTOCOL *This,
31 IN EFI_HANDLE Controller,
32 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
33 );
34
35 /**
36 Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
37
38 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
39 @param Controller driver controller handle
40 @param RemainingDevicePath Children's device path
41
42 @retval whether success to create floppy control instance.
43 **/
44 EFI_STATUS
45 EFIAPI
46 KbdControllerDriverStart (
47 IN EFI_DRIVER_BINDING_PROTOCOL *This,
48 IN EFI_HANDLE Controller,
49 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
50 );
51
52 /**
53 Stop this driver on ControllerHandle. Support stopping any child handles
54 created by this driver.
55
56 @param This Protocol instance pointer.
57 @param ControllerHandle Handle of device to stop driver on
58 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
59 children is zero stop the entire bus driver.
60 @param ChildHandleBuffer List of Child Handles to Stop.
61
62 @retval EFI_SUCCESS This driver is removed ControllerHandle
63 @retval other This driver was not removed from this device
64
65 **/
66 EFI_STATUS
67 EFIAPI
68 KbdControllerDriverStop (
69 IN EFI_DRIVER_BINDING_PROTOCOL *This,
70 IN EFI_HANDLE Controller,
71 IN UINTN NumberOfChildren,
72 IN EFI_HANDLE *ChildHandleBuffer
73 );
74
75 /**
76 Free the waiting key notify list.
77
78 @param ListHead Pointer to list head
79
80 @retval EFI_INVALID_PARAMETER ListHead is NULL
81 @retval EFI_SUCCESS Success to free NotifyList
82 **/
83 EFI_STATUS
84 KbdFreeNotifyList (
85 IN OUT LIST_ENTRY *ListHead
86 );
87
88 //
89 // DriverBinding Protocol Instance
90 //
91 EFI_DRIVER_BINDING_PROTOCOL gKeyboardControllerDriver = {
92 KbdControllerDriverSupported,
93 KbdControllerDriverStart,
94 KbdControllerDriverStop,
95 0xa,
96 NULL,
97 NULL
98 };
99
100 /**
101 Test controller is a keyboard Controller.
102
103 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
104 @param Controller driver's controller
105 @param RemainingDevicePath children device path
106
107 @retval EFI_UNSUPPORTED controller is not floppy disk
108 @retval EFI_SUCCESS controller is floppy disk
109 **/
110 EFI_STATUS
111 EFIAPI
112 KbdControllerDriverSupported (
113 IN EFI_DRIVER_BINDING_PROTOCOL *This,
114 IN EFI_HANDLE Controller,
115 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
116 )
117 {
118 EFI_STATUS Status;
119 EFI_SIO_PROTOCOL *Sio;
120 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
121 ACPI_HID_DEVICE_PATH *Acpi;
122
123 //
124 // Check whether the controller is keyboard.
125 //
126 Status = gBS->OpenProtocol (
127 Controller,
128 &gEfiDevicePathProtocolGuid,
129 (VOID **)&DevicePath,
130 This->DriverBindingHandle,
131 Controller,
132 EFI_OPEN_PROTOCOL_GET_PROTOCOL
133 );
134 if (EFI_ERROR (Status)) {
135 return Status;
136 }
137
138 do {
139 Acpi = (ACPI_HID_DEVICE_PATH *)DevicePath;
140 DevicePath = NextDevicePathNode (DevicePath);
141 } while (!IsDevicePathEnd (DevicePath));
142
143 if ((DevicePathType (Acpi) != ACPI_DEVICE_PATH) ||
144 ((DevicePathSubType (Acpi) != ACPI_DP) && (DevicePathSubType (Acpi) != ACPI_EXTENDED_DP)))
145 {
146 return EFI_UNSUPPORTED;
147 }
148
149 if ((Acpi->HID != EISA_PNP_ID (0x303)) || (Acpi->UID != 0)) {
150 return EFI_UNSUPPORTED;
151 }
152
153 //
154 // Open the IO Abstraction(s) needed to perform the supported test
155 //
156 Status = gBS->OpenProtocol (
157 Controller,
158 &gEfiSioProtocolGuid,
159 (VOID **)&Sio,
160 This->DriverBindingHandle,
161 Controller,
162 EFI_OPEN_PROTOCOL_BY_DRIVER
163 );
164 if (EFI_ERROR (Status)) {
165 return Status;
166 }
167
168 //
169 // Close the I/O Abstraction(s) used to perform the supported test
170 //
171 gBS->CloseProtocol (
172 Controller,
173 &gEfiSioProtocolGuid,
174 This->DriverBindingHandle,
175 Controller
176 );
177
178 return Status;
179 }
180
181 /**
182 Create KEYBOARD_CONSOLE_IN_DEV instance on controller.
183
184 @param This Pointer of EFI_DRIVER_BINDING_PROTOCOL
185 @param Controller driver controller handle
186 @param RemainingDevicePath Children's device path
187
188 @retval whether success to create floppy control instance.
189 **/
190 EFI_STATUS
191 EFIAPI
192 KbdControllerDriverStart (
193 IN EFI_DRIVER_BINDING_PROTOCOL *This,
194 IN EFI_HANDLE Controller,
195 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
196 )
197 {
198 EFI_STATUS Status;
199 EFI_STATUS Status1;
200 EFI_SIO_PROTOCOL *Sio;
201 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
202 UINT8 Data;
203 EFI_STATUS_CODE_VALUE StatusCode;
204 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
205
206 StatusCode = 0;
207
208 Status = gBS->OpenProtocol (
209 Controller,
210 &gEfiDevicePathProtocolGuid,
211 (VOID **)&DevicePath,
212 This->DriverBindingHandle,
213 Controller,
214 EFI_OPEN_PROTOCOL_GET_PROTOCOL
215 );
216 if (EFI_ERROR (Status)) {
217 return Status;
218 }
219
220 //
221 // Report that the keyboard is being enabled
222 //
223 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
224 EFI_PROGRESS_CODE,
225 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE,
226 DevicePath
227 );
228
229 //
230 // Get the ISA I/O Protocol on Controller's handle
231 //
232 Status = gBS->OpenProtocol (
233 Controller,
234 &gEfiSioProtocolGuid,
235 (VOID **)&Sio,
236 This->DriverBindingHandle,
237 Controller,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
239 );
240 if (EFI_ERROR (Status)) {
241 return Status;
242 }
243
244 //
245 // Allocate private data
246 //
247 ConsoleIn = AllocateZeroPool (sizeof (KEYBOARD_CONSOLE_IN_DEV));
248 if (ConsoleIn == NULL) {
249 Status = EFI_OUT_OF_RESOURCES;
250 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
251 goto ErrorExit;
252 }
253
254 //
255 // Setup the device instance
256 //
257 ConsoleIn->Signature = KEYBOARD_CONSOLE_IN_DEV_SIGNATURE;
258 ConsoleIn->Handle = Controller;
259 (ConsoleIn->ConIn).Reset = KeyboardEfiReset;
260 (ConsoleIn->ConIn).ReadKeyStroke = KeyboardReadKeyStroke;
261 ConsoleIn->DataRegisterAddress = KEYBOARD_8042_DATA_REGISTER;
262 ConsoleIn->StatusRegisterAddress = KEYBOARD_8042_STATUS_REGISTER;
263 ConsoleIn->CommandRegisterAddress = KEYBOARD_8042_COMMAND_REGISTER;
264 ConsoleIn->DevicePath = DevicePath;
265
266 ConsoleIn->ConInEx.Reset = KeyboardEfiResetEx;
267 ConsoleIn->ConInEx.ReadKeyStrokeEx = KeyboardReadKeyStrokeEx;
268 ConsoleIn->ConInEx.SetState = KeyboardSetState;
269 ConsoleIn->ConInEx.RegisterKeyNotify = KeyboardRegisterKeyNotify;
270 ConsoleIn->ConInEx.UnregisterKeyNotify = KeyboardUnregisterKeyNotify;
271
272 InitializeListHead (&ConsoleIn->NotifyList);
273
274 //
275 // Fix for random hangs in System waiting for the Key if no KBC is present in BIOS.
276 // When KBC decode (IO port 0x60/0x64 decode) is not enabled,
277 // KeyboardRead will read back as 0xFF and return status is EFI_SUCCESS.
278 // So instead we read status register to detect after read if KBC decode is enabled.
279 //
280
281 //
282 // Return code is ignored on purpose.
283 //
284 if (!PcdGetBool (PcdFastPS2Detection)) {
285 KeyboardRead (ConsoleIn, &Data);
286 if ((KeyReadStatusRegister (ConsoleIn) & (KBC_PARE | KBC_TIM)) == (KBC_PARE | KBC_TIM)) {
287 //
288 // If nobody decodes KBC I/O port, it will read back as 0xFF.
289 // Check the Time-Out and Parity bit to see if it has an active KBC in system
290 //
291 Status = EFI_DEVICE_ERROR;
292 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
293 goto ErrorExit;
294 }
295 }
296
297 //
298 // Setup the WaitForKey event
299 //
300 Status = gBS->CreateEvent (
301 EVT_NOTIFY_WAIT,
302 TPL_NOTIFY,
303 KeyboardWaitForKey,
304 ConsoleIn,
305 &((ConsoleIn->ConIn).WaitForKey)
306 );
307 if (EFI_ERROR (Status)) {
308 Status = EFI_OUT_OF_RESOURCES;
309 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
310 goto ErrorExit;
311 }
312
313 //
314 // Setup the WaitForKeyEx event
315 //
316 Status = gBS->CreateEvent (
317 EVT_NOTIFY_WAIT,
318 TPL_NOTIFY,
319 KeyboardWaitForKeyEx,
320 ConsoleIn,
321 &(ConsoleIn->ConInEx.WaitForKeyEx)
322 );
323 if (EFI_ERROR (Status)) {
324 Status = EFI_OUT_OF_RESOURCES;
325 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
326 goto ErrorExit;
327 }
328
329 // Setup a periodic timer, used for reading keystrokes at a fixed interval
330 //
331 Status = gBS->CreateEvent (
332 EVT_TIMER | EVT_NOTIFY_SIGNAL,
333 TPL_NOTIFY,
334 KeyboardTimerHandler,
335 ConsoleIn,
336 &ConsoleIn->TimerEvent
337 );
338 if (EFI_ERROR (Status)) {
339 Status = EFI_OUT_OF_RESOURCES;
340 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
341 goto ErrorExit;
342 }
343
344 Status = gBS->SetTimer (
345 ConsoleIn->TimerEvent,
346 TimerPeriodic,
347 KEYBOARD_TIMER_INTERVAL
348 );
349 if (EFI_ERROR (Status)) {
350 Status = EFI_OUT_OF_RESOURCES;
351 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
352 goto ErrorExit;
353 }
354
355 Status = gBS->CreateEvent (
356 EVT_NOTIFY_SIGNAL,
357 TPL_CALLBACK,
358 KeyNotifyProcessHandler,
359 ConsoleIn,
360 &ConsoleIn->KeyNotifyProcessEvent
361 );
362 if (EFI_ERROR (Status)) {
363 Status = EFI_OUT_OF_RESOURCES;
364 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
365 goto ErrorExit;
366 }
367
368 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
369 EFI_PROGRESS_CODE,
370 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT,
371 DevicePath
372 );
373
374 //
375 // Reset the keyboard device
376 //
377 Status = ConsoleIn->ConInEx.Reset (&ConsoleIn->ConInEx, FeaturePcdGet (PcdPs2KbdExtendedVerification));
378 if (EFI_ERROR (Status)) {
379 Status = EFI_DEVICE_ERROR;
380 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_NOT_DETECTED;
381 goto ErrorExit;
382 }
383
384 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
385 EFI_PROGRESS_CODE,
386 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DETECTED,
387 DevicePath
388 );
389
390 ConsoleIn->ControllerNameTable = NULL;
391 AddUnicodeString2 (
392 "eng",
393 gPs2KeyboardComponentName.SupportedLanguages,
394 &ConsoleIn->ControllerNameTable,
395 L"PS/2 Keyboard Device",
396 TRUE
397 );
398 AddUnicodeString2 (
399 "en",
400 gPs2KeyboardComponentName2.SupportedLanguages,
401 &ConsoleIn->ControllerNameTable,
402 L"PS/2 Keyboard Device",
403 FALSE
404 );
405
406 //
407 // Install protocol interfaces for the keyboard device.
408 //
409 Status = gBS->InstallMultipleProtocolInterfaces (
410 &Controller,
411 &gEfiSimpleTextInProtocolGuid,
412 &ConsoleIn->ConIn,
413 &gEfiSimpleTextInputExProtocolGuid,
414 &ConsoleIn->ConInEx,
415 NULL
416 );
417 if (EFI_ERROR (Status)) {
418 StatusCode = EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_CONTROLLER_ERROR;
419 goto ErrorExit;
420 }
421
422 return Status;
423
424 ErrorExit:
425 //
426 // Report error code
427 //
428 if (StatusCode != 0) {
429 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
430 EFI_ERROR_CODE | EFI_ERROR_MINOR,
431 StatusCode,
432 DevicePath
433 );
434 }
435
436 if ((ConsoleIn != NULL) && (ConsoleIn->ConIn.WaitForKey != NULL)) {
437 gBS->CloseEvent (ConsoleIn->ConIn.WaitForKey);
438 }
439
440 if ((ConsoleIn != NULL) && (ConsoleIn->TimerEvent != NULL)) {
441 gBS->CloseEvent (ConsoleIn->TimerEvent);
442 }
443
444 if ((ConsoleIn != NULL) && (ConsoleIn->ConInEx.WaitForKeyEx != NULL)) {
445 gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
446 }
447
448 if ((ConsoleIn != NULL) && (ConsoleIn->KeyNotifyProcessEvent != NULL)) {
449 gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
450 }
451
452 KbdFreeNotifyList (&ConsoleIn->NotifyList);
453 if ((ConsoleIn != NULL) && (ConsoleIn->ControllerNameTable != NULL)) {
454 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
455 }
456
457 //
458 // Since there will be no timer handler for keyboard input any more,
459 // exhaust input data just in case there is still keyboard data left
460 //
461 if (ConsoleIn != NULL) {
462 Status1 = EFI_SUCCESS;
463 while (!EFI_ERROR (Status1) && (Status != EFI_DEVICE_ERROR)) {
464 Status1 = KeyboardRead (ConsoleIn, &Data);
465 }
466 }
467
468 if (ConsoleIn != NULL) {
469 gBS->FreePool (ConsoleIn);
470 }
471
472 gBS->CloseProtocol (
473 Controller,
474 &gEfiSioProtocolGuid,
475 This->DriverBindingHandle,
476 Controller
477 );
478
479 return Status;
480 }
481
482 /**
483 Stop this driver on ControllerHandle. Support stopping any child handles
484 created by this driver.
485
486 @param This Protocol instance pointer.
487 @param ControllerHandle Handle of device to stop driver on
488 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
489 children is zero stop the entire bus driver.
490 @param ChildHandleBuffer List of Child Handles to Stop.
491
492 @retval EFI_SUCCESS This driver is removed ControllerHandle
493 @retval other This driver was not removed from this device
494
495 **/
496 EFI_STATUS
497 EFIAPI
498 KbdControllerDriverStop (
499 IN EFI_DRIVER_BINDING_PROTOCOL *This,
500 IN EFI_HANDLE Controller,
501 IN UINTN NumberOfChildren,
502 IN EFI_HANDLE *ChildHandleBuffer
503 )
504 {
505 EFI_STATUS Status;
506 EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
507 KEYBOARD_CONSOLE_IN_DEV *ConsoleIn;
508 UINT8 Data;
509
510 //
511 // Disable Keyboard
512 //
513 Status = gBS->OpenProtocol (
514 Controller,
515 &gEfiSimpleTextInProtocolGuid,
516 (VOID **)&ConIn,
517 This->DriverBindingHandle,
518 Controller,
519 EFI_OPEN_PROTOCOL_GET_PROTOCOL
520 );
521 if (EFI_ERROR (Status)) {
522 return Status;
523 }
524
525 Status = gBS->OpenProtocol (
526 Controller,
527 &gEfiSimpleTextInputExProtocolGuid,
528 NULL,
529 This->DriverBindingHandle,
530 Controller,
531 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
532 );
533 if (EFI_ERROR (Status)) {
534 return Status;
535 }
536
537 ConsoleIn = KEYBOARD_CONSOLE_IN_DEV_FROM_THIS (ConIn);
538
539 //
540 // Report that the keyboard is being disabled
541 //
542 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
543 EFI_PROGRESS_CODE,
544 EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE,
545 ConsoleIn->DevicePath
546 );
547
548 if (ConsoleIn->TimerEvent != NULL) {
549 gBS->CloseEvent (ConsoleIn->TimerEvent);
550 ConsoleIn->TimerEvent = NULL;
551 }
552
553 //
554 // Since there will be no timer handler for keyboard input any more,
555 // exhaust input data just in case there is still keyboard data left
556 //
557 Status = EFI_SUCCESS;
558 while (!EFI_ERROR (Status)) {
559 Status = KeyboardRead (ConsoleIn, &Data);
560 }
561
562 //
563 // Uninstall the SimpleTextIn and SimpleTextInEx protocols
564 //
565 Status = gBS->UninstallMultipleProtocolInterfaces (
566 Controller,
567 &gEfiSimpleTextInProtocolGuid,
568 &ConsoleIn->ConIn,
569 &gEfiSimpleTextInputExProtocolGuid,
570 &ConsoleIn->ConInEx,
571 NULL
572 );
573 if (EFI_ERROR (Status)) {
574 return Status;
575 }
576
577 gBS->CloseProtocol (
578 Controller,
579 &gEfiSioProtocolGuid,
580 This->DriverBindingHandle,
581 Controller
582 );
583
584 //
585 // Free other resources
586 //
587 if ((ConsoleIn->ConIn).WaitForKey != NULL) {
588 gBS->CloseEvent ((ConsoleIn->ConIn).WaitForKey);
589 (ConsoleIn->ConIn).WaitForKey = NULL;
590 }
591
592 if (ConsoleIn->ConInEx.WaitForKeyEx != NULL) {
593 gBS->CloseEvent (ConsoleIn->ConInEx.WaitForKeyEx);
594 ConsoleIn->ConInEx.WaitForKeyEx = NULL;
595 }
596
597 if (ConsoleIn->KeyNotifyProcessEvent != NULL) {
598 gBS->CloseEvent (ConsoleIn->KeyNotifyProcessEvent);
599 ConsoleIn->KeyNotifyProcessEvent = NULL;
600 }
601
602 KbdFreeNotifyList (&ConsoleIn->NotifyList);
603 FreeUnicodeStringTable (ConsoleIn->ControllerNameTable);
604 gBS->FreePool (ConsoleIn);
605
606 return EFI_SUCCESS;
607 }
608
609 /**
610 Free the waiting key notify list.
611
612 @param ListHead Pointer to list head
613
614 @retval EFI_INVALID_PARAMETER ListHead is NULL
615 @retval EFI_SUCCESS Success to free NotifyList
616 **/
617 EFI_STATUS
618 KbdFreeNotifyList (
619 IN OUT LIST_ENTRY *ListHead
620 )
621 {
622 KEYBOARD_CONSOLE_IN_EX_NOTIFY *NotifyNode;
623
624 if (ListHead == NULL) {
625 return EFI_INVALID_PARAMETER;
626 }
627
628 while (!IsListEmpty (ListHead)) {
629 NotifyNode = CR (
630 ListHead->ForwardLink,
631 KEYBOARD_CONSOLE_IN_EX_NOTIFY,
632 NotifyEntry,
633 KEYBOARD_CONSOLE_IN_EX_NOTIFY_SIGNATURE
634 );
635 RemoveEntryList (ListHead->ForwardLink);
636 gBS->FreePool (NotifyNode);
637 }
638
639 return EFI_SUCCESS;
640 }
641
642 /**
643 The module Entry Point for module Ps2Keyboard.
644
645 @param[in] ImageHandle The firmware allocated handle for the EFI image.
646 @param[in] SystemTable A pointer to the EFI System Table.
647
648 @retval EFI_SUCCESS The entry point is executed successfully.
649 @retval other Some error occurs when executing this entry point.
650
651 **/
652 EFI_STATUS
653 EFIAPI
654 InitializePs2Keyboard (
655 IN EFI_HANDLE ImageHandle,
656 IN EFI_SYSTEM_TABLE *SystemTable
657 )
658 {
659 EFI_STATUS Status;
660
661 //
662 // Install driver model protocol(s).
663 //
664 Status = EfiLibInstallDriverBindingComponentName2 (
665 ImageHandle,
666 SystemTable,
667 &gKeyboardControllerDriver,
668 ImageHandle,
669 &gPs2KeyboardComponentName,
670 &gPs2KeyboardComponentName2
671 );
672 ASSERT_EFI_ERROR (Status);
673
674 return Status;
675 }