3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file include all platform action which can be customized
23 #include "BdsPlatform.h"
25 #define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
27 CHAR16 mFirmwareVendor
[] = L
"TianoCore.org";
28 extern BOOLEAN gConnectAllHappened
;
29 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath
;
31 // BDS Platform Functions
35 GetSystemTablesFromHob (
41 Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
52 EFI_HOB_HANDOFF_INFO_TABLE
*HobList
;
53 EFI_HOB_HANDOFF_INFO_TABLE
*HobStart
;
54 EFI_PHYSICAL_ADDRESS
*Table
;
56 EFI_GUID
*TableGuidArray
[] = {
57 &gEfiAcpi20TableGuid
, &gEfiAcpiTableGuid
, &gEfiSmbiosTableGuid
, &gEfiMpsTableGuid
63 Status
= EfiGetSystemConfigurationTable (&gEfiHobListGuid
, (VOID
*) &HobList
);
64 if (EFI_ERROR (Status
)) {
69 // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
71 for (Index
= 0; Index
< sizeof (TableGuidArray
) / sizeof (*TableGuidArray
); ++Index
) {
74 Table
= GetNextGuidHob (TableGuidArray
[Index
], &HobStart
);
75 if (!EFI_ERROR (Status
)) {
78 // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
79 // According to UEFI Spec, we should make sure Smbios table,
80 // ACPI table and Mps tables kept in memory of specified type
82 ConvertSystemTable(TableGuidArray
[Index
], &Table
);
83 gBS
->InstallConfigurationTable (TableGuidArray
[Index
], (VOID
*)Table
);
91 #define EFI_LDR_MEMORY_DESCRIPTOR_GUID \
92 { 0x7701d7e5, 0x7d1d, 0x4432, 0xa4, 0x68, 0x67, 0x3d, 0xab, 0x8a, 0xde, 0x60 }
94 EFI_GUID gEfiLdrMemoryDescriptorGuid
= EFI_LDR_MEMORY_DESCRIPTOR_GUID
;
99 EFI_HOB_GUID_TYPE Hob
;
101 EFI_MEMORY_DESCRIPTOR
*MemDesc
;
112 EFI_MEMORY_DESCRIPTOR
*MemMap
;
113 EFI_MEMORY_DESCRIPTOR
*MemMapPtr
;
115 UINTN MapKey
, DescriptorSize
;
117 UINT32 DescriptorVersion
;
123 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
124 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
125 MemMapSize
+= EFI_PAGE_SIZE
;
126 Status
= gBS
->AllocatePool (EfiBootServicesData
, MemMapSize
, &MemMap
);
127 ASSERT (Status
== EFI_SUCCESS
);
128 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
129 ASSERT (Status
== EFI_SUCCESS
);
132 ASSERT (DescriptorVersion
== EFI_MEMORY_DESCRIPTOR_VERSION
);
134 for (Index
= 0; Index
< MemMapSize
/ DescriptorSize
; Index
++) {
135 Bytes
= LShiftU64 (MemMap
->NumberOfPages
, 12);
136 DEBUG ((EFI_D_ERROR
, "%lX-%lX %lX %lX %X\n",
137 MemMap
->PhysicalStart
,
138 MemMap
->PhysicalStart
+ Bytes
- 1,
139 MemMap
->NumberOfPages
,
141 (UINTN
)MemMap
->Type
));
142 MemMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemMap
+ DescriptorSize
);
145 gBS
->FreePool (MemMapPtr
);
155 EFI_HOB_HANDOFF_INFO_TABLE
*HobList
;
157 MEMORY_DESC_HOB MemoryDescHob
;
159 EFI_PHYSICAL_ADDRESS Memory
;
164 Status
= EfiGetSystemConfigurationTable (&gEfiHobListGuid
, (VOID
*) &HobList
);
165 if (EFI_ERROR (Status
)) {
169 Table
= GetNextGuidHob (&gEfiLdrMemoryDescriptorGuid
, &HobList
);
170 MemoryDescHob
.MemDescCount
= *(UINTN
*)Table
;
171 MemoryDescHob
.MemDesc
= *(EFI_MEMORY_DESCRIPTOR
**)((UINTN
)Table
+ sizeof(UINTN
));
174 // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
176 for (Index
= 0; Index
< MemoryDescHob
.MemDescCount
; Index
++) {
177 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
< 0x100000) {
180 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
>= 0x100000000) {
183 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiReservedMemoryType
) ||
184 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
185 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
) ||
186 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
187 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
188 DEBUG ((EFI_D_ERROR
, "PhysicalStart - 0x%x, ", MemoryDescHob
.MemDesc
[Index
].PhysicalStart
));
189 DEBUG ((EFI_D_ERROR
, "PageNumber - 0x%x, ", MemoryDescHob
.MemDesc
[Index
].NumberOfPages
));
190 DEBUG ((EFI_D_ERROR
, "Type - 0x%x\n", MemoryDescHob
.MemDesc
[Index
].Type
));
191 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
192 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
)) {
194 // Skip RuntimeSevicesData and RuntimeServicesCode, they are BFV
198 Status
= gDS
->AddMemorySpace (
199 EfiGcdMemoryTypeSystemMemory
,
200 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
201 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
),
202 MemoryDescHob
.MemDesc
[Index
].Attribute
204 if (EFI_ERROR (Status
)) {
205 DEBUG ((EFI_D_ERROR
, "AddMemorySpace fail!\n"));
206 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
207 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
209 // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
210 // For EfiReservedMemoryType, there maybe overlap. So skip check here.
212 // ASSERT_EFI_ERROR (Status);
217 Memory
= MemoryDescHob
.MemDesc
[Index
].PhysicalStart
;
218 Status
= gBS
->AllocatePages (
220 MemoryDescHob
.MemDesc
[Index
].Type
,
221 (UINTN
)MemoryDescHob
.MemDesc
[Index
].NumberOfPages
,
224 if (EFI_ERROR (Status
)) {
225 DEBUG ((EFI_D_ERROR
, "AllocatePages fail!\n"));
227 // For the page added, it must be allocated.
229 // ASSERT_EFI_ERROR (Status);
238 DisableUsbLegacySupport(
244 Disabble the USB legacy Support in all Ehci and Uhci.
245 This function assume all PciIo handles have been created in system.
256 EFI_HANDLE
*HandleArray
;
257 UINTN HandleArrayCount
;
259 EFI_PCI_IO_PROTOCOL
*PciIo
;
268 // Find the usb host controller
270 Status
= gBS
->LocateHandleBuffer (
272 &gEfiPciIoProtocolGuid
,
277 if (!EFI_ERROR (Status
)) {
278 for (Index
= 0; Index
< HandleArrayCount
; Index
++) {
279 Status
= gBS
->HandleProtocol (
281 &gEfiPciIoProtocolGuid
,
284 if (!EFI_ERROR (Status
)) {
286 // Find the USB host controller controller
288 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x09, 3, &Class
);
289 if (!EFI_ERROR (Status
)) {
290 if ((PCI_CLASS_SERIAL
== Class
[2]) &&
291 (PCI_CLASS_SERIAL_USB
== Class
[1])) {
292 if (PCI_CLASSC_PI_UHCI
== Class
[0]) {
294 // Found the UHCI, then disable the legacy support
297 Status
= PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0xC0, 1, &Command
);
298 } else if (PCI_CLASSC_PI_EHCI
== Class
[0]) {
300 // Found the EHCI, then disable the legacy support
302 Status
= PciIo
->Mem
.Read (
306 (UINT64
) 0x08, //EHC_HCCPARAMS_OFFSET
311 ExtendCap
= (HcCapParams
>> 8) & 0xFF;
313 // Disable the SMI in USBLEGCTLSTS firstly
315 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
317 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
320 // Get EHCI Ownership from legacy bios
322 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
323 Value
|= (0x1 << 24);
324 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
330 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
332 if ((Value
& 0x01010000) == 0x01000000) {
344 gBS
->FreePool (HandleArray
);
351 IN EFI_BDS_ARCH_PROTOCOL_INSTANCE
*PrivateData
357 Platform Bds init. Incude the platform firmware vendor, revision
362 PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
371 // set firmwarevendor, here can be IBV/OEM customize
373 gST
->FirmwareVendor
= AllocateRuntimeCopyPool (
374 sizeof (mFirmwareVendor
),
377 ASSERT (gST
->FirmwareVendor
!= NULL
);
379 gST
->FirmwareRevision
= 0;
382 // Fixup Tasble CRC after we updated Firmware Vendor and Revision
384 gBS
->CalculateCrc32 ((VOID
*) gST
, sizeof (EFI_SYSTEM_TABLE
), &gST
->Hdr
.CRC32
);
388 GetPciExpressBaseAddressForRootBridge (
389 IN UINTN HostBridgeNumber
,
390 IN UINTN RootBridgeNumber
395 This routine is to get PciExpress Base Address for this RootBridge
398 HostBridgeNumber - The number of HostBridge
399 RootBridgeNumber - The number of RootBridge
402 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
406 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
*PciExpressBaseAddressInfo
;
415 // Get Hob List from configuration table
417 Status
= EfiGetSystemConfigurationTable (&gEfiHobListGuid
, &HobList
);
418 if (EFI_ERROR (Status
)) {
423 // Get PciExpressAddressInfo Hob
425 PciExpressBaseAddressInfo
= NULL
;
426 PciExpressBaseAddressInfo
= GetNextGuidHob (&gEfiPciExpressBaseAddressGuid
, &HobList
);
429 // Search the PciExpress Base Address in the Hob for current RootBridge
431 Number
= (UINT32
)(BufferSize
/ sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
));
432 for (Index
= 0; Index
< Number
; Index
++) {
433 if ((PciExpressBaseAddressInfo
[Index
].HostBridgeNumber
== HostBridgeNumber
) &&
434 (PciExpressBaseAddressInfo
[Index
].RootBridgeNumber
== RootBridgeNumber
)) {
435 return PciExpressBaseAddressInfo
[Index
].PciExpressBaseAddress
;
440 // Do not find the PciExpress Base Address in the Hob
446 PatchPciRootBridgeDevicePath (
447 IN UINTN HostBridgeNumber
,
448 IN UINTN RootBridgeNumber
,
449 IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH
*RootBridge
452 UINT64 PciExpressBase
;
454 PciExpressBase
= GetPciExpressBaseAddressForRootBridge (HostBridgeNumber
, RootBridgeNumber
);
456 if (PciExpressBase
!= 0) {
457 RootBridge
->PciRootBridge
.HID
= EISA_PNP_ID(0x0A08);
477 EFI_SUCCESS - Connect RootBridge successfully.
478 EFI_STATUS - Connect RootBridge fail.
483 EFI_HANDLE RootHandle
;
486 // Patch Pci Root Bridge Device Path
488 PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0
);
491 // Make all the PCI_IO protocols on PCI Seg 0 show up
493 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
495 Status
= gBS
->LocateDevicePath (
496 &gEfiDevicePathProtocolGuid
,
497 &gPlatformRootBridges
[0],
500 if (EFI_ERROR (Status
)) {
504 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
505 if (EFI_ERROR (Status
)) {
513 PrepareLpcBridgeDevicePath (
514 IN EFI_HANDLE DeviceHandle
520 Add IsaKeyboard to ConIn,
521 add IsaSerial to ConOut, ConIn, ErrOut.
526 DeviceHandle - Handle of PCIIO protocol.
530 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
531 EFI_STATUS - No LPC bridge is added.
536 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
537 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
540 Status
= gBS
->HandleProtocol (
542 &gEfiDevicePathProtocolGuid
,
545 if (EFI_ERROR (Status
)) {
548 TempDevicePath
= DevicePath
;
553 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
555 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
560 DevicePath
= TempDevicePath
;
561 gPnp16550ComPortDeviceNode
.UID
= 0;
563 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
564 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
565 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
567 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
568 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
569 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
574 DevicePath
= TempDevicePath
;
575 gPnp16550ComPortDeviceNode
.UID
= 1;
577 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
578 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
579 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
581 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
582 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
583 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
588 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
591 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
592 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
597 EFI_HANDLE PciDeviceHandle
;
598 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
599 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
600 UINTN GopHandleCount
;
601 EFI_HANDLE
*GopHandleBuffer
;
603 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
604 return EFI_INVALID_PARAMETER
;
608 // Initialize the GopDevicePath to be PciDevicePath
610 *GopDevicePath
= PciDevicePath
;
611 TempPciDevicePath
= PciDevicePath
;
613 Status
= gBS
->LocateDevicePath (
614 &gEfiDevicePathProtocolGuid
,
618 if (EFI_ERROR (Status
)) {
623 // Try to connect this handle, so that GOP dirver could start on this
624 // device and create child handles with GraphicsOutput Protocol installed
625 // on them, then we get device paths of these child handles and select
626 // them as possible console device.
628 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
630 Status
= gBS
->LocateHandleBuffer (
632 &gEfiGraphicsOutputProtocolGuid
,
637 if (!EFI_ERROR (Status
)) {
639 // Add all the child handles as possible Console Device
641 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
642 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, &TempDevicePath
);
643 if (EFI_ERROR (Status
)) {
649 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
652 // In current implementation, we only enable one of the child handles
653 // as console device, i.e. sotre one of the child handle's device
654 // path to variable "ConOut"
655 // In futhure, we could select all child handles to be console device
658 *GopDevicePath
= TempDevicePath
;
661 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
662 // Add the integrity GOP device path.
664 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
665 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
668 gBS
->FreePool (GopHandleBuffer
);
676 PreparePciVgaDevicePath (
677 IN EFI_HANDLE DeviceHandle
683 Add PCI VGA to ConOut.
688 DeviceHandle - Handle of PCIIO protocol.
692 EFI_SUCCESS - PCI VGA is added to ConOut.
693 EFI_STATUS - No PCI VGA device is added.
698 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
699 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
700 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
704 Status
= gBS
->HandleProtocol (
706 &gEfiDevicePathProtocolGuid
,
709 if (EFI_ERROR (Status
)) {
713 #if (EFI_SPECIFICATION_VERSION >= 0x00020000)
714 GetGopDevicePath (DevicePath
, &GopDevicePath
);
715 DevicePath
= GopDevicePath
;
718 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
724 PreparePciSerialDevicePath (
725 IN EFI_HANDLE DeviceHandle
731 Add PCI Serial to ConOut, ConIn, ErrOut.
736 DeviceHandle - Handle of PCIIO protocol.
740 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
741 EFI_STATUS - No PCI Serial device is added.
746 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
749 Status
= gBS
->HandleProtocol (
751 &gEfiDevicePathProtocolGuid
,
754 if (EFI_ERROR (Status
)) {
758 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
759 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
761 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
762 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
763 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
769 DetectAndPreparePlatformPciDevicePath (
770 BOOLEAN DetectVgaOnly
776 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
780 DetectVgaOnly - Only detect VGA device if it's TRUE.
784 EFI_SUCCESS - PCI Device check and Console variable update successfully.
785 EFI_STATUS - PCI Device check or Console variable update fail.
791 EFI_HANDLE
*HandleBuffer
;
793 EFI_PCI_IO_PROTOCOL
*PciIo
;
797 // Start to check all the PciIo to find all possible device
801 Status
= gBS
->LocateHandleBuffer (
803 &gEfiPciIoProtocolGuid
,
808 if (EFI_ERROR (Status
)) {
812 for (Index
= 0; Index
< HandleCount
; Index
++) {
813 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, &PciIo
);
814 if (EFI_ERROR (Status
)) {
819 // Check for all PCI device
821 Status
= PciIo
->Pci
.Read (
825 sizeof (Pci
) / sizeof (UINT32
),
828 if (EFI_ERROR (Status
)) {
832 if (!DetectVgaOnly
) {
834 // Here we decide whether it is LPC Bridge
836 if ((IS_PCI_LPC (&Pci
)) ||
837 ((IS_PCI_ISA_PDECODE (&Pci
)) && (Pci
.Hdr
.VendorId
== 0x8086) && (Pci
.Hdr
.DeviceId
== 0x7110))) {
839 // Add IsaKeyboard to ConIn,
840 // add IsaSerial to ConOut, ConIn, ErrOut
842 PrepareLpcBridgeDevicePath (HandleBuffer
[Index
]);
846 // Here we decide which Serial device to enable in PCI bus
848 if (IS_PCI_16550SERIAL (&Pci
)) {
850 // Add them to ConOut, ConIn, ErrOut.
852 PreparePciSerialDevicePath (HandleBuffer
[Index
]);
858 // Here we decide which VGA device to enable in PCI bus
860 if (IS_PCI_VGA (&Pci
)) {
862 // Add them to ConOut.
864 PreparePciVgaDevicePath (HandleBuffer
[Index
]);
869 gBS
->FreePool (HandleBuffer
);
875 PlatformBdsConnectConsole (
876 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
882 Connect the predefined platform default console device. Always try to find
883 and enable the vga device if have.
887 PlatformConsole - Predfined platform default console device array.
891 EFI_SUCCESS - Success connect at least one ConIn and ConOut
892 device, there must have one ConOut device is
895 EFI_STATUS - Return the status of
896 BdsLibConnectAllDefaultConsoles ()
902 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
903 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
904 UINTN DevicePathSize
;
907 // Connect RootBridge
909 ConnectRootBridge ();
911 VarConout
= BdsLibGetVariableAndSize (
913 &gEfiGlobalVariableGuid
,
916 VarConin
= BdsLibGetVariableAndSize (
918 &gEfiGlobalVariableGuid
,
921 if (VarConout
== NULL
|| VarConin
== NULL
) {
923 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
925 DetectAndPreparePlatformPciDevicePath (FALSE
);
928 // Have chance to connect the platform default console,
929 // the platform default console is the minimue device group
930 // the platform should support
932 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
934 // Update the console variable with the connect type
936 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
937 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
939 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
940 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
942 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
943 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
948 // Only detect VGA device and add them to ConOut
950 DetectAndPreparePlatformPciDevicePath (TRUE
);
954 // The ConIn devices connection will start the USB bus, should disable all
955 // Usb legacy support firstly.
956 // Caution: Must ensure the PCI bus driver has been started. Since the
957 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
959 Status
= DisableUsbLegacySupport();
962 // Connect the all the default console with current cosole variable
964 Status
= BdsLibConnectAllDefaultConsoles ();
965 if (EFI_ERROR (Status
)) {
973 PlatformBdsConnectSequence (
980 Connect with predeined platform connect sequence,
981 the OEM/IBV can customize with their own connect sequence.
998 // Here we can get the customized platform connect sequence
999 // Notes: we can connect with new variable which record the
1000 // last time boots connect device path sequence
1002 while (gPlatformConnectSequence
[Index
] != NULL
) {
1004 // Build the platform boot option
1006 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1013 PlatformBdsGetDriverOption (
1014 IN OUT LIST_ENTRY
*BdsDriverLists
1018 Routine Description:
1020 Load the predefined driver option, OEM/IBV can customize this
1021 to load their own drivers
1025 BdsDriverLists - The header of the driver option link list.
1038 // Here we can get the customized platform driver option
1040 while (gPlatformDriverOption
[Index
] != NULL
) {
1042 // Build the platform boot option
1044 BdsLibRegisterNewOption (BdsDriverLists
, gPlatformDriverOption
[Index
], NULL
, L
"DriverOrder");
1051 PlatformBdsDiagnostics (
1052 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1053 IN BOOLEAN QuietBoot
1057 Routine Description:
1059 Perform the platform diagnostic, such like test memory. OEM/IBV also
1060 can customize this fuction to support specific platform diagnostic.
1064 MemoryTestLevel - The memory test intensive level
1066 QuietBoot - Indicate if need to enable the quiet boot
1077 // Here we can decide if we need to show
1078 // the diagnostics screen
1079 // Notes: this quiet boot code should be remove
1080 // from the graphic lib
1083 Status
= EnableQuietBootEx (&gEfiDefaultBmpLogoGuid
, mBdsImageHandle
);
1084 if (EFI_ERROR (Status
)) {
1085 DisableQuietBoot ();
1090 // Perform system diagnostic
1092 Status
= BdsMemoryTest (MemoryTestLevel
);
1093 if (EFI_ERROR (Status
)) {
1094 DisableQuietBoot ();
1100 // Perform system diagnostic
1102 Status
= BdsMemoryTest (MemoryTestLevel
);
1106 PlatformBdsPolicyBehavior (
1107 IN EFI_BDS_ARCH_PROTOCOL_INSTANCE
*PrivateData
,
1108 IN OUT LIST_ENTRY
*DriverOptionList
,
1109 IN OUT LIST_ENTRY
*BootOptionList
1113 Routine Description:
1115 The function will excute with as the platform policy, current policy
1116 is driven by boot mode. IBV/OEM can customize this code for their specific
1121 PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance
1123 DriverOptionList - The header of the driver option link list
1125 BootOptionList - The header of the boot option link list
1135 EFI_EVENT UserInputDurationTime
;
1137 BDS_COMMON_OPTION
*BootOption
;
1143 // Init the time out value
1145 Timeout
= BdsLibGetTimeout ();
1148 // Load the driver option as the driver option list
1150 PlatformBdsGetDriverOption (DriverOptionList
);
1153 // Get current Boot Mode
1155 Status
= BdsLibGetBootMode (&PrivateData
->BootMode
);
1156 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", PrivateData
->BootMode
));
1159 // Go the different platform policy with different boot mode
1160 // Notes: this part code can be change with the table policy
1162 ASSERT (PrivateData
->BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1164 // Connect platform console
1166 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1167 if (EFI_ERROR (Status
)) {
1169 // Here OEM/IBV can customize with defined action
1171 PlatformBdsNoConsoleAction ();
1174 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1176 Status
= gBS
->CreateEvent (
1181 &UserInputDurationTime
1183 ASSERT (Status
== EFI_SUCCESS
);
1184 Status
= gBS
->SetTimer (UserInputDurationTime
, TimerRelative
, 3000000);
1185 ASSERT (Status
== EFI_SUCCESS
);
1187 // Memory test and Logo show
1189 PlatformBdsDiagnostics (IGNORE
, TRUE
);
1192 // Perform some platform specific connect sequence
1194 PlatformBdsConnectSequence ();
1197 // Give one chance to enter the setup if we
1198 // have the time out
1201 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1205 //BdsLibConnectAll ();
1206 //BdsLibEnumerateAllBootOption (BootOptionList);
1209 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1210 // checking code in real production tip.
1212 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1213 // and do enumerate all the default boot options. But in development system board, the boot mode
1214 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1215 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1217 Status
= BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1218 if (EFI_ERROR(Status
)) {
1220 // If cannot find "BootOrder" variable, it may be first boot.
1221 // Try to connect all devices and enumerate all boot options here.
1223 BdsLibConnectAll ();
1224 BdsLibEnumerateAllBootOption (BootOptionList
);
1228 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1229 // BDS should still give user a chance to enter Setup
1231 // Connect first boot option, and then check user input before exit
1233 for (Link
= BootOptionList
->ForwardLink
; Link
!= BootOptionList
;Link
= Link
->ForwardLink
) {
1234 BootOption
= CR (Link
, BDS_COMMON_OPTION
, Link
, BDS_LOAD_OPTION_SIGNATURE
);
1235 if (!IS_LOAD_OPTION_TYPE (BootOption
->Attribute
, LOAD_OPTION_ACTIVE
)) {
1237 // skip the header of the link list, becuase it has no boot option
1242 // Make sure the boot option device path connected, but ignore the BBS device path
1244 if (DevicePathType (BootOption
->DevicePath
) != BBS_DEVICE_PATH
) {
1245 BdsLibConnectDevicePath (BootOption
->DevicePath
);
1252 // Check whether the user input after the duration time has expired
1254 OldTpl
= EfiGetCurrentTpl();
1255 gBS
->RestoreTPL (TPL_APPLICATION
);
1256 gBS
->WaitForEvent (1, &UserInputDurationTime
, &Index
);
1257 gBS
->CloseEvent (UserInputDurationTime
);
1258 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1259 gBS
->RaiseTPL (OldTpl
);
1261 if (!EFI_ERROR (Status
)) {
1263 // Enter Setup if user input
1266 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1274 PlatformBdsBootSuccess (
1275 IN BDS_COMMON_OPTION
*Option
1279 Routine Description:
1281 Hook point after a boot attempt succeeds. We don't expect a boot option to
1282 return, so the EFI 1.0 specification defines that you will default to an
1283 interactive mode and stop processing the BootOrder list in this case. This
1284 is alos a platform implementation and can be customized by IBV/OEM.
1288 Option - Pointer to Boot Option that succeeded to boot.
1299 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1300 // select loop then we need to pop up a UI and wait for user input.
1302 TmpStr
= Option
->StatusString
;
1303 if (TmpStr
!= NULL
) {
1304 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1305 gBS
->FreePool (TmpStr
);
1310 PlatformBdsBootFail (
1311 IN BDS_COMMON_OPTION
*Option
,
1312 IN EFI_STATUS Status
,
1313 IN CHAR16
*ExitData
,
1314 IN UINTN ExitDataSize
1318 Routine Description:
1320 Hook point after a boot attempt fails.
1324 Option - Pointer to Boot Option that failed to boot.
1326 Status - Status returned from failed boot.
1328 ExitData - Exit data returned from failed boot.
1330 ExitDataSize - Exit data size returned from failed boot.
1341 // If Boot returned with failed status then we need to pop up a UI and wait
1344 TmpStr
= Option
->StatusString
;
1345 if (TmpStr
!= NULL
) {
1346 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1347 gBS
->FreePool (TmpStr
);
1353 PlatformBdsNoConsoleAction (
1358 Routine Description:
1360 This function is remained for IBV/OEM to do some platform action,
1361 if there no console device can be connected.
1369 EFI_SUCCESS - Direct return success now.
1377 ConvertSystemTable (
1378 IN EFI_GUID
*TableGuid
,
1383 Routine Description:
1384 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1386 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1387 So here we just check if the range is E/F seg,
1388 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1391 TableGuid - Guid of the table
1392 Table - pointer to the table
1395 EFI_SUCEESS - Convert Table successfully
1405 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1407 AcpiHeader
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1409 if (CompareGuid(TableGuid
, &gEfiAcpiTableGuid
) || CompareGuid(TableGuid
, &gEfiAcpi20TableGuid
)){
1410 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
== 0x00){
1412 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1414 AcpiTableLen
= sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1415 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
>= 0x02){
1417 // If Acpi 2.0 or later, use RSDP Length fied.
1419 AcpiTableLen
= ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Length
;
1422 // Invalid Acpi Version, return
1424 return EFI_UNSUPPORTED
;
1426 Status
= ConvertAcpiTable (AcpiTableLen
, Table
);
1431 // If matches smbios guid, convert Smbios table.
1433 if (CompareGuid(TableGuid
, &gEfiSmbiosTableGuid
)){
1434 Status
= ConvertSmbiosTable (Table
);
1439 // If the table is MP table?
1441 if (CompareGuid(TableGuid
, &gEfiMpsTableGuid
)){
1442 Status
= ConvertMpsTable (Table
);
1446 return EFI_UNSUPPORTED
;
1456 Routine Description:
1457 Caculate buffer checksum (8-bit)
1460 Buffer - Pointer to Buffer that to be caculated
1461 Length - How many bytes are to be caculated
1464 Checksum of the buffer
1472 Ptr8
= (UINT8
*) Buffer
;
1474 while (Length
> 0) {
1475 CheckSum
= (UINT8
) (CheckSum
+ *Ptr8
++);
1479 return ((0xFF - CheckSum
) + 1);
1489 Routine Description:
1490 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1492 As in legacy Bios, ACPI table is required to place in E/F Seg,
1493 So here we just check if the range is E/F seg,
1494 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1497 TableLen - Acpi RSDP length
1498 Table - pointer to the table
1501 EFI_SUCEESS - Convert Table successfully
1509 EFI_PHYSICAL_ADDRESS BufferPtr
;
1512 AcpiTableOri
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1513 if (((UINTN
)AcpiTableOri
< 0x100000) && ((UINTN
)AcpiTableOri
> 0xE0000)) {
1514 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1515 Status
= gBS
->AllocatePages (
1518 EFI_SIZE_TO_PAGES(TableLen
),
1521 ASSERT_EFI_ERROR (Status
);
1522 AcpiTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1523 CopyMem (AcpiTableNew
, AcpiTableOri
, TableLen
);
1525 AcpiTableNew
= AcpiTableOri
;
1528 // Change configuration table Pointer
1530 *Table
= AcpiTableNew
;
1536 ConvertSmbiosTable (
1541 Routine Description:
1543 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1545 As in legacy Bios, Smbios table is required to place in E/F Seg,
1546 So here we just check if the range is F seg,
1547 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1549 Table - pointer to the table
1552 EFI_SUCEESS - Convert Table successfully
1557 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableNew
;
1558 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableOri
;
1560 UINT32 SmbiosEntryLen
;
1562 EFI_PHYSICAL_ADDRESS BufferPtr
;
1564 SmbiosTableNew
= NULL
;
1565 SmbiosTableOri
= NULL
;
1568 // Get Smibos configuration Table
1570 SmbiosTableOri
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)(*(UINT64
*)(*Table
));
1572 if ((SmbiosTableOri
== NULL
) ||
1573 ((UINTN
)SmbiosTableOri
> 0x100000) ||
1574 ((UINTN
)SmbiosTableOri
< 0xF0000)){
1578 // Relocate the Smibos memory
1580 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1581 if (SmbiosTableOri
->SmbiosBcdRevision
!= 0x21) {
1582 SmbiosEntryLen
= SmbiosTableOri
->EntryPointLength
;
1585 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1587 SmbiosEntryLen
= 0x1F;
1589 BufferLen
= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
) + SmbiosTableOri
->TableLength
;
1590 Status
= gBS
->AllocatePages (
1593 EFI_SIZE_TO_PAGES(BufferLen
),
1596 ASSERT_EFI_ERROR (Status
);
1597 SmbiosTableNew
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)BufferPtr
;
1604 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1606 BufferPtr
+= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
);
1608 (VOID
*)(UINTN
)BufferPtr
,
1609 (VOID
*)(UINTN
)(SmbiosTableOri
->TableAddress
),
1610 SmbiosTableOri
->TableLength
1612 SmbiosTableNew
->TableAddress
= (UINT32
)BufferPtr
;
1613 SmbiosTableNew
->IntermediateChecksum
= 0;
1614 SmbiosTableNew
->IntermediateChecksum
=
1615 GetBufferCheckSum ((UINT8
*)SmbiosTableNew
+ 0x10, SmbiosEntryLen
-0x10);
1617 // Change the SMBIOS pointer
1619 *Table
= SmbiosTableNew
;
1630 Routine Description:
1632 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1634 As in legacy Bios, MP table is required to place in E/F Seg,
1635 So here we just check if the range is E/F seg,
1636 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1638 Table - pointer to the table
1641 EFI_SUCEESS - Convert Table successfully
1648 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerOri
;
1649 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerNew
;
1650 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableOri
;
1651 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableNew
;
1655 EFI_PHYSICAL_ADDRESS BufferPtr
;
1658 // Get MP configuration Table
1660 MpsFloatingPointerOri
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)(*(UINT64
*)(*Table
));
1661 if (!(((UINTN
)MpsFloatingPointerOri
<= 0x100000) &&
1662 ((UINTN
)MpsFloatingPointerOri
>= 0xF0000))){
1666 // Get Floating pointer structure length
1668 FPLength
= MpsFloatingPointerOri
->Length
* 16;
1669 Data32
= FPLength
+ SYS_TABLE_PAD (FPLength
);
1670 MpsTableOri
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)(MpsFloatingPointerOri
->PhysicalAddress
);
1671 if (MpsTableOri
!= NULL
) {
1672 Data32
+= MpsTableOri
->BaseTableLength
;
1673 Data32
+= MpsTableOri
->ExtendedTableLength
;
1674 if (MpsTableOri
->OemTablePointer
!= 0x00) {
1675 Data32
+= SYS_TABLE_PAD (Data32
);
1676 Data32
+= MpsTableOri
->OemTableSize
;
1684 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1685 Status
= gBS
->AllocatePages (
1688 EFI_SIZE_TO_PAGES(Data32
),
1691 ASSERT_EFI_ERROR (Status
);
1692 MpsFloatingPointerNew
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)BufferPtr
;
1693 CopyMem (MpsFloatingPointerNew
, MpsFloatingPointerOri
, FPLength
);
1695 // If Mp Table exists
1697 if (MpsTableOri
!= NULL
) {
1699 // Get Mps table length, including Ext table
1701 BufferPtr
= BufferPtr
+ FPLength
+ SYS_TABLE_PAD (FPLength
);
1702 MpsTableNew
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)BufferPtr
;
1703 CopyMem (MpsTableNew
, MpsTableOri
, MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
);
1705 if ((MpsTableOri
->OemTableSize
!= 0x0000) && (MpsTableOri
->OemTablePointer
!= 0x0000)){
1706 BufferPtr
+= MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
;
1707 BufferPtr
+= SYS_TABLE_PAD (BufferPtr
);
1708 OemTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1709 OemTableOri
= (VOID
*)(UINTN
)MpsTableOri
->OemTablePointer
;
1710 CopyMem (OemTableNew
, OemTableOri
, MpsTableOri
->OemTableSize
);
1711 MpsTableNew
->OemTablePointer
= (UINT32
)(UINTN
)OemTableNew
;
1713 MpsTableNew
->Checksum
= 0;
1714 MpsTableNew
->Checksum
= GetBufferCheckSum (MpsTableNew
, MpsTableOri
->BaseTableLength
);
1715 MpsFloatingPointerNew
->PhysicalAddress
= (UINT32
)(UINTN
)MpsTableNew
;
1716 MpsFloatingPointerNew
->Checksum
= 0;
1717 MpsFloatingPointerNew
->Checksum
= GetBufferCheckSum (MpsFloatingPointerNew
, FPLength
);
1720 // Change the pointer
1722 *Table
= MpsFloatingPointerNew
;