]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
cae2192f9a318be65c1b08823fc8d5be90e18120
[mirror_edk2.git] / OvmfPkg / Library / PlatformBootManagerLib / BdsPlatform.c
1 /** @file
2 Platform BDS customizations.
3
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "BdsPlatform.h"
16 #include <Guid/RootBridgesConnectedEventGroup.h>
17 #include <Library/QemuBootOrderLib.h>
18
19
20 //
21 // Global data
22 //
23
24 VOID *mEfiDevPathNotifyReg;
25 EFI_EVENT mEfiDevPathEvent;
26 VOID *mEmuVariableEventReg;
27 EFI_EVENT mEmuVariableEvent;
28 BOOLEAN mDetectVgaOnly;
29 UINT16 mHostBridgeDevId;
30
31 //
32 // Table of host IRQs matching PCI IRQs A-D
33 // (for configuring PCI Interrupt Line register)
34 //
35 CONST UINT8 PciHostIrqs[] = {
36 0x0a, 0x0a, 0x0b, 0x0b
37 };
38
39 //
40 // Array Size macro
41 //
42 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
43
44 //
45 // Type definitions
46 //
47
48 typedef
49 EFI_STATUS
50 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
51 IN EFI_HANDLE Handle,
52 IN VOID *Instance,
53 IN VOID *Context
54 );
55
56 /**
57 @param[in] Handle - Handle of PCI device instance
58 @param[in] PciIo - PCI IO protocol instance
59 @param[in] Pci - PCI Header register block
60 **/
61 typedef
62 EFI_STATUS
63 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
64 IN EFI_HANDLE Handle,
65 IN EFI_PCI_IO_PROTOCOL *PciIo,
66 IN PCI_TYPE00 *Pci
67 );
68
69
70 //
71 // Function prototypes
72 //
73
74 EFI_STATUS
75 VisitAllInstancesOfProtocol (
76 IN EFI_GUID *Id,
77 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
78 IN VOID *Context
79 );
80
81 EFI_STATUS
82 VisitAllPciInstancesOfProtocol (
83 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
84 );
85
86 VOID
87 InstallDevicePathCallback (
88 VOID
89 );
90
91 EFI_STATUS
92 EFIAPI
93 ConnectRootBridge (
94 IN EFI_HANDLE RootBridgeHandle,
95 IN VOID *Instance,
96 IN VOID *Context
97 );
98
99 STATIC
100 VOID
101 SaveS3BootScript (
102 VOID
103 );
104
105 //
106 // BDS Platform Functions
107 //
108 VOID
109 EFIAPI
110 PlatformBootManagerBeforeConsole (
111 VOID
112 )
113 /*++
114
115 Routine Description:
116
117 Platform Bds init. Incude the platform firmware vendor, revision
118 and so crc check.
119
120 Arguments:
121
122 Returns:
123
124 None.
125
126 --*/
127 {
128 EFI_HANDLE Handle;
129 EFI_STATUS Status;
130
131 DEBUG ((EFI_D_INFO, "PlatformBootManagerBeforeConsole\n"));
132 InstallDevicePathCallback ();
133
134 VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
135 ConnectRootBridge, NULL);
136
137 //
138 // Signal the ACPI platform driver that it can download QEMU ACPI tables.
139 //
140 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
141
142 //
143 // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
144 // the preparation of S3 system information. That logic has a hard dependency
145 // on the presence of the FACS ACPI table. Since our ACPI tables are only
146 // installed after PCI enumeration completes, we must not trigger the S3 save
147 // earlier, hence we can't signal End-of-Dxe earlier.
148 //
149 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
150
151 if (QemuFwCfgS3Enabled ()) {
152 //
153 // Save the boot script too. Note that this will require us to emit the
154 // DxeSmmReadyToLock event just below, which in turn locks down SMM.
155 //
156 SaveS3BootScript ();
157 }
158
159 //
160 // Prevent further changes to LockBoxes or SMRAM.
161 //
162 Handle = NULL;
163 Status = gBS->InstallProtocolInterface (&Handle,
164 &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
165 NULL);
166 ASSERT_EFI_ERROR (Status);
167
168 PlatformInitializeConsole (gPlatformConsole);
169 }
170
171
172 EFI_STATUS
173 EFIAPI
174 ConnectRootBridge (
175 IN EFI_HANDLE RootBridgeHandle,
176 IN VOID *Instance,
177 IN VOID *Context
178 )
179 {
180 EFI_STATUS Status;
181
182 //
183 // Make the PCI bus driver connect the root bridge, non-recursively. This
184 // will produce a number of child handles with PciIo on them.
185 //
186 Status = gBS->ConnectController (
187 RootBridgeHandle, // ControllerHandle
188 NULL, // DriverImageHandle
189 NULL, // RemainingDevicePath -- produce all
190 // children
191 FALSE // Recursive
192 );
193 return Status;
194 }
195
196
197 EFI_STATUS
198 PrepareLpcBridgeDevicePath (
199 IN EFI_HANDLE DeviceHandle
200 )
201 /*++
202
203 Routine Description:
204
205 Add IsaKeyboard to ConIn,
206 add IsaSerial to ConOut, ConIn, ErrOut.
207 LPC Bridge: 06 01 00
208
209 Arguments:
210
211 DeviceHandle - Handle of PCIIO protocol.
212
213 Returns:
214
215 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
216 EFI_STATUS - No LPC bridge is added.
217
218 --*/
219 {
220 EFI_STATUS Status;
221 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
222 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
223 CHAR16 *DevPathStr;
224
225 DevicePath = NULL;
226 Status = gBS->HandleProtocol (
227 DeviceHandle,
228 &gEfiDevicePathProtocolGuid,
229 (VOID*)&DevicePath
230 );
231 if (EFI_ERROR (Status)) {
232 return Status;
233 }
234 TempDevicePath = DevicePath;
235
236 //
237 // Register Keyboard
238 //
239 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
240
241 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
242
243 //
244 // Register COM1
245 //
246 DevicePath = TempDevicePath;
247 gPnp16550ComPortDeviceNode.UID = 0;
248
249 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
250 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
251 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
252
253 //
254 // Print Device Path
255 //
256 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
257 if (DevPathStr != NULL) {
258 DEBUG((
259 EFI_D_INFO,
260 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
261 __LINE__,
262 gPnp16550ComPortDeviceNode.UID + 1,
263 DevPathStr
264 ));
265 FreePool(DevPathStr);
266 }
267
268 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
269 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
270 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
271
272 //
273 // Register COM2
274 //
275 DevicePath = TempDevicePath;
276 gPnp16550ComPortDeviceNode.UID = 1;
277
278 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
279 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
280 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
281
282 //
283 // Print Device Path
284 //
285 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
286 if (DevPathStr != NULL) {
287 DEBUG((
288 EFI_D_INFO,
289 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
290 __LINE__,
291 gPnp16550ComPortDeviceNode.UID + 1,
292 DevPathStr
293 ));
294 FreePool(DevPathStr);
295 }
296
297 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
298 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
299 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
300
301 return EFI_SUCCESS;
302 }
303
304 EFI_STATUS
305 GetGopDevicePath (
306 IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
307 OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
308 )
309 {
310 UINTN Index;
311 EFI_STATUS Status;
312 EFI_HANDLE PciDeviceHandle;
313 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
314 EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
315 UINTN GopHandleCount;
316 EFI_HANDLE *GopHandleBuffer;
317
318 if (PciDevicePath == NULL || GopDevicePath == NULL) {
319 return EFI_INVALID_PARAMETER;
320 }
321
322 //
323 // Initialize the GopDevicePath to be PciDevicePath
324 //
325 *GopDevicePath = PciDevicePath;
326 TempPciDevicePath = PciDevicePath;
327
328 Status = gBS->LocateDevicePath (
329 &gEfiDevicePathProtocolGuid,
330 &TempPciDevicePath,
331 &PciDeviceHandle
332 );
333 if (EFI_ERROR (Status)) {
334 return Status;
335 }
336
337 //
338 // Try to connect this handle, so that GOP dirver could start on this
339 // device and create child handles with GraphicsOutput Protocol installed
340 // on them, then we get device paths of these child handles and select
341 // them as possible console device.
342 //
343 gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
344
345 Status = gBS->LocateHandleBuffer (
346 ByProtocol,
347 &gEfiGraphicsOutputProtocolGuid,
348 NULL,
349 &GopHandleCount,
350 &GopHandleBuffer
351 );
352 if (!EFI_ERROR (Status)) {
353 //
354 // Add all the child handles as possible Console Device
355 //
356 for (Index = 0; Index < GopHandleCount; Index++) {
357 Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
358 if (EFI_ERROR (Status)) {
359 continue;
360 }
361 if (CompareMem (
362 PciDevicePath,
363 TempDevicePath,
364 GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
365 ) == 0) {
366 //
367 // In current implementation, we only enable one of the child handles
368 // as console device, i.e. sotre one of the child handle's device
369 // path to variable "ConOut"
370 // In futhure, we could select all child handles to be console device
371 //
372
373 *GopDevicePath = TempDevicePath;
374
375 //
376 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
377 // Add the integrity GOP device path.
378 //
379 EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
380 EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
381 }
382 }
383 gBS->FreePool (GopHandleBuffer);
384 }
385
386 return EFI_SUCCESS;
387 }
388
389 EFI_STATUS
390 PreparePciVgaDevicePath (
391 IN EFI_HANDLE DeviceHandle
392 )
393 /*++
394
395 Routine Description:
396
397 Add PCI VGA to ConOut.
398 PCI VGA: 03 00 00
399
400 Arguments:
401
402 DeviceHandle - Handle of PCIIO protocol.
403
404 Returns:
405
406 EFI_SUCCESS - PCI VGA is added to ConOut.
407 EFI_STATUS - No PCI VGA device is added.
408
409 --*/
410 {
411 EFI_STATUS Status;
412 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
413 EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
414
415 DevicePath = NULL;
416 GopDevicePath = NULL;
417 Status = gBS->HandleProtocol (
418 DeviceHandle,
419 &gEfiDevicePathProtocolGuid,
420 (VOID*)&DevicePath
421 );
422 if (EFI_ERROR (Status)) {
423 return Status;
424 }
425
426 GetGopDevicePath (DevicePath, &GopDevicePath);
427 DevicePath = GopDevicePath;
428
429 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
430
431 return EFI_SUCCESS;
432 }
433
434 EFI_STATUS
435 PreparePciSerialDevicePath (
436 IN EFI_HANDLE DeviceHandle
437 )
438 /*++
439
440 Routine Description:
441
442 Add PCI Serial to ConOut, ConIn, ErrOut.
443 PCI Serial: 07 00 02
444
445 Arguments:
446
447 DeviceHandle - Handle of PCIIO protocol.
448
449 Returns:
450
451 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
452 EFI_STATUS - No PCI Serial device is added.
453
454 --*/
455 {
456 EFI_STATUS Status;
457 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
458
459 DevicePath = NULL;
460 Status = gBS->HandleProtocol (
461 DeviceHandle,
462 &gEfiDevicePathProtocolGuid,
463 (VOID*)&DevicePath
464 );
465 if (EFI_ERROR (Status)) {
466 return Status;
467 }
468
469 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
470 DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
471
472 EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
473 EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
474 EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
475
476 return EFI_SUCCESS;
477 }
478
479 EFI_STATUS
480 VisitAllInstancesOfProtocol (
481 IN EFI_GUID *Id,
482 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
483 IN VOID *Context
484 )
485 {
486 EFI_STATUS Status;
487 UINTN HandleCount;
488 EFI_HANDLE *HandleBuffer;
489 UINTN Index;
490 VOID *Instance;
491
492 //
493 // Start to check all the PciIo to find all possible device
494 //
495 HandleCount = 0;
496 HandleBuffer = NULL;
497 Status = gBS->LocateHandleBuffer (
498 ByProtocol,
499 Id,
500 NULL,
501 &HandleCount,
502 &HandleBuffer
503 );
504 if (EFI_ERROR (Status)) {
505 return Status;
506 }
507
508 for (Index = 0; Index < HandleCount; Index++) {
509 Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
510 if (EFI_ERROR (Status)) {
511 continue;
512 }
513
514 Status = (*CallBackFunction) (
515 HandleBuffer[Index],
516 Instance,
517 Context
518 );
519 }
520
521 gBS->FreePool (HandleBuffer);
522
523 return EFI_SUCCESS;
524 }
525
526
527 EFI_STATUS
528 EFIAPI
529 VisitingAPciInstance (
530 IN EFI_HANDLE Handle,
531 IN VOID *Instance,
532 IN VOID *Context
533 )
534 {
535 EFI_STATUS Status;
536 EFI_PCI_IO_PROTOCOL *PciIo;
537 PCI_TYPE00 Pci;
538
539 PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
540
541 //
542 // Check for all PCI device
543 //
544 Status = PciIo->Pci.Read (
545 PciIo,
546 EfiPciIoWidthUint32,
547 0,
548 sizeof (Pci) / sizeof (UINT32),
549 &Pci
550 );
551 if (EFI_ERROR (Status)) {
552 return Status;
553 }
554
555 return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
556 Handle,
557 PciIo,
558 &Pci
559 );
560
561 }
562
563
564
565 EFI_STATUS
566 VisitAllPciInstances (
567 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
568 )
569 {
570 return VisitAllInstancesOfProtocol (
571 &gEfiPciIoProtocolGuid,
572 VisitingAPciInstance,
573 (VOID*)(UINTN) CallBackFunction
574 );
575 }
576
577
578 /**
579 Do platform specific PCI Device check and add them to
580 ConOut, ConIn, ErrOut.
581
582 @param[in] Handle - Handle of PCI device instance
583 @param[in] PciIo - PCI IO protocol instance
584 @param[in] Pci - PCI Header register block
585
586 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
587 @retval EFI_STATUS - PCI Device check or Console variable update fail.
588
589 **/
590 EFI_STATUS
591 EFIAPI
592 DetectAndPreparePlatformPciDevicePath (
593 IN EFI_HANDLE Handle,
594 IN EFI_PCI_IO_PROTOCOL *PciIo,
595 IN PCI_TYPE00 *Pci
596 )
597 {
598 EFI_STATUS Status;
599
600 Status = PciIo->Attributes (
601 PciIo,
602 EfiPciIoAttributeOperationEnable,
603 EFI_PCI_DEVICE_ENABLE,
604 NULL
605 );
606 ASSERT_EFI_ERROR (Status);
607
608 if (!mDetectVgaOnly) {
609 //
610 // Here we decide whether it is LPC Bridge
611 //
612 if ((IS_PCI_LPC (Pci)) ||
613 ((IS_PCI_ISA_PDECODE (Pci)) &&
614 (Pci->Hdr.VendorId == 0x8086) &&
615 (Pci->Hdr.DeviceId == 0x7000)
616 )
617 ) {
618 //
619 // Add IsaKeyboard to ConIn,
620 // add IsaSerial to ConOut, ConIn, ErrOut
621 //
622 DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
623 PrepareLpcBridgeDevicePath (Handle);
624 return EFI_SUCCESS;
625 }
626 //
627 // Here we decide which Serial device to enable in PCI bus
628 //
629 if (IS_PCI_16550SERIAL (Pci)) {
630 //
631 // Add them to ConOut, ConIn, ErrOut.
632 //
633 DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
634 PreparePciSerialDevicePath (Handle);
635 return EFI_SUCCESS;
636 }
637 }
638
639 //
640 // Here we decide which VGA device to enable in PCI bus
641 //
642 if (IS_PCI_VGA (Pci)) {
643 //
644 // Add them to ConOut.
645 //
646 DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
647 PreparePciVgaDevicePath (Handle);
648 return EFI_SUCCESS;
649 }
650
651 return Status;
652 }
653
654
655 /**
656 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
657
658 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
659
660 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
661 @retval EFI_STATUS - PCI Device check or Console variable update fail.
662
663 **/
664 EFI_STATUS
665 DetectAndPreparePlatformPciDevicePaths (
666 BOOLEAN DetectVgaOnly
667 )
668 {
669 mDetectVgaOnly = DetectVgaOnly;
670 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
671 }
672
673
674 VOID
675 PlatformInitializeConsole (
676 IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
677 )
678 /*++
679
680 Routine Description:
681
682 Connect the predefined platform default console device. Always try to find
683 and enable the vga device if have.
684
685 Arguments:
686
687 PlatformConsole - Predfined platform default console device array.
688 --*/
689 {
690 UINTN Index;
691 EFI_DEVICE_PATH_PROTOCOL *VarConout;
692 EFI_DEVICE_PATH_PROTOCOL *VarConin;
693
694 //
695 // Connect RootBridge
696 //
697 GetEfiGlobalVariable2 (EFI_CON_OUT_VARIABLE_NAME, (VOID **) &VarConout, NULL);
698 GetEfiGlobalVariable2 (EFI_CON_IN_VARIABLE_NAME, (VOID **) &VarConin, NULL);
699
700 if (VarConout == NULL || VarConin == NULL) {
701 //
702 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
703 //
704 DetectAndPreparePlatformPciDevicePaths (FALSE);
705
706 //
707 // Have chance to connect the platform default console,
708 // the platform default console is the minimue device group
709 // the platform should support
710 //
711 for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
712 //
713 // Update the console variable with the connect type
714 //
715 if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
716 EfiBootManagerUpdateConsoleVariable (ConIn, PlatformConsole[Index].DevicePath, NULL);
717 }
718 if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
719 EfiBootManagerUpdateConsoleVariable (ConOut, PlatformConsole[Index].DevicePath, NULL);
720 }
721 if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
722 EfiBootManagerUpdateConsoleVariable (ErrOut, PlatformConsole[Index].DevicePath, NULL);
723 }
724 }
725 } else {
726 //
727 // Only detect VGA device and add them to ConOut
728 //
729 DetectAndPreparePlatformPciDevicePaths (TRUE);
730 }
731 }
732
733
734 /**
735 Configure PCI Interrupt Line register for applicable devices
736 Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
737
738 @param[in] Handle - Handle of PCI device instance
739 @param[in] PciIo - PCI IO protocol instance
740 @param[in] PciHdr - PCI Header register block
741
742 @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
743
744 **/
745 EFI_STATUS
746 EFIAPI
747 SetPciIntLine (
748 IN EFI_HANDLE Handle,
749 IN EFI_PCI_IO_PROTOCOL *PciIo,
750 IN PCI_TYPE00 *PciHdr
751 )
752 {
753 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
754 EFI_DEVICE_PATH_PROTOCOL *DevPath;
755 UINTN RootSlot;
756 UINTN Idx;
757 UINT8 IrqLine;
758 EFI_STATUS Status;
759 UINT32 RootBusNumber;
760
761 Status = EFI_SUCCESS;
762
763 if (PciHdr->Device.InterruptPin != 0) {
764
765 DevPathNode = DevicePathFromHandle (Handle);
766 ASSERT (DevPathNode != NULL);
767 DevPath = DevPathNode;
768
769 RootBusNumber = 0;
770 if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
771 DevicePathSubType (DevPathNode) == ACPI_DP &&
772 ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
773 RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
774 }
775
776 //
777 // Compute index into PciHostIrqs[] table by walking
778 // the device path and adding up all device numbers
779 //
780 Status = EFI_NOT_FOUND;
781 RootSlot = 0;
782 Idx = PciHdr->Device.InterruptPin - 1;
783 while (!IsDevicePathEnd (DevPathNode)) {
784 if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
785 DevicePathSubType (DevPathNode) == HW_PCI_DP) {
786
787 Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
788
789 //
790 // Unlike SeaBIOS, which starts climbing from the leaf device
791 // up toward the root, we traverse the device path starting at
792 // the root moving toward the leaf node.
793 // The slot number of the top-level parent bridge is needed for
794 // Q35 cases with more than 24 slots on the root bus.
795 //
796 if (Status != EFI_SUCCESS) {
797 Status = EFI_SUCCESS;
798 RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
799 }
800 }
801
802 DevPathNode = NextDevicePathNode (DevPathNode);
803 }
804 if (EFI_ERROR (Status)) {
805 return Status;
806 }
807 if (RootBusNumber == 0 && RootSlot == 0) {
808 DEBUG((
809 EFI_D_ERROR,
810 "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
811 __FUNCTION__
812 ));
813 ASSERT (FALSE);
814 }
815
816 //
817 // Final PciHostIrqs[] index calculation depends on the platform
818 // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
819 //
820 switch (mHostBridgeDevId) {
821 case INTEL_82441_DEVICE_ID:
822 Idx -= 1;
823 break;
824 case INTEL_Q35_MCH_DEVICE_ID:
825 //
826 // SeaBIOS contains the following comment:
827 // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
828 // with a different starting index - see q35-acpi-dsdt.dsl.
829 //
830 // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
831 //
832 if (RootSlot > 24) {
833 //
834 // in this case, subtract back out RootSlot from Idx
835 // (SeaBIOS never adds it to begin with, but that would make our
836 // device path traversal loop above too awkward)
837 //
838 Idx -= RootSlot;
839 }
840 break;
841 default:
842 ASSERT (FALSE); // should never get here
843 }
844 Idx %= ARRAY_SIZE (PciHostIrqs);
845 IrqLine = PciHostIrqs[Idx];
846
847 DEBUG_CODE_BEGIN ();
848 {
849 CHAR16 *DevPathString;
850 STATIC CHAR16 Fallback[] = L"<failed to convert>";
851 UINTN Segment, Bus, Device, Function;
852
853 DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
854 if (DevPathString == NULL) {
855 DevPathString = Fallback;
856 }
857 Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
858 ASSERT_EFI_ERROR (Status);
859
860 DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
861 (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
862 IrqLine));
863
864 if (DevPathString != Fallback) {
865 FreePool (DevPathString);
866 }
867 }
868 DEBUG_CODE_END ();
869
870 //
871 // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
872 //
873 Status = PciIo->Pci.Write (
874 PciIo,
875 EfiPciIoWidthUint8,
876 PCI_INT_LINE_OFFSET,
877 1,
878 &IrqLine
879 );
880 }
881
882 return Status;
883 }
884
885
886 VOID
887 PciAcpiInitialization (
888 )
889 {
890 UINTN Pmba;
891
892 //
893 // Query Host Bridge DID to determine platform type
894 //
895 mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
896 switch (mHostBridgeDevId) {
897 case INTEL_82441_DEVICE_ID:
898 Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
899 //
900 // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
901 //
902 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
903 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
904 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
905 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
906 break;
907 case INTEL_Q35_MCH_DEVICE_ID:
908 Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
909 //
910 // 00:1f.0 LPC Bridge (Q35) LNK routing targets
911 //
912 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
913 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
914 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
915 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
916 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
917 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
918 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
919 PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
920 break;
921 default:
922 DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
923 __FUNCTION__, mHostBridgeDevId));
924 ASSERT (FALSE);
925 return;
926 }
927
928 //
929 // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
930 //
931 VisitAllPciInstances (SetPciIntLine);
932
933 //
934 // Set ACPI SCI_EN bit in PMCNTRL
935 //
936 IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
937 }
938
939
940 EFI_STATUS
941 EFIAPI
942 ConnectRecursivelyIfPciMassStorage (
943 IN EFI_HANDLE Handle,
944 IN EFI_PCI_IO_PROTOCOL *Instance,
945 IN PCI_TYPE00 *PciHeader
946 )
947 {
948 EFI_STATUS Status;
949 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
950 CHAR16 *DevPathStr;
951
952 if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
953 DevicePath = NULL;
954 Status = gBS->HandleProtocol (
955 Handle,
956 &gEfiDevicePathProtocolGuid,
957 (VOID*)&DevicePath
958 );
959 if (EFI_ERROR (Status)) {
960 return Status;
961 }
962
963 //
964 // Print Device Path
965 //
966 DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
967 if (DevPathStr != NULL) {
968 DEBUG((
969 EFI_D_INFO,
970 "Found Mass Storage device: %s\n",
971 DevPathStr
972 ));
973 FreePool(DevPathStr);
974 }
975
976 Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
977 if (EFI_ERROR (Status)) {
978 return Status;
979 }
980
981 }
982
983 return EFI_SUCCESS;
984 }
985
986
987 /**
988 This notification function is invoked when the
989 EMU Variable FVB has been changed.
990
991 @param Event The event that occured
992 @param Context For EFI compatiblity. Not used.
993
994 **/
995 VOID
996 EFIAPI
997 EmuVariablesUpdatedCallback (
998 IN EFI_EVENT Event,
999 IN VOID *Context
1000 )
1001 {
1002 DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
1003 UpdateNvVarsOnFileSystem ();
1004 }
1005
1006
1007 EFI_STATUS
1008 EFIAPI
1009 VisitingFileSystemInstance (
1010 IN EFI_HANDLE Handle,
1011 IN VOID *Instance,
1012 IN VOID *Context
1013 )
1014 {
1015 EFI_STATUS Status;
1016 STATIC BOOLEAN ConnectedToFileSystem = FALSE;
1017
1018 if (ConnectedToFileSystem) {
1019 return EFI_ALREADY_STARTED;
1020 }
1021
1022 Status = ConnectNvVarsToFileSystem (Handle);
1023 if (EFI_ERROR (Status)) {
1024 return Status;
1025 }
1026
1027 ConnectedToFileSystem = TRUE;
1028 mEmuVariableEvent =
1029 EfiCreateProtocolNotifyEvent (
1030 &gEfiDevicePathProtocolGuid,
1031 TPL_CALLBACK,
1032 EmuVariablesUpdatedCallback,
1033 NULL,
1034 &mEmuVariableEventReg
1035 );
1036 PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
1037
1038 return EFI_SUCCESS;
1039 }
1040
1041
1042 VOID
1043 PlatformBdsRestoreNvVarsFromHardDisk (
1044 )
1045 {
1046 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
1047 VisitAllInstancesOfProtocol (
1048 &gEfiSimpleFileSystemProtocolGuid,
1049 VisitingFileSystemInstance,
1050 NULL
1051 );
1052
1053 }
1054
1055
1056 VOID
1057 PlatformBdsConnectSequence (
1058 VOID
1059 )
1060 /*++
1061
1062 Routine Description:
1063
1064 Connect with predeined platform connect sequence,
1065 the OEM/IBV can customize with their own connect sequence.
1066
1067 Arguments:
1068
1069 None.
1070
1071 Returns:
1072
1073 None.
1074
1075 --*/
1076 {
1077 UINTN Index;
1078
1079 DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
1080
1081 Index = 0;
1082
1083 //
1084 // Here we can get the customized platform connect sequence
1085 // Notes: we can connect with new variable which record the
1086 // last time boots connect device path sequence
1087 //
1088 while (gPlatformConnectSequence[Index] != NULL) {
1089 //
1090 // Build the platform boot option
1091 //
1092 BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
1093 Index++;
1094 }
1095
1096 //
1097 // Just use the simple policy to connect all devices
1098 //
1099 BdsLibConnectAll ();
1100
1101 PciAcpiInitialization ();
1102
1103 //
1104 // Clear the logo after all devices are connected.
1105 //
1106 gST->ConOut->ClearScreen (gST->ConOut);
1107 }
1108
1109 VOID
1110 PlatformBdsGetDriverOption (
1111 IN OUT LIST_ENTRY *BdsDriverLists
1112 )
1113 /*++
1114
1115 Routine Description:
1116
1117 Load the predefined driver option, OEM/IBV can customize this
1118 to load their own drivers
1119
1120 Arguments:
1121
1122 BdsDriverLists - The header of the driver option link list.
1123
1124 Returns:
1125
1126 None.
1127
1128 --*/
1129 {
1130 DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
1131 return;
1132 }
1133
1134 VOID
1135 PlatformBdsDiagnostics (
1136 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,
1137 IN BOOLEAN QuietBoot,
1138 IN BASEM_MEMORY_TEST BaseMemoryTest
1139 )
1140 /*++
1141
1142 Routine Description:
1143
1144 Perform the platform diagnostic, such like test memory. OEM/IBV also
1145 can customize this fuction to support specific platform diagnostic.
1146
1147 Arguments:
1148
1149 MemoryTestLevel - The memory test intensive level
1150
1151 QuietBoot - Indicate if need to enable the quiet boot
1152
1153 BaseMemoryTest - A pointer to BaseMemoryTest()
1154
1155 Returns:
1156
1157 None.
1158
1159 --*/
1160 {
1161 EFI_STATUS Status;
1162
1163 DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
1164
1165 //
1166 // Here we can decide if we need to show
1167 // the diagnostics screen
1168 // Notes: this quiet boot code should be remove
1169 // from the graphic lib
1170 //
1171 if (QuietBoot) {
1172 EnableQuietBoot (PcdGetPtr(PcdLogoFile));
1173 //
1174 // Perform system diagnostic
1175 //
1176 Status = BaseMemoryTest (MemoryTestLevel);
1177 if (EFI_ERROR (Status)) {
1178 DisableQuietBoot ();
1179 }
1180
1181 return ;
1182 }
1183 //
1184 // Perform system diagnostic
1185 //
1186 Status = BaseMemoryTest (MemoryTestLevel);
1187 }
1188
1189
1190 /**
1191 Save the S3 boot script.
1192
1193 Note that DxeSmmReadyToLock must be signaled after this function returns;
1194 otherwise the script wouldn't be saved actually.
1195 **/
1196 STATIC
1197 VOID
1198 SaveS3BootScript (
1199 VOID
1200 )
1201 {
1202 EFI_STATUS Status;
1203 EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
1204 STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
1205
1206 Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
1207 (VOID **) &BootScript);
1208 ASSERT_EFI_ERROR (Status);
1209
1210 //
1211 // Despite the opcode documentation in the PI spec, the protocol
1212 // implementation embeds a deep copy of the info in the boot script, rather
1213 // than storing just a pointer to runtime or NVS storage.
1214 //
1215 Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
1216 (UINT32) sizeof Info,
1217 (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
1218 ASSERT_EFI_ERROR (Status);
1219 }
1220
1221
1222 VOID
1223 EFIAPI
1224 PlatformBootManagerAfterConsole (
1225 VOID
1226 )
1227 /*++
1228
1229 Routine Description:
1230
1231 The function will excute with as the platform policy, current policy
1232 is driven by boot mode. IBV/OEM can customize this code for their specific
1233 policy action.
1234
1235 --*/
1236 {
1237 EFI_STATUS Status;
1238 EFI_BOOT_MODE BootMode;
1239
1240 DEBUG ((EFI_D_INFO, "PlatformBootManagerAfterConsole\n"));
1241
1242 if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
1243 DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
1244 "from disk since flash variables appear to be supported.\n"));
1245 } else {
1246 //
1247 // Try to restore variables from the hard disk early so
1248 // they can be used for the other BDS connect operations.
1249 //
1250 PlatformBdsRestoreNvVarsFromHardDisk ();
1251 }
1252
1253 //
1254 // Load the driver option as the driver option list
1255 //
1256 PlatformBdsGetDriverOption (DriverOptionList);
1257
1258 //
1259 // Get current Boot Mode
1260 //
1261 Status = BdsLibGetBootMode (&BootMode);
1262 DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
1263
1264 //
1265 // Go the different platform policy with different boot mode
1266 // Notes: this part code can be change with the table policy
1267 //
1268 ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
1269
1270 //
1271 // Memory test and Logo show
1272 //
1273 PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
1274
1275 //
1276 // Perform some platform specific connect sequence
1277 //
1278 PlatformBdsConnectSequence ();
1279
1280 //
1281 // Process QEMU's -kernel command line option
1282 //
1283 TryRunningQemuKernel ();
1284
1285 DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
1286 BdsLibConnectAll ();
1287 BdsLibEnumerateAllBootOption (BootOptionList);
1288
1289 SetBootOrderFromQemu (BootOptionList);
1290 //
1291 // The BootOrder variable may have changed, reload the in-memory list with
1292 // it.
1293 //
1294 BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
1295
1296 PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
1297 }
1298
1299 VOID
1300 EFIAPI
1301 PlatformBdsBootSuccess (
1302 IN BDS_COMMON_OPTION *Option
1303 )
1304 /*++
1305
1306 Routine Description:
1307
1308 Hook point after a boot attempt succeeds. We don't expect a boot option to
1309 return, so the EFI 1.0 specification defines that you will default to an
1310 interactive mode and stop processing the BootOrder list in this case. This
1311 is alos a platform implementation and can be customized by IBV/OEM.
1312
1313 Arguments:
1314
1315 Option - Pointer to Boot Option that succeeded to boot.
1316
1317 Returns:
1318
1319 None.
1320
1321 --*/
1322 {
1323 CHAR16 *TmpStr;
1324
1325 DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
1326 //
1327 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1328 // select loop then we need to pop up a UI and wait for user input.
1329 //
1330 TmpStr = Option->StatusString;
1331 if (TmpStr != NULL) {
1332 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1333 FreePool (TmpStr);
1334 }
1335 }
1336
1337 VOID
1338 EFIAPI
1339 PlatformBdsBootFail (
1340 IN BDS_COMMON_OPTION *Option,
1341 IN EFI_STATUS Status,
1342 IN CHAR16 *ExitData,
1343 IN UINTN ExitDataSize
1344 )
1345 /*++
1346
1347 Routine Description:
1348
1349 Hook point after a boot attempt fails.
1350
1351 Arguments:
1352
1353 Option - Pointer to Boot Option that failed to boot.
1354
1355 Status - Status returned from failed boot.
1356
1357 ExitData - Exit data returned from failed boot.
1358
1359 ExitDataSize - Exit data size returned from failed boot.
1360
1361 Returns:
1362
1363 None.
1364
1365 --*/
1366 {
1367 CHAR16 *TmpStr;
1368
1369 DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
1370
1371 //
1372 // If Boot returned with failed status then we need to pop up a UI and wait
1373 // for user input.
1374 //
1375 TmpStr = Option->StatusString;
1376 if (TmpStr != NULL) {
1377 BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
1378 FreePool (TmpStr);
1379 }
1380 }
1381
1382 VOID
1383 EFIAPI
1384 PlatformBdsLockNonUpdatableFlash (
1385 VOID
1386 )
1387 {
1388 DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
1389 return;
1390 }
1391
1392
1393 /**
1394 This notification function is invoked when an instance of the
1395 EFI_DEVICE_PATH_PROTOCOL is produced.
1396
1397 @param Event The event that occured
1398 @param Context For EFI compatiblity. Not used.
1399
1400 **/
1401 VOID
1402 EFIAPI
1403 NotifyDevPath (
1404 IN EFI_EVENT Event,
1405 IN VOID *Context
1406 )
1407 {
1408 EFI_HANDLE Handle;
1409 EFI_STATUS Status;
1410 UINTN BufferSize;
1411 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
1412 ATAPI_DEVICE_PATH *Atapi;
1413
1414 //
1415 // Examine all new handles
1416 //
1417 for (;;) {
1418 //
1419 // Get the next handle
1420 //
1421 BufferSize = sizeof (Handle);
1422 Status = gBS->LocateHandle (
1423 ByRegisterNotify,
1424 NULL,
1425 mEfiDevPathNotifyReg,
1426 &BufferSize,
1427 &Handle
1428 );
1429
1430 //
1431 // If not found, we're done
1432 //
1433 if (EFI_NOT_FOUND == Status) {
1434 break;
1435 }
1436
1437 if (EFI_ERROR (Status)) {
1438 continue;
1439 }
1440
1441 //
1442 // Get the DevicePath protocol on that handle
1443 //
1444 Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
1445 ASSERT_EFI_ERROR (Status);
1446
1447 while (!IsDevicePathEnd (DevPathNode)) {
1448 //
1449 // Find the handler to dump this device path node
1450 //
1451 if (
1452 (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
1453 (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
1454 ) {
1455 Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
1456 PciOr16 (
1457 PCI_LIB_ADDRESS (
1458 0,
1459 1,
1460 1,
1461 (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
1462 ),
1463 BIT15
1464 );
1465 }
1466
1467 //
1468 // Next device path node
1469 //
1470 DevPathNode = NextDevicePathNode (DevPathNode);
1471 }
1472 }
1473
1474 return;
1475 }
1476
1477
1478 VOID
1479 InstallDevicePathCallback (
1480 VOID
1481 )
1482 {
1483 DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
1484 mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
1485 &gEfiDevicePathProtocolGuid,
1486 TPL_CALLBACK,
1487 NotifyDevPath,
1488 NULL,
1489 &mEfiDevPathNotifyReg
1490 );
1491 }
1492
1493 /**
1494 This function is called each second during the boot manager waits the timeout.
1495
1496 @param TimeoutRemain The remaining timeout.
1497 **/
1498 VOID
1499 EFIAPI
1500 PlatformBootManagerWaitCallback (
1501 UINT16 TimeoutRemain
1502 )
1503 {
1504 }
1505