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