2 Platform BDS customizations.
4 Copyright (c) 2004 - 2009, 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 BdsLibSaveMemoryTypeInformation ();
114 InstallDevicePathCallback ();
135 EFI_SUCCESS - Connect RootBridge successfully.
136 EFI_STATUS - Connect RootBridge fail.
141 EFI_HANDLE RootHandle
;
144 // Make all the PCI_IO protocols on PCI Seg 0 show up
146 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
148 Status
= gBS
->LocateDevicePath (
149 &gEfiDevicePathProtocolGuid
,
150 &gPlatformRootBridges
[0],
153 if (EFI_ERROR (Status
)) {
157 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
158 if (EFI_ERROR (Status
)) {
167 PrepareLpcBridgeDevicePath (
168 IN EFI_HANDLE DeviceHandle
174 Add IsaKeyboard to ConIn,
175 add IsaSerial to ConOut, ConIn, ErrOut.
180 DeviceHandle - Handle of PCIIO protocol.
184 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
185 EFI_STATUS - No LPC bridge is added.
190 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
191 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
195 Status
= gBS
->HandleProtocol (
197 &gEfiDevicePathProtocolGuid
,
200 if (EFI_ERROR (Status
)) {
203 TempDevicePath
= DevicePath
;
208 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
210 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
215 DevicePath
= TempDevicePath
;
216 gPnp16550ComPortDeviceNode
.UID
= 0;
218 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
219 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
220 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
225 DevPathStr
= DevicePathToStr(DevicePath
);
228 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
230 gPnp16550ComPortDeviceNode
.UID
+ 1,
233 FreePool(DevPathStr
);
235 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
236 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
237 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
242 DevicePath
= TempDevicePath
;
243 gPnp16550ComPortDeviceNode
.UID
= 1;
245 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
246 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
247 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
252 DevPathStr
= DevicePathToStr(DevicePath
);
255 "BdsPlatform.c+%d: COM%d DevPath: %s\n",
257 gPnp16550ComPortDeviceNode
.UID
+ 1,
260 FreePool(DevPathStr
);
262 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
263 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
264 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
271 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
272 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
277 EFI_HANDLE PciDeviceHandle
;
278 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
279 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
280 UINTN GopHandleCount
;
281 EFI_HANDLE
*GopHandleBuffer
;
283 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
284 return EFI_INVALID_PARAMETER
;
288 // Initialize the GopDevicePath to be PciDevicePath
290 *GopDevicePath
= PciDevicePath
;
291 TempPciDevicePath
= PciDevicePath
;
293 Status
= gBS
->LocateDevicePath (
294 &gEfiDevicePathProtocolGuid
,
298 if (EFI_ERROR (Status
)) {
303 // Try to connect this handle, so that GOP dirver could start on this
304 // device and create child handles with GraphicsOutput Protocol installed
305 // on them, then we get device paths of these child handles and select
306 // them as possible console device.
308 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
310 Status
= gBS
->LocateHandleBuffer (
312 &gEfiGraphicsOutputProtocolGuid
,
317 if (!EFI_ERROR (Status
)) {
319 // Add all the child handles as possible Console Device
321 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
322 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
323 if (EFI_ERROR (Status
)) {
329 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
332 // In current implementation, we only enable one of the child handles
333 // as console device, i.e. sotre one of the child handle's device
334 // path to variable "ConOut"
335 // In futhure, we could select all child handles to be console device
338 *GopDevicePath
= TempDevicePath
;
341 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
342 // Add the integrity GOP device path.
344 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
345 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
348 gBS
->FreePool (GopHandleBuffer
);
355 PreparePciVgaDevicePath (
356 IN EFI_HANDLE DeviceHandle
362 Add PCI VGA to ConOut.
367 DeviceHandle - Handle of PCIIO protocol.
371 EFI_SUCCESS - PCI VGA is added to ConOut.
372 EFI_STATUS - No PCI VGA device is added.
377 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
378 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
381 Status
= gBS
->HandleProtocol (
383 &gEfiDevicePathProtocolGuid
,
386 if (EFI_ERROR (Status
)) {
390 GetGopDevicePath (DevicePath
, &GopDevicePath
);
391 DevicePath
= GopDevicePath
;
393 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
399 PreparePciSerialDevicePath (
400 IN EFI_HANDLE DeviceHandle
406 Add PCI Serial to ConOut, ConIn, ErrOut.
411 DeviceHandle - Handle of PCIIO protocol.
415 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
416 EFI_STATUS - No PCI Serial device is added.
421 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
424 Status
= gBS
->HandleProtocol (
426 &gEfiDevicePathProtocolGuid
,
429 if (EFI_ERROR (Status
)) {
433 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
434 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
436 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
437 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
438 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
444 VisitAllInstancesOfProtocol (
446 IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction
,
452 EFI_HANDLE
*HandleBuffer
;
457 // Start to check all the PciIo to find all possible device
461 Status
= gBS
->LocateHandleBuffer (
468 if (EFI_ERROR (Status
)) {
472 for (Index
= 0; Index
< HandleCount
; Index
++) {
473 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], Id
, &Instance
);
474 if (EFI_ERROR (Status
)) {
478 Status
= (*CallBackFunction
) (
485 gBS
->FreePool (HandleBuffer
);
493 VisitingAPciInstance (
494 IN EFI_HANDLE Handle
,
500 EFI_PCI_IO_PROTOCOL
*PciIo
;
503 PciIo
= (EFI_PCI_IO_PROTOCOL
*) Instance
;
506 // Check for all PCI device
508 Status
= PciIo
->Pci
.Read (
512 sizeof (Pci
) / sizeof (UINT32
),
515 if (EFI_ERROR (Status
)) {
519 return (*(VISIT_PCI_INSTANCE_CALLBACK
)(UINTN
) Context
) (
530 VisitAllPciInstances (
531 IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
534 return VisitAllInstancesOfProtocol (
535 &gEfiPciIoProtocolGuid
,
536 VisitingAPciInstance
,
537 (VOID
*)(UINTN
) CallBackFunction
543 Do platform specific PCI Device check and add them to
544 ConOut, ConIn, ErrOut.
546 @param[in] Handle - Handle of PCI device instance
547 @param[in] PciIo - PCI IO protocol instance
548 @param[in] Pci - PCI Header register block
550 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
551 @retval EFI_STATUS - PCI Device check or Console variable update fail.
556 DetectAndPreparePlatformPciDevicePath (
557 IN EFI_HANDLE Handle
,
558 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
564 Status
= PciIo
->Attributes (
566 EfiPciIoAttributeOperationEnable
,
567 EFI_PCI_DEVICE_ENABLE
,
570 ASSERT_EFI_ERROR (Status
);
572 if (!mDetectVgaOnly
) {
574 // Here we decide whether it is LPC Bridge
576 if ((IS_PCI_LPC (Pci
)) ||
577 ((IS_PCI_ISA_PDECODE (Pci
)) &&
578 (Pci
->Hdr
.VendorId
== 0x8086) &&
579 (Pci
->Hdr
.DeviceId
== 0x7000)
583 // Add IsaKeyboard to ConIn,
584 // add IsaSerial to ConOut, ConIn, ErrOut
586 DEBUG ((EFI_D_INFO
, "Found LPC Bridge device\n"));
587 PrepareLpcBridgeDevicePath (Handle
);
591 // Here we decide which Serial device to enable in PCI bus
593 if (IS_PCI_16550SERIAL (Pci
)) {
595 // Add them to ConOut, ConIn, ErrOut.
597 DEBUG ((EFI_D_INFO
, "Found PCI 16550 SERIAL device\n"));
598 PreparePciSerialDevicePath (Handle
);
604 // Here we decide which VGA device to enable in PCI bus
606 if (IS_PCI_VGA (Pci
)) {
608 // Add them to ConOut.
610 DEBUG ((EFI_D_INFO
, "Found PCI VGA device\n"));
611 PreparePciVgaDevicePath (Handle
);
620 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
622 @param[in] DetectVgaOnly - Only detect VGA device if it's TRUE.
624 @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
625 @retval EFI_STATUS - PCI Device check or Console variable update fail.
629 DetectAndPreparePlatformPciDevicePaths (
630 BOOLEAN DetectVgaOnly
633 mDetectVgaOnly
= DetectVgaOnly
;
634 return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath
);
639 PlatformBdsConnectConsole (
640 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
646 Connect the predefined platform default console device. Always try to find
647 and enable the vga device if have.
651 PlatformConsole - Predfined platform default console device array.
655 EFI_SUCCESS - Success connect at least one ConIn and ConOut
656 device, there must have one ConOut device is
659 EFI_STATUS - Return the status of
660 BdsLibConnectAllDefaultConsoles ()
666 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
667 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
668 UINTN DevicePathSize
;
671 // Connect RootBridge
673 VarConout
= BdsLibGetVariableAndSize (
675 &gEfiGlobalVariableGuid
,
678 VarConin
= BdsLibGetVariableAndSize (
680 &gEfiGlobalVariableGuid
,
684 if (VarConout
== NULL
|| VarConin
== NULL
) {
686 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
688 DetectAndPreparePlatformPciDevicePaths (FALSE
);
691 // Have chance to connect the platform default console,
692 // the platform default console is the minimue device group
693 // the platform should support
695 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
697 // Update the console variable with the connect type
699 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
700 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
702 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
703 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
705 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
706 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
711 // Only detect VGA device and add them to ConOut
713 DetectAndPreparePlatformPciDevicePaths (TRUE
);
717 // Connect the all the default console with current cosole variable
719 Status
= BdsLibConnectAllDefaultConsoles ();
720 if (EFI_ERROR (Status
)) {
733 // Bus 0, Device 0, Function 0 - Host to PCI Bridge
735 PciWrite8 (PCI_LIB_ADDRESS (0, 0, 0, 0x3c), 0x00);
738 // Bus 0, Device 1, Function 0 - PCI to ISA Bridge
740 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x3c), 0x00);
741 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b);
742 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x09);
743 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0b);
744 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x09);
747 // Bus 0, Device 1, Function 1 - IDE Controller
749 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x3c), 0x00);
750 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 1, 0x0d), 0x40);
753 // Bus 0, Device 1, Function 3 - Power Managment Controller
755 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3c), 0x0b);
756 PciWrite8 (PCI_LIB_ADDRESS (0, 1, 3, 0x3d), 0x01);
759 // Bus 0, Device 2, Function 0 - Video Controller
761 PciWrite8 (PCI_LIB_ADDRESS (0, 2, 0, 0x3c), 0x00);
764 // Bus 0, Device 3, Function 0 - Network Controller
766 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3c), 0x0b);
767 PciWrite8 (PCI_LIB_ADDRESS (0, 3, 0, 0x3d), 0x01);
770 // Bus 0, Device 4, Function 0 - RAM Memory
772 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3c), 0x09);
773 PciWrite8 (PCI_LIB_ADDRESS (0, 4, 0, 0x3d), 0x01);
779 ConnectRecursivelyIfPciMassStorage (
780 IN EFI_HANDLE Handle
,
781 IN EFI_PCI_IO_PROTOCOL
*Instance
,
782 IN PCI_TYPE00
*PciHeader
786 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
789 if (IS_CLASS1 (PciHeader
, PCI_CLASS_MASS_STORAGE
)) {
791 Status
= gBS
->HandleProtocol (
793 &gEfiDevicePathProtocolGuid
,
796 if (EFI_ERROR (Status
)) {
803 DevPathStr
= DevicePathToStr (DevicePath
);
806 "Found Mass Storage device: %s\n",
809 FreePool(DevPathStr
);
811 Status
= gBS
->ConnectController (Handle
, NULL
, NULL
, TRUE
);
812 if (EFI_ERROR (Status
)) {
823 This notification function is invoked when the
824 EMU Variable FVB has been changed.
826 @param Event The event that occured
827 @param Context For EFI compatiblity. Not used.
832 EmuVariablesUpdatedCallback (
837 DEBUG ((EFI_D_INFO
, "EmuVariablesUpdatedCallback\n"));
838 UpdateNvVarsOnFileSystem ();
844 VisitingFileSystemInstance (
845 IN EFI_HANDLE Handle
,
851 STATIC BOOLEAN ConnectedToFileSystem
= FALSE
;
853 if (ConnectedToFileSystem
) {
854 return EFI_ALREADY_STARTED
;
857 Status
= ConnectNvVarsToFileSystem (Handle
);
858 if (EFI_ERROR (Status
)) {
862 ConnectedToFileSystem
= TRUE
;
864 EfiCreateProtocolNotifyEvent (
865 &gEfiDevicePathProtocolGuid
,
867 EmuVariablesUpdatedCallback
,
869 &mEmuVariableEventReg
871 PcdSet64 (PcdEmuVariableEvent
, (UINT64
)(UINTN
) mEmuVariableEvent
);
878 PlatformBdsRestoreNvVarsFromHardDisk (
881 VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage
);
882 VisitAllInstancesOfProtocol (
883 &gEfiSimpleFileSystemProtocolGuid
,
884 VisitingFileSystemInstance
,
892 PlatformBdsConnectSequence (
899 Connect with predeined platform connect sequence,
900 the OEM/IBV can customize with their own connect sequence.
914 DEBUG ((EFI_D_INFO
, "PlatformBdsConnectSequence\n"));
919 // Here we can get the customized platform connect sequence
920 // Notes: we can connect with new variable which record the
921 // last time boots connect device path sequence
923 while (gPlatformConnectSequence
[Index
] != NULL
) {
925 // Build the platform boot option
927 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
932 // Just use the simple policy to connect all devices
936 PciInitialization ();
939 // Clear the logo after all devices are connected.
941 gST
->ConOut
->ClearScreen (gST
->ConOut
);
945 PlatformBdsGetDriverOption (
946 IN OUT LIST_ENTRY
*BdsDriverLists
952 Load the predefined driver option, OEM/IBV can customize this
953 to load their own drivers
957 BdsDriverLists - The header of the driver option link list.
965 DEBUG ((EFI_D_INFO
, "PlatformBdsGetDriverOption\n"));
970 PlatformBdsDiagnostics (
971 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
972 IN BOOLEAN QuietBoot
,
973 IN BASEM_MEMORY_TEST BaseMemoryTest
979 Perform the platform diagnostic, such like test memory. OEM/IBV also
980 can customize this fuction to support specific platform diagnostic.
984 MemoryTestLevel - The memory test intensive level
986 QuietBoot - Indicate if need to enable the quiet boot
988 BaseMemoryTest - A pointer to BaseMemoryTest()
998 DEBUG ((EFI_D_INFO
, "PlatformBdsDiagnostics\n"));
1001 // Here we can decide if we need to show
1002 // the diagnostics screen
1003 // Notes: this quiet boot code should be remove
1004 // from the graphic lib
1007 EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1009 // Perform system diagnostic
1011 Status
= BaseMemoryTest (MemoryTestLevel
);
1012 if (EFI_ERROR (Status
)) {
1013 DisableQuietBoot ();
1019 // Perform system diagnostic
1021 Status
= BaseMemoryTest (MemoryTestLevel
);
1027 PlatformBdsPolicyBehavior (
1028 IN OUT LIST_ENTRY
*DriverOptionList
,
1029 IN OUT LIST_ENTRY
*BootOptionList
,
1030 IN PROCESS_CAPSULES ProcessCapsules
,
1031 IN BASEM_MEMORY_TEST BaseMemoryTest
1035 Routine Description:
1037 The function will excute with as the platform policy, current policy
1038 is driven by boot mode. IBV/OEM can customize this code for their specific
1043 DriverOptionList - The header of the driver option link list
1045 BootOptionList - The header of the boot option link list
1047 ProcessCapsules - A pointer to ProcessCapsules()
1049 BaseMemoryTest - A pointer to BaseMemoryTest()
1059 EFI_EVENT UserInputDurationTime
;
1061 BDS_COMMON_OPTION
*BootOption
;
1065 EFI_BOOT_MODE BootMode
;
1067 DEBUG ((EFI_D_INFO
, "PlatformBdsPolicyBehavior\n"));
1069 ConnectRootBridge ();
1072 // Try to restore variables from the hard disk early so
1073 // they can be used for the other BDS connect operations.
1075 PlatformBdsRestoreNvVarsFromHardDisk ();
1078 // Init the time out value
1080 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1083 // Load the driver option as the driver option list
1085 PlatformBdsGetDriverOption (DriverOptionList
);
1088 // Get current Boot Mode
1090 Status
= BdsLibGetBootMode (&BootMode
);
1091 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1094 // Go the different platform policy with different boot mode
1095 // Notes: this part code can be change with the table policy
1097 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1099 // Connect platform console
1101 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1102 if (EFI_ERROR (Status
)) {
1104 // Here OEM/IBV can customize with defined action
1106 PlatformBdsNoConsoleAction ();
1109 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1111 Status
= gBS
->CreateEvent (
1116 &UserInputDurationTime
1118 ASSERT (Status
== EFI_SUCCESS
);
1119 Status
= gBS
->SetTimer (UserInputDurationTime
, TimerRelative
, 3000000);
1120 ASSERT (Status
== EFI_SUCCESS
);
1122 // Memory test and Logo show
1124 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1127 // Perform some platform specific connect sequence
1129 PlatformBdsConnectSequence ();
1132 // Give one chance to enter the setup if we
1133 // have the time out
1136 //PlatformBdsEnterFrontPage (Timeout, FALSE);
1139 DEBUG ((EFI_D_INFO
, "BdsLibConnectAll\n"));
1140 BdsLibConnectAll ();
1141 BdsLibEnumerateAllBootOption (BootOptionList
);
1144 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1145 // checking code in real production tip.
1147 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1148 // and do enumerate all the default boot options. But in development system board, the boot mode
1149 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1150 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1152 Status
= BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1153 if (EFI_ERROR(Status
)) {
1155 // If cannot find "BootOrder" variable, it may be first boot.
1156 // Try to connect all devices and enumerate all boot options here.
1158 BdsLibConnectAll ();
1159 BdsLibEnumerateAllBootOption (BootOptionList
);
1163 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1164 // BDS should still give user a chance to enter Setup
1166 // Connect first boot option, and then check user input before exit
1168 for (Link
= BootOptionList
->ForwardLink
; Link
!= BootOptionList
;Link
= Link
->ForwardLink
) {
1169 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
1170 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
1172 // skip the header of the link list, becuase it has no boot option
1177 // Make sure the boot option device path connected, but ignore the BBS device path
1179 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
1180 BdsLibConnectDevicePath (BootOption
->DevicePath
);
1187 // Check whether the user input after the duration time has expired
1189 OldTpl
= EfiGetCurrentTpl();
1190 gBS
->RestoreTPL (TPL_APPLICATION
);
1191 gBS
->WaitForEvent (1, &UserInputDurationTime
, &Index
);
1192 gBS
->CloseEvent (UserInputDurationTime
);
1193 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1194 gBS
->RaiseTPL (OldTpl
);
1196 if (!EFI_ERROR (Status
)) {
1198 // Enter Setup if user input
1201 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1209 PlatformBdsBootSuccess (
1210 IN BDS_COMMON_OPTION
*Option
1214 Routine Description:
1216 Hook point after a boot attempt succeeds. We don't expect a boot option to
1217 return, so the EFI 1.0 specification defines that you will default to an
1218 interactive mode and stop processing the BootOrder list in this case. This
1219 is alos a platform implementation and can be customized by IBV/OEM.
1223 Option - Pointer to Boot Option that succeeded to boot.
1233 DEBUG ((EFI_D_INFO
, "PlatformBdsBootSuccess\n"));
1235 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1236 // select loop then we need to pop up a UI and wait for user input.
1238 TmpStr
= Option
->StatusString
;
1239 if (TmpStr
!= NULL
) {
1240 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1247 PlatformBdsBootFail (
1248 IN BDS_COMMON_OPTION
*Option
,
1249 IN EFI_STATUS Status
,
1250 IN CHAR16
*ExitData
,
1251 IN UINTN ExitDataSize
1255 Routine Description:
1257 Hook point after a boot attempt fails.
1261 Option - Pointer to Boot Option that failed to boot.
1263 Status - Status returned from failed boot.
1265 ExitData - Exit data returned from failed boot.
1267 ExitDataSize - Exit data size returned from failed boot.
1277 DEBUG ((EFI_D_INFO
, "PlatformBdsBootFail\n"));
1280 // If Boot returned with failed status then we need to pop up a UI and wait
1283 TmpStr
= Option
->StatusString
;
1284 if (TmpStr
!= NULL
) {
1285 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1291 PlatformBdsNoConsoleAction (
1296 Routine Description:
1298 This function is remained for IBV/OEM to do some platform action,
1299 if there no console device can be connected.
1307 EFI_SUCCESS - Direct return success now.
1311 DEBUG ((EFI_D_INFO
, "PlatformBdsNoConsoleAction\n"));
1317 PlatformBdsLockNonUpdatableFlash (
1321 DEBUG ((EFI_D_INFO
, "PlatformBdsLockNonUpdatableFlash\n"));
1327 This notification function is invoked when an instance of the
1328 EFI_DEVICE_PATH_PROTOCOL is produced.
1330 @param Event The event that occured
1331 @param Context For EFI compatiblity. Not used.
1344 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
1345 ATAPI_DEVICE_PATH
*Atapi
;
1348 // Examine all new handles
1352 // Get the next handle
1354 BufferSize
= sizeof (Handle
);
1355 Status
= gBS
->LocateHandle (
1358 mEfiDevPathNotifyReg
,
1364 // If not found, we're done
1366 if (EFI_NOT_FOUND
== Status
) {
1370 if (EFI_ERROR (Status
)) {
1375 // Get the DevicePath protocol on that handle
1377 Status
= gBS
->HandleProtocol (Handle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&DevPathNode
);
1378 ASSERT_EFI_ERROR (Status
);
1380 while (!IsDevicePathEnd (DevPathNode
)) {
1382 // Find the handler to dump this device path node
1385 (DevicePathType(DevPathNode
) == MESSAGING_DEVICE_PATH
) &&
1386 (DevicePathSubType(DevPathNode
) == MSG_ATAPI_DP
)
1388 Atapi
= (ATAPI_DEVICE_PATH
*) DevPathNode
;
1394 (Atapi
->PrimarySecondary
== 1) ? 0x42: 0x40
1401 // Next device path node
1403 DevPathNode
= NextDevicePathNode (DevPathNode
);
1412 InstallDevicePathCallback (
1416 DEBUG ((EFI_D_INFO
, "Registered NotifyDevPath Event\n"));
1417 mEfiDevPathEvent
= EfiCreateProtocolNotifyEvent (
1418 &gEfiDevicePathProtocolGuid
,
1422 &mEfiDevPathNotifyReg
1427 Lock the ConsoleIn device in system table. All key
1428 presses will be ignored until the Password is typed in. The only way to
1429 disable the password is to type it in to a ConIn device.
1431 @param Password Password used to lock ConIn device.
1433 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1434 @retval EFI_UNSUPPORTED Password not found
1443 return EFI_UNSUPPORTED
;
1453 PCI_DATA_STRUCTURE
*Pcir
;
1457 // The virtual machines sometimes load the video rom image
1458 // directly at the legacy video BIOS location of C000:0000,
1459 // and do not implement the PCI expansion ROM feature.
1461 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) 0xc0000;
1462 RomSize
= Pcir
->ImageLength
* 512;
1463 PciRomLoadEfiDriversFromRomImage (0xc0000, RomSize
);
1469 PciRomLoadEfiDriversFromRomImage (
1470 IN EFI_PHYSICAL_ADDRESS Rom
,
1475 EFI_PCI_EXPANSION_ROM_HEADER
*EfiRomHeader
;
1476 PCI_DATA_STRUCTURE
*Pcir
;
1481 EFI_HANDLE ImageHandle
;
1483 EFI_STATUS retStatus
;
1484 EFI_DEVICE_PATH_PROTOCOL
*FilePath
;
1486 UINT32 DestinationSize
;
1490 VOID
*DecompressedImageBuffer
;
1492 EFI_DECOMPRESS_PROTOCOL
*Decompress
;
1494 FileName
= L
"PciRomInMemory";
1496 //FileName = L"PciRom Addr=0000000000000000";
1497 //HexToString (&FileName[12], Rom, 16);
1500 retStatus
= EFI_NOT_FOUND
;
1501 RomOffset
= (UINTN
) Rom
;
1505 EfiRomHeader
= (EFI_PCI_EXPANSION_ROM_HEADER
*) (UINTN
) RomOffset
;
1507 if (EfiRomHeader
->Signature
!= 0xaa55) {
1511 Pcir
= (PCI_DATA_STRUCTURE
*) (UINTN
) (RomOffset
+ EfiRomHeader
->PcirOffset
);
1512 ImageSize
= Pcir
->ImageLength
* 512;
1514 if ((Pcir
->CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) &&
1515 (EfiRomHeader
->EfiSignature
== EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
) ) {
1517 if ((EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
) ||
1518 (EfiRomHeader
->EfiSubsystem
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) ) {
1520 ImageOffset
= EfiRomHeader
->EfiImageHeaderOffset
;
1521 ImageSize
= EfiRomHeader
->InitializationSize
* 512;
1523 ImageBuffer
= (VOID
*) (UINTN
) (RomOffset
+ ImageOffset
);
1524 ImageLength
= ImageSize
- ImageOffset
;
1525 DecompressedImageBuffer
= NULL
;
1528 // decompress here if needed
1531 if (EfiRomHeader
->CompressionType
> EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
1535 if (EfiRomHeader
->CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
1536 Status
= gBS
->LocateProtocol (&gEfiDecompressProtocolGuid
, NULL
, (VOID
**) &Decompress
);
1537 if (EFI_ERROR (Status
)) {
1541 Status
= Decompress
->GetInfo (
1548 if (!EFI_ERROR (Status
)) {
1549 DecompressedImageBuffer
= NULL
;
1550 DecompressedImageBuffer
= AllocatePool (DestinationSize
);
1551 if (DecompressedImageBuffer
!= NULL
) {
1552 Scratch
= AllocatePool (ScratchSize
);
1553 if (Scratch
!= NULL
) {
1554 Status
= Decompress
->Decompress (
1558 DecompressedImageBuffer
,
1563 if (!EFI_ERROR (Status
)) {
1564 ImageBuffer
= DecompressedImageBuffer
;
1565 ImageLength
= DestinationSize
;
1569 gBS
->FreePool (Scratch
);
1579 // load image and start image
1582 FilePath
= FileDevicePath (NULL
, FileName
);
1584 Status
= gBS
->LoadImage (
1592 if (!EFI_ERROR (Status
)) {
1593 Status
= gBS
->StartImage (ImageHandle
, NULL
, NULL
);
1594 if (!EFI_ERROR (Status
)) {
1598 if (FilePath
!= NULL
) {
1599 gBS
->FreePool (FilePath
);
1603 if (DecompressedImageBuffer
!= NULL
) {
1604 gBS
->FreePool (DecompressedImageBuffer
);
1610 RomOffset
= RomOffset
+ ImageSize
;
1612 } while (((Pcir
->Indicator
& 0x80) == 0x00) && ((RomOffset
- (UINTN
) Rom
) < RomSize
));