2 Platform BDS customizations.
4 Copyright (c) 2004 - 2012, 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
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.
15 #include "BdsPlatform.h"
22 VOID
*mEfiDevPathNotifyReg
;
23 EFI_EVENT mEfiDevPathEvent
;
24 VOID
*mEmuVariableEventReg
;
25 EFI_EVENT mEmuVariableEvent
;
26 BOOLEAN mDetectVgaOnly
;
35 (EFIAPI
*PROTOCOL_INSTANCE_CALLBACK
)(
42 @param[in] Handle - Handle of PCI device instance
43 @param[in] PciIo - PCI IO protocol instance
44 @param[in] Pci - PCI Header register block
48 (EFIAPI
*VISIT_PCI_INSTANCE_CALLBACK
)(
50 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
56 // Function prototypes
60 VisitAllInstancesOfProtocol (
62 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
67 VisitAllPciInstancesOfProtocol (
68 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
72 InstallDevicePathCallback (
84 PciRomLoadEfiDriversFromRomImage (
85 IN EFI_PHYSICAL_ADDRESS Rom
,
90 // BDS Platform Functions
101 Platform Bds init. Incude the platform firmware vendor, revision
112 DEBUG ((EFI_D_INFO
, "PlatformBdsInit\n"));
113 InstallDevicePathCallback ();
134 EFI_SUCCESS - Connect RootBridge successfully.
135 EFI_STATUS - Connect RootBridge fail.
140 EFI_HANDLE RootHandle
;
143 // Make all the PCI_IO protocols on PCI Seg 0 show up
145 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
147 Status
= gBS
->LocateDevicePath (
148 &gEfiDevicePathProtocolGuid
,
149 &gPlatformRootBridges
[0],
152 if (EFI_ERROR (Status
)) {
156 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
157 if (EFI_ERROR (Status
)) {
166 PrepareLpcBridgeDevicePath (
167 IN EFI_HANDLE DeviceHandle
173 Add IsaKeyboard to ConIn,
174 add IsaSerial to ConOut, ConIn, ErrOut.
179 DeviceHandle - Handle of PCIIO protocol.
183 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
184 EFI_STATUS - No LPC bridge is added.
189 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
190 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
194 Status
= gBS
->HandleProtocol (
196 &gEfiDevicePathProtocolGuid
,
199 if (EFI_ERROR (Status
)) {
202 TempDevicePath
= DevicePath
;
207 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
209 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
214 DevicePath
= TempDevicePath
;
215 gPnp16550ComPortDeviceNode
.UID
= 0;
217 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
218 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
219 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
224 DevPathStr
= DevicePathToStr(DevicePath
);
227 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
229 gPnp16550ComPortDeviceNode
.UID
+ 1,
232 FreePool(DevPathStr
);
234 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
235 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
236 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
241 DevicePath
= TempDevicePath
;
242 gPnp16550ComPortDeviceNode
.UID
= 1;
244 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
245 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
246 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
251 DevPathStr
= DevicePathToStr(DevicePath
);
254 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
256 gPnp16550ComPortDeviceNode
.UID
+ 1,
259 FreePool(DevPathStr
);
261 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
262 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
263 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
270 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
271 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
276 EFI_HANDLE PciDeviceHandle
;
277 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
278 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
279 UINTN GopHandleCount
;
280 EFI_HANDLE
*GopHandleBuffer
;
282 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
283 return EFI_INVALID_PARAMETER
;
287 // Initialize the GopDevicePath to be PciDevicePath
289 *GopDevicePath
= PciDevicePath
;
290 TempPciDevicePath
= PciDevicePath
;
292 Status
= gBS
->LocateDevicePath (
293 &gEfiDevicePathProtocolGuid
,
297 if (EFI_ERROR (Status
)) {
302 // Try to connect this handle, so that GOP dirver could start on this
303 // device and create child handles with GraphicsOutput Protocol installed
304 // on them, then we get device paths of these child handles and select
305 // them as possible console device.
307 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
309 Status
= gBS
->LocateHandleBuffer (
311 &gEfiGraphicsOutputProtocolGuid
,
316 if (!EFI_ERROR (Status
)) {
318 // Add all the child handles as possible Console Device
320 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
321 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
322 if (EFI_ERROR (Status
)) {
328 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
331 // In current implementation, we only enable one of the child handles
332 // as console device, i.e. sotre one of the child handle's device
333 // path to variable "ConOut"
334 // In futhure, we could select all child handles to be console device
337 *GopDevicePath
= TempDevicePath
;
340 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
341 // Add the integrity GOP device path.
343 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
344 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
347 gBS
->FreePool (GopHandleBuffer
);
354 PreparePciVgaDevicePath (
355 IN EFI_HANDLE DeviceHandle
361 Add PCI VGA to ConOut.
366 DeviceHandle - Handle of PCIIO protocol.
370 EFI_SUCCESS - PCI VGA is added to ConOut.
371 EFI_STATUS - No PCI VGA device is added.
376 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
377 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
380 Status
= gBS
->HandleProtocol (
382 &gEfiDevicePathProtocolGuid
,
385 if (EFI_ERROR (Status
)) {
389 GetGopDevicePath (DevicePath
, &GopDevicePath
);
390 DevicePath
= GopDevicePath
;
392 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
398 PreparePciSerialDevicePath (
399 IN EFI_HANDLE DeviceHandle
405 Add PCI Serial to ConOut, ConIn, ErrOut.
410 DeviceHandle - Handle of PCIIO protocol.
414 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
415 EFI_STATUS - No PCI Serial device is added.
420 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
423 Status
= gBS
->HandleProtocol (
425 &gEfiDevicePathProtocolGuid
,
428 if (EFI_ERROR (Status
)) {
432 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
433 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
435 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
436 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
437 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
443 VisitAllInstancesOfProtocol (
445 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
451 EFI_HANDLE
*HandleBuffer
;
456 // Start to check all the PciIo to find all possible device
460 Status
= gBS
->LocateHandleBuffer (
467 if (EFI_ERROR (Status
)) {
471 for (Index
= 0; Index
< HandleCount
; Index
++) {
472 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
473 if (EFI_ERROR (Status
)) {
477 Status
= (*CallBackFunction
) (
484 gBS
->FreePool (HandleBuffer
);
492 VisitingAPciInstance (
493 IN EFI_HANDLE Handle
,
499 EFI_PCI_IO_PROTOCOL
*PciIo
;
502 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
505 // Check for all PCI device
507 Status
= PciIo
->Pci
.Read (
511 sizeof (Pci
) / sizeof (UINT32
),
514 if (EFI_ERROR (Status
)) {
518 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
529 VisitAllPciInstances (
530 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
533 return VisitAllInstancesOfProtocol (
534 &gEfiPciIoProtocolGuid
,
535 VisitingAPciInstance
,
536 (VOID
*)(UINTN
) CallBackFunction
542 Do platform specific PCI Device check and add them to
543 ConOut, ConIn, ErrOut.
545 @param[in] Handle - Handle of PCI device instance
546 @param[in] PciIo - PCI IO protocol instance
547 @param[in] Pci - PCI Header register block
549 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
550 @retval EFI_STATUS - PCI Device check or Console variable update fail.
555 DetectAndPreparePlatformPciDevicePath (
556 IN EFI_HANDLE Handle
,
557 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
563 Status
= PciIo
->Attributes (
565 EfiPciIoAttributeOperationEnable
,
566 EFI_PCI_DEVICE_ENABLE
,
569 ASSERT_EFI_ERROR (Status
);
571 if (!mDetectVgaOnly
) {
573 // Here we decide whether it is LPC Bridge
575 if ((IS_PCI_LPC (Pci
)) ||
576 ((IS_PCI_ISA_PDECODE (Pci
)) &&
577 (Pci
->Hdr
.VendorId
== 0x8086) &&
578 (Pci
->Hdr
.DeviceId
== 0x7000)
582 // Add IsaKeyboard to ConIn,
583 // add IsaSerial to ConOut, ConIn, ErrOut
585 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
586 PrepareLpcBridgeDevicePath (Handle
);
590 // Here we decide which Serial device to enable in PCI bus
592 if (IS_PCI_16550SERIAL (Pci
)) {
594 // Add them to ConOut, ConIn, ErrOut.
596 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
597 PreparePciSerialDevicePath (Handle
);
603 // Here we decide which VGA device to enable in PCI bus
605 if (IS_PCI_VGA (Pci
)) {
607 // Add them to ConOut.
609 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
610 PreparePciVgaDevicePath (Handle
);
619 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
621 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
623 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
624 @retval EFI_STATUS - PCI Device check or Console variable update fail.
628 DetectAndPreparePlatformPciDevicePaths (
629 BOOLEAN DetectVgaOnly
632 mDetectVgaOnly
= DetectVgaOnly
;
633 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
638 PlatformBdsConnectConsole (
639 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
645 Connect the predefined platform default console device. Always try to find
646 and enable the vga device if have.
650 PlatformConsole - Predfined platform default console device array.
654 EFI_SUCCESS - Success connect at least one ConIn and ConOut
655 device, there must have one ConOut device is
658 EFI_STATUS - Return the status of
659 BdsLibConnectAllDefaultConsoles ()
665 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
666 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
667 UINTN DevicePathSize
;
670 // Connect RootBridge
672 VarConout
= BdsLibGetVariableAndSize (
674 &gEfiGlobalVariableGuid
,
677 VarConin
= BdsLibGetVariableAndSize (
679 &gEfiGlobalVariableGuid
,
683 if (VarConout
== NULL
|| VarConin
== NULL
) {
685 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
687 DetectAndPreparePlatformPciDevicePaths (FALSE
);
690 // Have chance to connect the platform default console,
691 // the platform default console is the minimue device group
692 // the platform should support
694 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
696 // Update the console variable with the connect type
698 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
699 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
701 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
702 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
704 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
705 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
710 // Only detect VGA device and add them to ConOut
712 DetectAndPreparePlatformPciDevicePaths (TRUE
);
716 // Connect the all the default console with current cosole variable
718 Status
= BdsLibConnectAllDefaultConsoles ();
719 if (EFI_ERROR (Status
)) {
732 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
734 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
737 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
739 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
740 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);
741 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);
742 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);
743 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);
746 // Bus 0, Device 1, Function 1 - IDE Controller
748 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
749 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
752 // Bus 0, Device 1, Function 3 - Power Managment Controller
754 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);
755 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);
758 // Bus 0, Device 2, Function 0 - Video Controller
760 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
763 // Bus 0, Device 3, Function 0 - Network Controller
765 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
766 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);
769 // Bus 0, Device 4, Function 0 - RAM Memory
771 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);
772 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);
782 // Set ACPI SCI_EN bit in PMCNTRL
784 IoOr16 ((PciRead32 (PCI_LIB_ADDRESS (0, 1, 3, 0x40)) & ~BIT0
) + 4, BIT0
);
790 ConnectRecursivelyIfPciMassStorage (
791 IN EFI_HANDLE Handle
,
792 IN EFI_PCI_IO_PROTOCOL
*Instance
,
793 IN PCI_TYPE00
*PciHeader
797 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
800 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
802 Status
= gBS
->HandleProtocol (
804 &gEfiDevicePathProtocolGuid
,
807 if (EFI_ERROR (Status
)) {
814 DevPathStr
= DevicePathToStr (DevicePath
);
817 "Found Mass Storage device: %s\n",
820 FreePool(DevPathStr
);
822 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
823 if (EFI_ERROR (Status
)) {
834 This notification function is invoked when the
835 EMU Variable FVB has been changed.
837 @param Event The event that occured
838 @param Context For EFI compatiblity. Not used.
843 EmuVariablesUpdatedCallback (
848 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
849 UpdateNvVarsOnFileSystem ();
855 VisitingFileSystemInstance (
856 IN EFI_HANDLE Handle
,
862 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
864 if (ConnectedToFileSystem
) {
865 return EFI_ALREADY_STARTED
;
868 Status
= ConnectNvVarsToFileSystem (Handle
);
869 if (EFI_ERROR (Status
)) {
873 ConnectedToFileSystem
= TRUE
;
875 EfiCreateProtocolNotifyEvent (
876 &gEfiDevicePathProtocolGuid
,
878 EmuVariablesUpdatedCallback
,
880 &mEmuVariableEventReg
882 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
889 PlatformBdsRestoreNvVarsFromHardDisk (
892 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
893 VisitAllInstancesOfProtocol (
894 &gEfiSimpleFileSystemProtocolGuid
,
895 VisitingFileSystemInstance
,
903 PlatformBdsConnectSequence (
910 Connect with predeined platform connect sequence,
911 the OEM/IBV can customize with their own connect sequence.
925 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
930 // Here we can get the customized platform connect sequence
931 // Notes: we can connect with new variable which record the
932 // last time boots connect device path sequence
934 while (gPlatformConnectSequence
[Index
] != NULL
) {
936 // Build the platform boot option
938 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
943 // Just use the simple policy to connect all devices
947 PciInitialization ();
948 AcpiInitialization ();
951 // Clear the logo after all devices are connected.
953 gST
->ConOut
->ClearScreen (gST
->ConOut
);
957 PlatformBdsGetDriverOption (
958 IN OUT LIST_ENTRY
*BdsDriverLists
964 Load the predefined driver option, OEM/IBV can customize this
965 to load their own drivers
969 BdsDriverLists - The header of the driver option link list.
977 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
982 PlatformBdsDiagnostics (
983 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
984 IN BOOLEAN QuietBoot
,
985 IN BASEM_MEMORY_TEST BaseMemoryTest
991 Perform the platform diagnostic, such like test memory. OEM/IBV also
992 can customize this fuction to support specific platform diagnostic.
996 MemoryTestLevel - The memory test intensive level
998 QuietBoot - Indicate if need to enable the quiet boot
1000 BaseMemoryTest - A pointer to BaseMemoryTest()
1010 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1013 // Here we can decide if we need to show
1014 // the diagnostics screen
1015 // Notes: this quiet boot code should be remove
1016 // from the graphic lib
1019 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1021 // Perform system diagnostic
1023 Status
= BaseMemoryTest (MemoryTestLevel
);
1024 if (EFI_ERROR (Status
)) {
1025 DisableQuietBoot ();
1031 // Perform system diagnostic
1033 Status
= BaseMemoryTest (MemoryTestLevel
);
1039 PlatformBdsPolicyBehavior (
1040 IN OUT LIST_ENTRY
*DriverOptionList
,
1041 IN OUT LIST_ENTRY
*BootOptionList
,
1042 IN PROCESS_CAPSULES ProcessCapsules
,
1043 IN BASEM_MEMORY_TEST BaseMemoryTest
1047 Routine Description:
1049 The function will excute with as the platform policy, current policy
1050 is driven by boot mode. IBV/OEM can customize this code for their specific
1055 DriverOptionList - The header of the driver option link list
1057 BootOptionList - The header of the boot option link list
1059 ProcessCapsules - A pointer to ProcessCapsules()
1061 BaseMemoryTest - A pointer to BaseMemoryTest()
1071 EFI_EVENT UserInputDurationTime
;
1073 BDS_COMMON_OPTION
*BootOption
;
1077 EFI_BOOT_MODE BootMode
;
1079 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior\n"));
1081 ConnectRootBridge ();
1084 // Try to restore variables from the hard disk early so
1085 // they can be used for the other BDS connect operations.
1087 PlatformBdsRestoreNvVarsFromHardDisk ();
1090 // Init the time out value
1092 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1095 // Load the driver option as the driver option list
1097 PlatformBdsGetDriverOption (DriverOptionList
);
1100 // Get current Boot Mode
1102 Status
= BdsLibGetBootMode (&BootMode
);
1103 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1106 // Go the different platform policy with different boot mode
1107 // Notes: this part code can be change with the table policy
1109 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1111 // Connect platform console
1113 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1114 if (EFI_ERROR (Status
)) {
1116 // Here OEM/IBV can customize with defined action
1118 PlatformBdsNoConsoleAction ();
1121 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1123 Status
= gBS
->CreateEvent (
1128 &UserInputDurationTime
1130 ASSERT (Status
== EFI_SUCCESS
);
1131 Status
= gBS
->SetTimer (UserInputDurationTime
, TimerRelative
, 3000000);
1132 ASSERT (Status
== EFI_SUCCESS
);
1134 // Memory test and Logo show
1136 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1139 // Perform some platform specific connect sequence
1141 PlatformBdsConnectSequence ();
1144 // Give one chance to enter the setup if we
1145 // have the time out
1148 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1151 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1152 BdsLibConnectAll ();
1153 BdsLibEnumerateAllBootOption (BootOptionList
);
1156 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1157 // checking code in real production tip.
1159 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1160 // and do enumerate all the default boot options. But in development system board, the boot mode
1161 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1162 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1164 Status
= BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1165 if (EFI_ERROR(Status
)) {
1167 // If cannot find "BootOrder" variable, it may be first boot.
1168 // Try to connect all devices and enumerate all boot options here.
1170 BdsLibConnectAll ();
1171 BdsLibEnumerateAllBootOption (BootOptionList
);
1175 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1176 // BDS should still give user a chance to enter Setup
1178 // Connect first boot option, and then check user input before exit
1180 for (Link
= BootOptionList
->ForwardLink
; Link
!= BootOptionList
;Link
= Link
->ForwardLink
) {
1181 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
1182 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
1184 // skip the header of the link list, becuase it has no boot option
1189 // Make sure the boot option device path connected, but ignore the BBS device path
1191 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
1192 BdsLibConnectDevicePath (BootOption
->DevicePath
);
1199 // Check whether the user input after the duration time has expired
1201 OldTpl
= EfiGetCurrentTpl();
1202 gBS
->RestoreTPL (TPL_APPLICATION
);
1203 gBS
->WaitForEvent (1, &UserInputDurationTime
, &Index
);
1204 gBS
->CloseEvent (UserInputDurationTime
);
1205 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1206 gBS
->RaiseTPL (OldTpl
);
1208 if (!EFI_ERROR (Status
)) {
1210 // Enter Setup if user input
1213 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1221 PlatformBdsBootSuccess (
1222 IN BDS_COMMON_OPTION
*Option
1226 Routine Description:
1228 Hook point after a boot attempt succeeds. We don't expect a boot option to
1229 return, so the EFI 1.0 specification defines that you will default to an
1230 interactive mode and stop processing the BootOrder list in this case. This
1231 is alos a platform implementation and can be customized by IBV/OEM.
1235 Option - Pointer to Boot Option that succeeded to boot.
1245 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1247 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1248 // select loop then we need to pop up a UI and wait for user input.
1250 TmpStr
= Option
->StatusString
;
1251 if (TmpStr
!= NULL
) {
1252 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1259 PlatformBdsBootFail (
1260 IN BDS_COMMON_OPTION
*Option
,
1261 IN EFI_STATUS Status
,
1262 IN CHAR16
*ExitData
,
1263 IN UINTN ExitDataSize
1267 Routine Description:
1269 Hook point after a boot attempt fails.
1273 Option - Pointer to Boot Option that failed to boot.
1275 Status - Status returned from failed boot.
1277 ExitData - Exit data returned from failed boot.
1279 ExitDataSize - Exit data size returned from failed boot.
1289 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1292 // If Boot returned with failed status then we need to pop up a UI and wait
1295 TmpStr
= Option
->StatusString
;
1296 if (TmpStr
!= NULL
) {
1297 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1303 PlatformBdsNoConsoleAction (
1308 Routine Description:
1310 This function is remained for IBV/OEM to do some platform action,
1311 if there no console device can be connected.
1319 EFI_SUCCESS - Direct return success now.
1323 DEBUG ((EFI_D_INFO
, "PlatformBdsNoConsoleAction\n"));
1329 PlatformBdsLockNonUpdatableFlash (
1333 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
1339 This notification function is invoked when an instance of the
1340 EFI_DEVICE_PATH_PROTOCOL is produced.
1342 @param Event The event that occured
1343 @param Context For EFI compatiblity. Not used.
1356 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1357 ATAPI_DEVICE_PATH
*Atapi
;
1360 // Examine all new handles
1364 // Get the next handle
1366 BufferSize
= sizeof (Handle
);
1367 Status
= gBS
->LocateHandle (
1370 mEfiDevPathNotifyReg
,
1376 // If not found, we're done
1378 if (EFI_NOT_FOUND
== Status
) {
1382 if (EFI_ERROR (Status
)) {
1387 // Get the DevicePath protocol on that handle
1389 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1390 ASSERT_EFI_ERROR (Status
);
1392 while (!IsDevicePathEnd (DevPathNode
)) {
1394 // Find the handler to dump this device path node
1397 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1398 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1400 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1406 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1413 // Next device path node
1415 DevPathNode
= NextDevicePathNode (DevPathNode
);
1424 InstallDevicePathCallback (
1428 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1429 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1430 &gEfiDevicePathProtocolGuid
,
1434 &mEfiDevPathNotifyReg
1439 Lock the ConsoleIn device in system table. All key
1440 presses will be ignored until the Password is typed in. The only way to
1441 disable the password is to type it in to a ConIn device.
1443 @param Password Password used to lock ConIn device.
1445 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1446 @retval EFI_UNSUPPORTED Password not found
1455 return EFI_UNSUPPORTED
;
1465 PCI_DATA_STRUCTURE
*Pcir
;
1469 // The virtual machines sometimes load the video rom image
1470 // directly at the legacy video BIOS location of C000:0000,
1471 // and do not implement the PCI expansion ROM feature.
1473 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) 0xc0000;
1474 RomSize
= Pcir
->ImageLength
* 512;
1475 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize
);
1481 PciRomLoadEfiDriversFromRomImage (
1482 IN EFI_PHYSICAL_ADDRESS Rom
,
1487 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
1488 PCI_DATA_STRUCTURE
*Pcir
;
1493 EFI_HANDLE ImageHandle
;
1495 EFI_STATUS retStatus
;
1496 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
1498 UINT32 DestinationSize
;
1502 VOID
*DecompressedImageBuffer
;
1504 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
1505 UINT32 InitializationSize
;
1507 FileName
= L
"PciRomInMemory";
1509 //FileName = L"PciRom Addr=0000000000000000";
1510 //HexToString (&FileName[12], Rom, 16);
1513 retStatus
= EFI_NOT_FOUND
;
1514 RomOffset
= (UINTN
) Rom
;
1518 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) (UINTN
) RomOffset
;
1520 if (EfiRomHeader
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
1525 // If the pointer to the PCI Data Structure is invalid, no further images can be located.
1526 // The PCI Data Structure must be DWORD aligned.
1528 if (EfiRomHeader
->PcirOffset
== 0 ||
1529 (EfiRomHeader
->PcirOffset
& 3) != 0 ||
1530 RomOffset
- (UINTN
)Rom
+ EfiRomHeader
->PcirOffset
+ sizeof (PCI_DATA_STRUCTURE
) > RomSize
) {
1533 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) (RomOffset
+ EfiRomHeader
->PcirOffset
);
1535 // If a valid signature is not present in the PCI Data Structure, no further images can be located.
1537 if (Pcir
->Signature
!= PCI_DATA_STRUCTURE_SIGNATURE
) {
1540 ImageSize
= Pcir
->ImageLength
* 512;
1541 if (RomOffset
- (UINTN
)Rom
+ ImageSize
> RomSize
) {
1545 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
1546 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) &&
1547 ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
1548 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
))) {
1550 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
1551 InitializationSize
= EfiRomHeader
->InitializationSize
* 512;
1553 if (InitializationSize
<= ImageSize
&& ImageOffset
< InitializationSize
) {
1555 ImageBuffer
= (VOID
*) (UINTN
) (RomOffset
+ ImageOffset
);
1556 ImageLength
= InitializationSize
- ImageOffset
;
1557 DecompressedImageBuffer
= NULL
;
1560 // decompress here if needed
1563 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
1567 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
1568 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
1569 if (EFI_ERROR (Status
)) {
1573 Status
= Decompress
->GetInfo (
1580 if (!EFI_ERROR (Status
)) {
1581 DecompressedImageBuffer
= NULL
;
1582 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
1583 if (DecompressedImageBuffer
!= NULL
) {
1584 Scratch
= AllocatePool (ScratchSize
);
1585 if (Scratch
!= NULL
) {
1586 Status
= Decompress
->Decompress (
1590 DecompressedImageBuffer
,
1595 if (!EFI_ERROR (Status
)) {
1596 ImageBuffer
= DecompressedImageBuffer
;
1597 ImageLength
= DestinationSize
;
1601 gBS
->FreePool (Scratch
);
1611 // load image and start image
1614 FilePath
= FileDevicePath (NULL
, FileName
);
1616 Status
= gBS
->LoadImage (
1624 if (!EFI_ERROR (Status
)) {
1625 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
1626 if (!EFI_ERROR (Status
)) {
1630 if (FilePath
!= NULL
) {
1631 gBS
->FreePool (FilePath
);
1635 if (DecompressedImageBuffer
!= NULL
) {
1636 gBS
->FreePool (DecompressedImageBuffer
);
1642 RomOffset
= RomOffset
+ ImageSize
;
1644 } while (((Pcir
->Indicator
& 0x80) == 0x00) && ((RomOffset
- (UINTN
) Rom
) < RomSize
));