3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
4 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 extern BOOLEAN gConnectAllHappened
;
28 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath
;
30 EFI_GUID
*gTableGuidArray
[] = {
31 &gEfiAcpi20TableGuid
, &gEfiAcpiTableGuid
, &gEfiSmbiosTableGuid
, &gEfiMpsTableGuid
35 // BDS Platform Functions
39 GetSystemTablesFromHob (
45 Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
55 EFI_PEI_HOB_POINTERS GuidHob
;
56 EFI_PEI_HOB_POINTERS HobStart
;
57 EFI_PHYSICAL_ADDRESS
*Table
;
63 HobStart
.Raw
= GetHobList ();
65 // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
67 for (Index
= 0; Index
< sizeof (gTableGuidArray
) / sizeof (*gTableGuidArray
); ++Index
) {
68 GuidHob
.Raw
= GetNextGuidHob (gTableGuidArray
[Index
], HobStart
.Raw
);
69 if (GuidHob
.Raw
!= NULL
) {
70 Table
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
73 // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
74 // According to UEFI Spec, we should make sure Smbios table,
75 // ACPI table and Mps tables kept in memory of specified type
77 ConvertSystemTable(gTableGuidArray
[Index
], (VOID
**)&Table
);
78 gBS
->InstallConfigurationTable (gTableGuidArray
[Index
], (VOID
*)Table
);
92 EFI_MEMORY_DESCRIPTOR
*MemMap
;
93 EFI_MEMORY_DESCRIPTOR
*MemMapPtr
;
95 UINTN MapKey
, DescriptorSize
;
97 UINT32 DescriptorVersion
;
103 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
104 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
105 MemMapSize
+= EFI_PAGE_SIZE
;
106 Status
= gBS
->AllocatePool (EfiBootServicesData
, MemMapSize
, &MemMap
);
107 ASSERT (Status
== EFI_SUCCESS
);
108 Status
= gBS
->GetMemoryMap (&MemMapSize
, MemMap
, &MapKey
, &DescriptorSize
, &DescriptorVersion
);
109 ASSERT (Status
== EFI_SUCCESS
);
112 ASSERT (DescriptorVersion
== EFI_MEMORY_DESCRIPTOR_VERSION
);
114 for (Index
= 0; Index
< MemMapSize
/ DescriptorSize
; Index
++) {
115 Bytes
= LShiftU64 (MemMap
->NumberOfPages
, 12);
116 DEBUG ((EFI_D_ERROR
, "%lX-%lX %lX %lX %X\n",
117 MemMap
->PhysicalStart
,
118 MemMap
->PhysicalStart
+ Bytes
- 1,
119 MemMap
->NumberOfPages
,
121 (UINTN
)MemMap
->Type
));
122 MemMap
= (EFI_MEMORY_DESCRIPTOR
*)((UINTN
)MemMap
+ DescriptorSize
);
125 gBS
->FreePool (MemMapPtr
);
135 EFI_PEI_HOB_POINTERS GuidHob
;
137 MEMORY_DESC_HOB MemoryDescHob
;
139 EFI_PHYSICAL_ADDRESS Memory
;
140 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
142 GuidHob
.Raw
= GetFirstGuidHob (&gLdrMemoryDescriptorGuid
);
143 if (GuidHob
.Raw
== NULL
) {
144 DEBUG ((EFI_D_ERROR
, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
147 Table
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
149 DEBUG ((EFI_D_ERROR
, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
152 MemoryDescHob
.MemDescCount
= *(UINTN
*)Table
;
153 MemoryDescHob
.MemDesc
= *(EFI_MEMORY_DESCRIPTOR
**)((UINTN
)Table
+ sizeof(UINTN
));
156 // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
158 for (Index
= 0; Index
< MemoryDescHob
.MemDescCount
; Index
++) {
159 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
< 0x100000) {
162 if (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
>= 0x100000000ULL
) {
165 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiReservedMemoryType
) ||
166 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
167 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
) ||
168 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
169 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
170 DEBUG ((EFI_D_ERROR
, "PhysicalStart - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].PhysicalStart
));
171 DEBUG ((EFI_D_ERROR
, "PageNumber - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].NumberOfPages
));
172 DEBUG ((EFI_D_ERROR
, "Attribute - 0x%016lx, ", MemoryDescHob
.MemDesc
[Index
].Attribute
));
173 DEBUG ((EFI_D_ERROR
, "Type - 0x%08x\n", MemoryDescHob
.MemDesc
[Index
].Type
));
174 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) ||
175 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesCode
)) {
177 // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore.
178 // The memory type is assigned in EfiLdr
180 Status
= gDS
->GetMemorySpaceDescriptor (MemoryDescHob
.MemDesc
[Index
].PhysicalStart
, &Descriptor
);
181 if (EFI_ERROR (Status
)) {
184 if (Descriptor
.GcdMemoryType
!= EfiGcdMemoryTypeReserved
) {
186 // BFV or tested DXE core
191 // Untested DXE Core region, free and remove
193 Status
= gDS
->FreeMemorySpace (
194 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
195 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
)
197 if (EFI_ERROR (Status
)) {
198 DEBUG ((EFI_D_ERROR
, "FreeMemorySpace fail - %r!\n", Status
));
201 Status
= gDS
->RemoveMemorySpace (
202 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
203 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
)
205 if (EFI_ERROR (Status
)) {
206 DEBUG ((EFI_D_ERROR
, "RemoveMemorySpace fail - %r!\n", Status
));
211 // Convert Runtime type to BootTime type
213 if (MemoryDescHob
.MemDesc
[Index
].Type
== EfiRuntimeServicesData
) {
214 MemoryDescHob
.MemDesc
[Index
].Type
= EfiBootServicesData
;
216 MemoryDescHob
.MemDesc
[Index
].Type
= EfiBootServicesCode
;
220 // PassThrough, let below code add and alloate.
224 // ACPI or reserved memory
226 Status
= gDS
->AddMemorySpace (
227 EfiGcdMemoryTypeSystemMemory
,
228 MemoryDescHob
.MemDesc
[Index
].PhysicalStart
,
229 LShiftU64 (MemoryDescHob
.MemDesc
[Index
].NumberOfPages
, EFI_PAGE_SHIFT
),
230 MemoryDescHob
.MemDesc
[Index
].Attribute
232 if (EFI_ERROR (Status
)) {
233 DEBUG ((EFI_D_ERROR
, "AddMemorySpace fail - %r!\n", Status
));
234 if ((MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIReclaimMemory
) ||
235 (MemoryDescHob
.MemDesc
[Index
].Type
== EfiACPIMemoryNVS
)) {
237 // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
238 // For EfiReservedMemoryType, there maybe overlap. So skip check here.
240 // ASSERT_EFI_ERROR (Status);
245 Memory
= MemoryDescHob
.MemDesc
[Index
].PhysicalStart
;
246 Status
= gBS
->AllocatePages (
248 (EFI_MEMORY_TYPE
)MemoryDescHob
.MemDesc
[Index
].Type
,
249 (UINTN
)MemoryDescHob
.MemDesc
[Index
].NumberOfPages
,
252 if (EFI_ERROR (Status
)) {
253 DEBUG ((EFI_D_ERROR
, "AllocatePages fail - %r!\n", Status
));
255 // For the page added, it must be allocated.
257 // ASSERT_EFI_ERROR (Status);
266 DisableUsbLegacySupport(
272 Disabble the USB legacy Support in all Ehci and Uhci.
273 This function assume all PciIo handles have been created in system.
284 EFI_HANDLE
*HandleArray
;
285 UINTN HandleArrayCount
;
287 EFI_PCI_IO_PROTOCOL
*PciIo
;
296 // Find the usb host controller
298 Status
= gBS
->LocateHandleBuffer (
300 &gEfiPciIoProtocolGuid
,
305 if (!EFI_ERROR (Status
)) {
306 for (Index
= 0; Index
< HandleArrayCount
; Index
++) {
307 Status
= gBS
->HandleProtocol (
309 &gEfiPciIoProtocolGuid
,
312 if (!EFI_ERROR (Status
)) {
314 // Find the USB host controller controller
316 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x09, 3, &Class
);
317 if (!EFI_ERROR (Status
)) {
318 if ((PCI_CLASS_SERIAL
== Class
[2]) &&
319 (PCI_CLASS_SERIAL_USB
== Class
[1])) {
320 if (PCI_IF_UHCI
== Class
[0]) {
322 // Found the UHCI, then disable the legacy support
325 Status
= PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0xC0, 1, &Command
);
326 } else if (PCI_IF_EHCI
== Class
[0]) {
328 // Found the EHCI, then disable the legacy support
330 Status
= PciIo
->Mem
.Read (
334 (UINT64
) 0x08, //EHC_HCCPARAMS_OFFSET
339 ExtendCap
= (HcCapParams
>> 8) & 0xFF;
341 // Disable the SMI in USBLEGCTLSTS firstly
343 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
345 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
+ 0x4, 1, &Value
);
348 // Get EHCI Ownership from legacy bios
350 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
351 Value
|= (0x1 << 24);
352 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
358 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, ExtendCap
, 1, &Value
);
360 if ((Value
& 0x01010000) == 0x01000000) {
372 gBS
->FreePool (HandleArray
);
386 Platform Bds init. Incude the platform firmware vendor, revision
397 GetSystemTablesFromHob ();
402 // Append Usb Keyboard short form DevicePath into "ConInDev"
404 BdsLibUpdateConsoleVariable (
406 (EFI_DEVICE_PATH_PROTOCOL
*) &gUsbClassKeyboardDevicePath
,
412 GetPciExpressBaseAddressForRootBridge (
413 IN UINTN HostBridgeNumber
,
414 IN UINTN RootBridgeNumber
419 This routine is to get PciExpress Base Address for this RootBridge
422 HostBridgeNumber - The number of HostBridge
423 RootBridgeNumber - The number of RootBridge
426 UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
430 EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
*PciExpressBaseAddressInfo
;
434 EFI_PEI_HOB_POINTERS GuidHob
;
437 // Get PciExpressAddressInfo Hob
439 PciExpressBaseAddressInfo
= NULL
;
441 GuidHob
.Raw
= GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid
);
442 if (GuidHob
.Raw
!= NULL
) {
443 PciExpressBaseAddressInfo
= GET_GUID_HOB_DATA (GuidHob
.Guid
);
444 BufferSize
= GET_GUID_HOB_DATA_SIZE (GuidHob
.Guid
);
450 // Search the PciExpress Base Address in the Hob for current RootBridge
452 Number
= (UINT32
)(BufferSize
/ sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION
));
453 for (Index
= 0; Index
< Number
; Index
++) {
454 if ((PciExpressBaseAddressInfo
[Index
].HostBridgeNumber
== HostBridgeNumber
) &&
455 (PciExpressBaseAddressInfo
[Index
].RootBridgeNumber
== RootBridgeNumber
)) {
456 return PciExpressBaseAddressInfo
[Index
].PciExpressBaseAddress
;
461 // Do not find the PciExpress Base Address in the Hob
467 PatchPciRootBridgeDevicePath (
468 IN UINTN HostBridgeNumber
,
469 IN UINTN RootBridgeNumber
,
470 IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH
*RootBridge
473 UINT64 PciExpressBase
;
475 PciExpressBase
= GetPciExpressBaseAddressForRootBridge (HostBridgeNumber
, RootBridgeNumber
);
477 DEBUG ((EFI_D_INFO
, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase
));
479 if (PciExpressBase
!= 0) {
480 RootBridge
->PciRootBridge
.HID
= EISA_PNP_ID(0x0A08);
500 EFI_SUCCESS - Connect RootBridge successfully.
501 EFI_STATUS - Connect RootBridge fail.
506 EFI_HANDLE RootHandle
;
509 // Patch Pci Root Bridge Device Path
511 PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0
);
514 // Make all the PCI_IO protocols on PCI Seg 0 show up
516 BdsLibConnectDevicePath (gPlatformRootBridges
[0]);
518 Status
= gBS
->LocateDevicePath (
519 &gEfiDevicePathProtocolGuid
,
520 &gPlatformRootBridges
[0],
523 DEBUG ((EFI_D_INFO
, "Pci Root bridge handle is 0x%X\n", RootHandle
));
525 if (EFI_ERROR (Status
)) {
529 Status
= gBS
->ConnectController (RootHandle
, NULL
, NULL
, FALSE
);
530 if (EFI_ERROR (Status
)) {
538 PrepareLpcBridgeDevicePath (
539 IN EFI_HANDLE DeviceHandle
545 Add IsaKeyboard to ConIn,
546 add IsaSerial to ConOut, ConIn, ErrOut.
551 DeviceHandle - Handle of PCIIO protocol.
555 EFI_SUCCESS - LPC bridge is added to ConOut, ConIn, and ErrOut.
556 EFI_STATUS - No LPC bridge is added.
561 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
562 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
565 Status
= gBS
->HandleProtocol (
567 &gEfiDevicePathProtocolGuid
,
570 if (EFI_ERROR (Status
)) {
573 TempDevicePath
= DevicePath
;
578 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnpPs2KeyboardDeviceNode
);
580 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
585 DevicePath
= TempDevicePath
;
586 gPnp16550ComPortDeviceNode
.UID
= 0;
588 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
589 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
590 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
592 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
593 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
594 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
599 DevicePath
= TempDevicePath
;
600 gPnp16550ComPortDeviceNode
.UID
= 1;
602 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gPnp16550ComPortDeviceNode
);
603 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
604 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
606 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
607 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
608 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
615 IN EFI_DEVICE_PATH_PROTOCOL
*PciDevicePath
,
616 OUT EFI_DEVICE_PATH_PROTOCOL
**GopDevicePath
621 EFI_HANDLE PciDeviceHandle
;
622 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePath
;
623 EFI_DEVICE_PATH_PROTOCOL
*TempPciDevicePath
;
624 UINTN GopHandleCount
;
625 EFI_HANDLE
*GopHandleBuffer
;
627 if (PciDevicePath
== NULL
|| GopDevicePath
== NULL
) {
628 return EFI_INVALID_PARAMETER
;
632 // Initialize the GopDevicePath to be PciDevicePath
634 *GopDevicePath
= PciDevicePath
;
635 TempPciDevicePath
= PciDevicePath
;
637 Status
= gBS
->LocateDevicePath (
638 &gEfiDevicePathProtocolGuid
,
642 if (EFI_ERROR (Status
)) {
647 // Try to connect this handle, so that GOP dirver could start on this
648 // device and create child handles with GraphicsOutput Protocol installed
649 // on them, then we get device paths of these child handles and select
650 // them as possible console device.
652 gBS
->ConnectController (PciDeviceHandle
, NULL
, NULL
, FALSE
);
654 Status
= gBS
->LocateHandleBuffer (
656 &gEfiGraphicsOutputProtocolGuid
,
661 if (!EFI_ERROR (Status
)) {
663 // Add all the child handles as possible Console Device
665 for (Index
= 0; Index
< GopHandleCount
; Index
++) {
666 Status
= gBS
->HandleProtocol (GopHandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
*)&TempDevicePath
);
667 if (EFI_ERROR (Status
)) {
673 GetDevicePathSize (PciDevicePath
) - END_DEVICE_PATH_LENGTH
676 // In current implementation, we only enable one of the child handles
677 // as console device, i.e. sotre one of the child handle's device
678 // path to variable "ConOut"
679 // In futhure, we could select all child handles to be console device
682 *GopDevicePath
= TempDevicePath
;
685 // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
686 // Add the integrity GOP device path.
688 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, NULL
, PciDevicePath
);
689 BdsLibUpdateConsoleVariable (VarConsoleOutDev
, TempDevicePath
, NULL
);
692 gBS
->FreePool (GopHandleBuffer
);
699 PreparePciVgaDevicePath (
700 IN EFI_HANDLE DeviceHandle
706 Add PCI VGA to ConOut.
711 DeviceHandle - Handle of PCIIO protocol.
715 EFI_SUCCESS - PCI VGA is added to ConOut.
716 EFI_STATUS - No PCI VGA device is added.
721 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
722 EFI_DEVICE_PATH_PROTOCOL
*GopDevicePath
;
725 Status
= gBS
->HandleProtocol (
727 &gEfiDevicePathProtocolGuid
,
730 if (EFI_ERROR (Status
)) {
734 GetGopDevicePath (DevicePath
, &GopDevicePath
);
735 DevicePath
= GopDevicePath
;
737 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
743 PreparePciSerialDevicePath (
744 IN EFI_HANDLE DeviceHandle
750 Add PCI Serial to ConOut, ConIn, ErrOut.
755 DeviceHandle - Handle of PCIIO protocol.
759 EFI_SUCCESS - PCI Serial is added to ConOut, ConIn, and ErrOut.
760 EFI_STATUS - No PCI Serial device is added.
765 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
768 Status
= gBS
->HandleProtocol (
770 &gEfiDevicePathProtocolGuid
,
773 if (EFI_ERROR (Status
)) {
777 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gUartDeviceNode
);
778 DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&gTerminalTypeDeviceNode
);
780 BdsLibUpdateConsoleVariable (VarConsoleOut
, DevicePath
, NULL
);
781 BdsLibUpdateConsoleVariable (VarConsoleInp
, DevicePath
, NULL
);
782 BdsLibUpdateConsoleVariable (VarErrorOut
, DevicePath
, NULL
);
788 DetectAndPreparePlatformPciDevicePath (
789 BOOLEAN DetectVgaOnly
795 Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
799 DetectVgaOnly - Only detect VGA device if it's TRUE.
803 EFI_SUCCESS - PCI Device check and Console variable update successfully.
804 EFI_STATUS - PCI Device check or Console variable update fail.
810 EFI_HANDLE
*HandleBuffer
;
812 EFI_PCI_IO_PROTOCOL
*PciIo
;
816 // Start to check all the PciIo to find all possible device
820 Status
= gBS
->LocateHandleBuffer (
822 &gEfiPciIoProtocolGuid
,
827 if (EFI_ERROR (Status
)) {
831 for (Index
= 0; Index
< HandleCount
; Index
++) {
832 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiPciIoProtocolGuid
, (VOID
*)&PciIo
);
833 if (EFI_ERROR (Status
)) {
838 // Check for all PCI device
840 Status
= PciIo
->Pci
.Read (
844 sizeof (Pci
) / sizeof (UINT32
),
847 if (EFI_ERROR (Status
)) {
851 if (!DetectVgaOnly
) {
853 // Here we decide whether it is LPC Bridge
855 if ((IS_PCI_LPC (&Pci
)) ||
856 ((IS_PCI_ISA_PDECODE (&Pci
)) && (Pci
.Hdr
.VendorId
== 0x8086) && (Pci
.Hdr
.DeviceId
== 0x7110))) {
858 // Add IsaKeyboard to ConIn,
859 // add IsaSerial to ConOut, ConIn, ErrOut
861 DEBUG ((EFI_D_INFO
, "Find the LPC Bridge device\n"));
862 PrepareLpcBridgeDevicePath (HandleBuffer
[Index
]);
866 // Here we decide which Serial device to enable in PCI bus
868 if (IS_PCI_16550SERIAL (&Pci
)) {
870 // Add them to ConOut, ConIn, ErrOut.
872 DEBUG ((EFI_D_INFO
, "Find the 16550 SERIAL device\n"));
873 PreparePciSerialDevicePath (HandleBuffer
[Index
]);
879 // Here we decide which VGA device to enable in PCI bus
881 if (IS_PCI_VGA (&Pci
)) {
883 // Add them to ConOut.
885 DEBUG ((EFI_D_INFO
, "Find the VGA device\n"));
886 PreparePciVgaDevicePath (HandleBuffer
[Index
]);
891 gBS
->FreePool (HandleBuffer
);
897 PlatformBdsConnectConsole (
898 IN BDS_CONSOLE_CONNECT_ENTRY
*PlatformConsole
904 Connect the predefined platform default console device. Always try to find
905 and enable the vga device if have.
909 PlatformConsole - Predfined platform default console device array.
913 EFI_SUCCESS - Success connect at least one ConIn and ConOut
914 device, there must have one ConOut device is
917 EFI_STATUS - Return the status of
918 BdsLibConnectAllDefaultConsoles ()
924 EFI_DEVICE_PATH_PROTOCOL
*VarConout
;
925 EFI_DEVICE_PATH_PROTOCOL
*VarConin
;
926 UINTN DevicePathSize
;
929 // Connect RootBridge
931 ConnectRootBridge ();
933 VarConout
= BdsLibGetVariableAndSize (
935 &gEfiGlobalVariableGuid
,
938 VarConin
= BdsLibGetVariableAndSize (
940 &gEfiGlobalVariableGuid
,
944 if (VarConout
== NULL
|| VarConin
== NULL
) {
946 // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
948 DetectAndPreparePlatformPciDevicePath (FALSE
);
951 // Have chance to connect the platform default console,
952 // the platform default console is the minimue device group
953 // the platform should support
955 for (Index
= 0; PlatformConsole
[Index
].DevicePath
!= NULL
; ++Index
) {
957 // Update the console variable with the connect type
959 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_IN
) == CONSOLE_IN
) {
960 BdsLibUpdateConsoleVariable (VarConsoleInp
, PlatformConsole
[Index
].DevicePath
, NULL
);
962 if ((PlatformConsole
[Index
].ConnectType
& CONSOLE_OUT
) == CONSOLE_OUT
) {
963 BdsLibUpdateConsoleVariable (VarConsoleOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
965 if ((PlatformConsole
[Index
].ConnectType
& STD_ERROR
) == STD_ERROR
) {
966 BdsLibUpdateConsoleVariable (VarErrorOut
, PlatformConsole
[Index
].DevicePath
, NULL
);
971 // Only detect VGA device and add them to ConOut
973 DetectAndPreparePlatformPciDevicePath (TRUE
);
977 // The ConIn devices connection will start the USB bus, should disable all
978 // Usb legacy support firstly.
979 // Caution: Must ensure the PCI bus driver has been started. Since the
980 // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
982 Status
= DisableUsbLegacySupport();
985 // Connect the all the default console with current cosole variable
987 Status
= BdsLibConnectAllDefaultConsoles ();
988 if (EFI_ERROR (Status
)) {
996 PlatformBdsConnectSequence (
1001 Routine Description:
1003 Connect with predeined platform connect sequence,
1004 the OEM/IBV can customize with their own connect sequence.
1021 // Here we can get the customized platform connect sequence
1022 // Notes: we can connect with new variable which record the
1023 // last time boots connect device path sequence
1025 while (gPlatformConnectSequence
[Index
] != NULL
) {
1027 // Build the platform boot option
1029 BdsLibConnectDevicePath (gPlatformConnectSequence
[Index
]);
1036 PlatformBdsGetDriverOption (
1037 IN OUT LIST_ENTRY
*BdsDriverLists
1041 Routine Description:
1043 Load the predefined driver option, OEM/IBV can customize this
1044 to load their own drivers
1048 BdsDriverLists - The header of the driver option link list.
1061 // Here we can get the customized platform driver option
1063 while (gPlatformDriverOption
[Index
] != NULL
) {
1065 // Build the platform boot option
1067 BdsLibRegisterNewOption (BdsDriverLists
, gPlatformDriverOption
[Index
], NULL
, L
"DriverOrder");
1074 PlatformBdsDiagnostics (
1075 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel
,
1076 IN BOOLEAN QuietBoot
,
1077 IN BASEM_MEMORY_TEST BaseMemoryTest
1081 Routine Description:
1083 Perform the platform diagnostic, such like test memory. OEM/IBV also
1084 can customize this fuction to support specific platform diagnostic.
1088 MemoryTestLevel - The memory test intensive level
1090 QuietBoot - Indicate if need to enable the quiet boot
1092 BaseMemoryTest - A pointer to BdsMemoryTest()
1103 // Here we can decide if we need to show
1104 // the diagnostics screen
1105 // Notes: this quiet boot code should be remove
1106 // from the graphic lib
1109 Status
= EnableQuietBoot (PcdGetPtr(PcdLogoFile
));
1110 if (EFI_ERROR (Status
)) {
1111 DisableQuietBoot ();
1116 // Perform system diagnostic
1118 Status
= BaseMemoryTest (MemoryTestLevel
);
1119 if (EFI_ERROR (Status
)) {
1120 DisableQuietBoot ();
1126 // Perform system diagnostic
1128 Status
= BaseMemoryTest (MemoryTestLevel
);
1133 PlatformBdsPolicyBehavior (
1134 IN OUT LIST_ENTRY
*DriverOptionList
,
1135 IN OUT LIST_ENTRY
*BootOptionList
,
1136 IN PROCESS_CAPSULES ProcessCapsules
,
1137 IN BASEM_MEMORY_TEST BaseMemoryTest
1141 Routine Description:
1143 The function will excute with as the platform policy, current policy
1144 is driven by boot mode. IBV/OEM can customize this code for their specific
1149 DriverOptionList - The header of the driver option link list
1151 BootOptionList - The header of the boot option link list
1161 EFI_EVENT UserInputDurationTime
;
1164 EFI_BOOT_MODE BootMode
;
1167 // Init the time out value
1169 Timeout
= PcdGet16 (PcdPlatformBootTimeOut
);
1172 // Load the driver option as the driver option list
1174 PlatformBdsGetDriverOption (DriverOptionList
);
1177 // Get current Boot Mode
1179 Status
= BdsLibGetBootMode (&BootMode
);
1180 DEBUG ((EFI_D_ERROR
, "Boot Mode:%x\n", BootMode
));
1183 // Go the different platform policy with different boot mode
1184 // Notes: this part code can be change with the table policy
1186 ASSERT (BootMode
== BOOT_WITH_FULL_CONFIGURATION
);
1188 // Connect platform console
1190 Status
= PlatformBdsConnectConsole (gPlatformConsole
);
1191 if (EFI_ERROR (Status
)) {
1193 // Here OEM/IBV can customize with defined action
1195 PlatformBdsNoConsoleAction ();
1198 // Create a 300ms duration event to ensure user has enough input time to enter Setup
1200 Status
= gBS
->CreateEvent (
1205 &UserInputDurationTime
1207 ASSERT (Status
== EFI_SUCCESS
);
1208 Status
= gBS
->SetTimer (UserInputDurationTime
, TimerRelative
, 3000000);
1209 ASSERT (Status
== EFI_SUCCESS
);
1211 // Memory test and Logo show
1213 PlatformBdsDiagnostics (IGNORE
, TRUE
, BaseMemoryTest
);
1216 // Perform some platform specific connect sequence
1218 PlatformBdsConnectSequence ();
1221 // Give one chance to enter the setup if we
1222 // have the time out
1224 // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.
1227 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1231 //BdsLibConnectAll ();
1232 //BdsLibEnumerateAllBootOption (BootOptionList);
1235 // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
1236 // checking code in real production tip.
1238 // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
1239 // and do enumerate all the default boot options. But in development system board, the boot mode
1240 // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
1241 // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
1243 Status
= BdsLibBuildOptionFromVar (BootOptionList
, L
"BootOrder");
1244 if (EFI_ERROR(Status
)) {
1246 // If cannot find "BootOrder" variable, it may be first boot.
1247 // Try to connect all devices and enumerate all boot options here.
1249 BdsLibConnectAll ();
1250 BdsLibEnumerateAllBootOption (BootOptionList
);
1254 // To give the User a chance to enter Setup here, if user set TimeOut is 0.
1255 // BDS should still give user a chance to enter Setup
1256 // Check whether the user input after the duration time has expired
1258 gBS
->WaitForEvent (1, &UserInputDurationTime
, &Index
);
1259 gBS
->CloseEvent (UserInputDurationTime
);
1260 Status
= gST
->ConIn
->ReadKeyStroke (gST
->ConIn
, &Key
);
1262 if (!EFI_ERROR (Status
)) {
1264 // Enter Setup if user input
1267 PlatformBdsEnterFrontPage (Timeout
, FALSE
);
1276 PlatformBdsBootSuccess (
1277 IN BDS_COMMON_OPTION
*Option
1281 Routine Description:
1283 Hook point after a boot attempt succeeds. We don't expect a boot option to
1284 return, so the EFI 1.0 specification defines that you will default to an
1285 interactive mode and stop processing the BootOrder list in this case. This
1286 is alos a platform implementation and can be customized by IBV/OEM.
1290 Option - Pointer to Boot Option that succeeded to boot.
1301 // If Boot returned with EFI_SUCCESS and there is not in the boot device
1302 // select loop then we need to pop up a UI and wait for user input.
1304 TmpStr
= Option
->StatusString
;
1305 if (TmpStr
!= NULL
) {
1306 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1307 gBS
->FreePool (TmpStr
);
1313 PlatformBdsBootFail (
1314 IN BDS_COMMON_OPTION
*Option
,
1315 IN EFI_STATUS Status
,
1316 IN CHAR16
*ExitData
,
1317 IN UINTN ExitDataSize
1321 Routine Description:
1323 Hook point after a boot attempt fails.
1327 Option - Pointer to Boot Option that failed to boot.
1329 Status - Status returned from failed boot.
1331 ExitData - Exit data returned from failed boot.
1333 ExitDataSize - Exit data size returned from failed boot.
1344 // If Boot returned with failed status then we need to pop up a UI and wait
1347 TmpStr
= Option
->StatusString
;
1348 if (TmpStr
!= NULL
) {
1349 BdsLibOutputStrings (gST
->ConOut
, TmpStr
, Option
->Description
, L
"\n\r", NULL
);
1350 gBS
->FreePool (TmpStr
);
1356 PlatformBdsNoConsoleAction (
1361 Routine Description:
1363 This function is remained for IBV/OEM to do some platform action,
1364 if there no console device can be connected.
1372 EFI_SUCCESS - Direct return success now.
1380 ConvertSystemTable (
1381 IN EFI_GUID
*TableGuid
,
1386 Routine Description:
1387 Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
1389 As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
1390 So here we just check if the range is E/F seg,
1391 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1394 TableGuid - Guid of the table
1395 Table - pointer to the table
1398 EFI_SUCEESS - Convert Table successfully
1408 // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
1410 AcpiHeader
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1412 if (CompareGuid(TableGuid
, &gEfiAcpiTableGuid
) || CompareGuid(TableGuid
, &gEfiAcpi20TableGuid
)){
1413 if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
== 0x00){
1415 // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
1417 AcpiTableLen
= sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
);
1418 } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Reserved
>= 0x02){
1420 // If Acpi 2.0 or later, use RSDP Length fied.
1422 AcpiTableLen
= ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER
*)AcpiHeader
)->Length
;
1425 // Invalid Acpi Version, return
1427 return EFI_UNSUPPORTED
;
1429 Status
= ConvertAcpiTable (AcpiTableLen
, Table
);
1434 // If matches smbios guid, convert Smbios table.
1436 if (CompareGuid(TableGuid
, &gEfiSmbiosTableGuid
)){
1437 Status
= ConvertSmbiosTable (Table
);
1442 // If the table is MP table?
1444 if (CompareGuid(TableGuid
, &gEfiMpsTableGuid
)){
1445 Status
= ConvertMpsTable (Table
);
1449 return EFI_UNSUPPORTED
;
1460 Routine Description:
1461 Convert RSDP of ACPI Table if its location is lower than Address:0x100000
1463 As in legacy Bios, ACPI table is required to place in E/F Seg,
1464 So here we just check if the range is E/F seg,
1465 and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
1468 TableLen - Acpi RSDP length
1469 Table - pointer to the table
1472 EFI_SUCEESS - Convert Table successfully
1480 EFI_PHYSICAL_ADDRESS BufferPtr
;
1483 AcpiTableOri
= (VOID
*)(UINTN
)(*(UINT64
*)(*Table
));
1484 if (((UINTN
)AcpiTableOri
< 0x100000) && ((UINTN
)AcpiTableOri
> 0xE0000)) {
1485 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1486 Status
= gBS
->AllocatePages (
1489 EFI_SIZE_TO_PAGES(TableLen
),
1492 ASSERT_EFI_ERROR (Status
);
1493 AcpiTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1494 CopyMem (AcpiTableNew
, AcpiTableOri
, TableLen
);
1496 AcpiTableNew
= AcpiTableOri
;
1499 // Change configuration table Pointer
1501 *Table
= AcpiTableNew
;
1507 ConvertSmbiosTable (
1512 Routine Description:
1514 Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
1516 As in legacy Bios, Smbios table is required to place in E/F Seg,
1517 So here we just check if the range is F seg,
1518 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1520 Table - pointer to the table
1523 EFI_SUCEESS - Convert Table successfully
1528 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableNew
;
1529 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTableOri
;
1531 UINT32 SmbiosEntryLen
;
1533 EFI_PHYSICAL_ADDRESS BufferPtr
;
1535 SmbiosTableNew
= NULL
;
1536 SmbiosTableOri
= NULL
;
1539 // Get Smibos configuration Table
1541 SmbiosTableOri
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)(*(UINT64
*)(*Table
));
1543 if ((SmbiosTableOri
== NULL
) ||
1544 ((UINTN
)SmbiosTableOri
> 0x100000) ||
1545 ((UINTN
)SmbiosTableOri
< 0xF0000)){
1549 // Relocate the Smibos memory
1551 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1552 if (SmbiosTableOri
->SmbiosBcdRevision
!= 0x21) {
1553 SmbiosEntryLen
= SmbiosTableOri
->EntryPointLength
;
1556 // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
1558 SmbiosEntryLen
= 0x1F;
1560 BufferLen
= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
) + SmbiosTableOri
->TableLength
;
1561 Status
= gBS
->AllocatePages (
1564 EFI_SIZE_TO_PAGES(BufferLen
),
1567 ASSERT_EFI_ERROR (Status
);
1568 SmbiosTableNew
= (SMBIOS_TABLE_ENTRY_POINT
*)(UINTN
)BufferPtr
;
1575 // Get Smbios Structure table address, and make sure the start address is 32-bit align
1577 BufferPtr
+= SmbiosEntryLen
+ SYS_TABLE_PAD(SmbiosEntryLen
);
1579 (VOID
*)(UINTN
)BufferPtr
,
1580 (VOID
*)(UINTN
)(SmbiosTableOri
->TableAddress
),
1581 SmbiosTableOri
->TableLength
1583 SmbiosTableNew
->TableAddress
= (UINT32
)BufferPtr
;
1584 SmbiosTableNew
->IntermediateChecksum
= 0;
1585 SmbiosTableNew
->IntermediateChecksum
=
1586 CalculateCheckSum8 ((UINT8
*)SmbiosTableNew
+ 0x10, SmbiosEntryLen
-0x10);
1588 // Change the SMBIOS pointer
1590 *Table
= SmbiosTableNew
;
1601 Routine Description:
1603 Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
1605 As in legacy Bios, MP table is required to place in E/F Seg,
1606 So here we just check if the range is E/F seg,
1607 and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
1609 Table - pointer to the table
1612 EFI_SUCEESS - Convert Table successfully
1619 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerOri
;
1620 EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*MpsFloatingPointerNew
;
1621 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableOri
;
1622 EFI_LEGACY_MP_TABLE_HEADER
*MpsTableNew
;
1626 EFI_PHYSICAL_ADDRESS BufferPtr
;
1629 // Get MP configuration Table
1631 MpsFloatingPointerOri
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)(*(UINT64
*)(*Table
));
1632 if (!(((UINTN
)MpsFloatingPointerOri
<= 0x100000) &&
1633 ((UINTN
)MpsFloatingPointerOri
>= 0xF0000))){
1637 // Get Floating pointer structure length
1639 FPLength
= MpsFloatingPointerOri
->Length
* 16;
1640 Data32
= FPLength
+ SYS_TABLE_PAD (FPLength
);
1641 MpsTableOri
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)(MpsFloatingPointerOri
->PhysicalAddress
);
1642 if (MpsTableOri
!= NULL
) {
1643 Data32
+= MpsTableOri
->BaseTableLength
;
1644 Data32
+= MpsTableOri
->ExtendedTableLength
;
1645 if (MpsTableOri
->OemTablePointer
!= 0x00) {
1646 Data32
+= SYS_TABLE_PAD (Data32
);
1647 Data32
+= MpsTableOri
->OemTableSize
;
1655 BufferPtr
= EFI_SYSTEM_TABLE_MAX_ADDRESS
;
1656 Status
= gBS
->AllocatePages (
1659 EFI_SIZE_TO_PAGES(Data32
),
1662 ASSERT_EFI_ERROR (Status
);
1663 MpsFloatingPointerNew
= (EFI_LEGACY_MP_TABLE_FLOATING_POINTER
*)(UINTN
)BufferPtr
;
1664 CopyMem (MpsFloatingPointerNew
, MpsFloatingPointerOri
, FPLength
);
1666 // If Mp Table exists
1668 if (MpsTableOri
!= NULL
) {
1670 // Get Mps table length, including Ext table
1672 BufferPtr
= BufferPtr
+ FPLength
+ SYS_TABLE_PAD (FPLength
);
1673 MpsTableNew
= (EFI_LEGACY_MP_TABLE_HEADER
*)(UINTN
)BufferPtr
;
1674 CopyMem (MpsTableNew
, MpsTableOri
, MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
);
1676 if ((MpsTableOri
->OemTableSize
!= 0x0000) && (MpsTableOri
->OemTablePointer
!= 0x0000)){
1677 BufferPtr
+= MpsTableOri
->BaseTableLength
+ MpsTableOri
->ExtendedTableLength
;
1678 BufferPtr
+= SYS_TABLE_PAD (BufferPtr
);
1679 OemTableNew
= (VOID
*)(UINTN
)BufferPtr
;
1680 OemTableOri
= (VOID
*)(UINTN
)MpsTableOri
->OemTablePointer
;
1681 CopyMem (OemTableNew
, OemTableOri
, MpsTableOri
->OemTableSize
);
1682 MpsTableNew
->OemTablePointer
= (UINT32
)(UINTN
)OemTableNew
;
1684 MpsTableNew
->Checksum
= 0;
1685 MpsTableNew
->Checksum
= CalculateCheckSum8 ((UINT8
*)MpsTableNew
, MpsTableOri
->BaseTableLength
);
1686 MpsFloatingPointerNew
->PhysicalAddress
= (UINT32
)(UINTN
)MpsTableNew
;
1687 MpsFloatingPointerNew
->Checksum
= 0;
1688 MpsFloatingPointerNew
->Checksum
= CalculateCheckSum8 ((UINT8
*)MpsFloatingPointerNew
, FPLength
);
1691 // Change the pointer
1693 *Table
= MpsFloatingPointerNew
;
1699 Lock the ConsoleIn device in system table. All key
1700 presses will be ignored until the Password is typed in. The only way to
1701 disable the password is to type it in to a ConIn device.
1703 @param Password Password used to lock ConIn device.
1705 @retval EFI_SUCCESS lock the Console In Spliter virtual handle successfully.
1706 @retval EFI_UNSUPPORTED Password not found
1715 return EFI_UNSUPPORTED
;
1719 This function locks platform flash that is not allowed to be updated during normal boot path.
1720 The flash layout is platform specific.
1725 PlatformBdsLockNonUpdatableFlash (