/** @file Copyright (c) 2024, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define IGD_BUS_NUM 0x00 #define IGD_DEV_NUM 0x02 #define IGD_FUN_NUM 0x00 EDKII_PCI_DEVICE_PPI *mPciDevicePpi; BOOLEAN mResourceAssigned; CHAR8 *mMemoryAllocType[] = { "Reserved", "LoaderCode", "LoaderData", "boot-code", "boot-data", "runtime-code", "runtime-data", "ConventionalMemory", "UnusableMemory", "acpi", "acpi-nvs", "mmio", "MemoryMappedIOPortSpace", "PalCode", "PersistentMemory", }; /** The wrapper function of PeiServicesLocatePpi() for gEdkiiPeiPciDevicePpiGuid and Save the PPI to mPciDevicePpi. @retval EFI_SUCCESS If it locate gEdkiiPeiPciDevicePpiGuid successfully. @retval EFI_NOT_FOUND If it can't find gEdkiiPeiPciDevicePpiGuid. **/ EFI_STATUS EFIAPI LocatePciDevicePpi ( VOID ) { EFI_STATUS Status; EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; mPciDevicePpi = NULL; Status = PeiServicesLocatePpi ( &gEdkiiPeiPciDevicePpiGuid, 0, &PpiDescriptor, (void **)&mPciDevicePpi ); if (EFI_ERROR (Status) || (mPciDevicePpi == NULL)) { return EFI_NOT_FOUND; } return EFI_SUCCESS; } /** It will build FDT based on memory information from Hobs. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForMemory ( IN VOID *FdtBase ) { EFI_STATUS Status; EFI_PEI_HOB_POINTERS Hob; EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; VOID *HobStart; VOID *Fdt; INT32 TempNode; CHAR8 TempStr[32]; UINT64 RegTmp[2]; Fdt = FdtBase; HobStart = GetFirstHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR); // // Scan resource descriptor hobs to set memory nodes // for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { ResourceHob = Hob.ResourceDescriptor; // Memory if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) { // DEBUG ((DEBUG_ERROR, "Found hob for memory: base %016lX length %016lX\n", ResourceHob->PhysicalStart, ResourceHob->ResourceLength)); Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", ResourceHob->PhysicalStart); TempNode = FdtAddSubnode (Fdt, 0, TempStr); ASSERT (TempNode > 0); RegTmp[0] = CpuToFdt64 (ResourceHob->PhysicalStart); RegTmp[1] = CpuToFdt64 (ResourceHob->ResourceLength); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "device_type", "memory", (UINT32)(AsciiStrLen ("memory")+1)); ASSERT_EFI_ERROR (Status); } } } return Status; } /** It will build FDT based on memory allocation information from Hobs. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForMemAlloc ( IN VOID *FdtBase ) { EFI_STATUS Status; EFI_PEI_HOB_POINTERS Hob; VOID *HobStart; VOID *Fdt; INT32 ParentNode; INT32 TempNode; CHAR8 TempStr[32]; UINT64 RegTmp[2]; UINT32 AllocMemType; EFI_GUID *AllocMemName; UINT8 IsStackHob; UINT8 IsBspStore; UINT32 Data32; UNIVERSAL_PAYLOAD_SMBIOS_TABLE *SmbiosTable; UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable; EFI_HOB_GUID_TYPE *GuidHob; Fdt = FdtBase; ParentNode = FdtAddSubnode (Fdt, 0, "reserved-memory"); ASSERT (ParentNode > 0); Data32 = CpuToFdt32 (2); Status = FdtSetProperty (Fdt, ParentNode, "#address-cells", &Data32, sizeof (UINT32)); Status = FdtSetProperty (Fdt, ParentNode, "#size-cells", &Data32, sizeof (UINT32)); GuidHob = NULL; SmbiosTable = NULL; GuidHob = GetFirstGuidHob (&gUniversalPayloadSmbios3TableGuid); if (GuidHob != NULL) { SmbiosTable = GET_GUID_HOB_DATA (GuidHob); DEBUG ((DEBUG_INFO, "To build Smbios memory FDT ,SmbiosTable :%lx, SmBiosEntryPoint :%lx\n", (UINTN)SmbiosTable, SmbiosTable->SmBiosEntryPoint)); Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", SmbiosTable->SmBiosEntryPoint); DEBUG ((DEBUG_INFO, "To build Smbios memory FDT #2, SmbiosTable->Header.Length :%x\n", SmbiosTable->Header.Length)); TempNode = 0; TempNode = FdtAddSubnode (Fdt, ParentNode, TempStr); DEBUG ((DEBUG_INFO, "FdtAddSubnode %x", TempNode)); RegTmp[0] = CpuToFdt64 (SmbiosTable->SmBiosEntryPoint); RegTmp[1] = CpuToFdt64 (SmbiosTable->Header.Length); FdtSetProperty (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp)); ASSERT_EFI_ERROR (Status); FdtSetProperty (Fdt, TempNode, "compatible", "smbios", (UINT32)(AsciiStrLen ("smbios")+1)); ASSERT_EFI_ERROR (Status); } GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid); if (GuidHob != NULL) { AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob); } HobStart = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION); // // Scan memory allocation hobs to set memory type // for (Hob.Raw = HobStart; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) { if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { AllocMemName = NULL; IsStackHob = 0; IsBspStore = 0; if (CompareGuid (&(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid)) { continue; } else if (IsZeroGuid (&(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name)) == FALSE) { AllocMemName = &(Hob.MemoryAllocationModule->MemoryAllocationHeader.Name); if (CompareGuid (AllocMemName, &gEfiHobMemoryAllocStackGuid)) { IsStackHob = 1; } else if (CompareGuid (AllocMemName, &gEfiHobMemoryAllocBspStoreGuid)) { IsBspStore = 1; } } DEBUG (( DEBUG_ERROR, "Found hob for rsvd memory alloc: base %016lX length %016lX type %x\n", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, Hob.MemoryAllocation->AllocDescriptor.MemoryLength, Hob.MemoryAllocation->AllocDescriptor.MemoryType )); AllocMemType = Hob.MemoryAllocation->AllocDescriptor.MemoryType; if (IsStackHob == 1) { Status = AsciiSPrint ( TempStr, sizeof (TempStr), "%a@%lX", "stackhob", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress ); } else if (IsBspStore == 1) { Status = AsciiSPrint ( TempStr, sizeof (TempStr), "%a@%lX", "bspstore", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress ); } else { Status = AsciiSPrint ( TempStr, sizeof (TempStr), "%a@%lX", mMemoryAllocType[AllocMemType], Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress ); } if (AsciiStrCmp (mMemoryAllocType[AllocMemType], "ConventionalMemory") == 0) { continue; } if (AsciiStrCmp (mMemoryAllocType[AllocMemType], "mmio") == 0) { Status = AsciiSPrint (TempStr, sizeof (TempStr), "mmio@%lX", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress); } else { Status = AsciiSPrint (TempStr, sizeof (TempStr), "memory@%lX", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress); } TempNode = FdtAddSubnode (Fdt, ParentNode, TempStr); DEBUG ((DEBUG_INFO, "FdtAddSubnode %x", TempNode)); if (TempNode < 0) { continue; } RegTmp[0] = CpuToFdt64 (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress); RegTmp[1] = CpuToFdt64 (Hob.MemoryAllocation->AllocDescriptor.MemoryLength); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegTmp, sizeof (RegTmp)); ASSERT_EFI_ERROR (Status); if ((AsciiStrCmp (mMemoryAllocType[AllocMemType], "mmio") == 0)) { continue; } if (!(AsciiStrCmp (mMemoryAllocType[AllocMemType], "acpi-nvs") == 0) && (AsciiStrCmp (mMemoryAllocType[AllocMemType], "acpi") == 0)) { DEBUG ((DEBUG_INFO, "find acpi memory hob MemoryBaseAddress:%x , AcpiTable->Rsdp :%x\n", Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress, AcpiTable->Rsdp)); if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == AcpiTable->Rsdp) { DEBUG ((DEBUG_INFO, "keep acpi memory hob \n")); Status = FdtSetProperty (Fdt, TempNode, "compatible", mMemoryAllocType[AllocMemType], (UINT32)(AsciiStrLen (mMemoryAllocType[AllocMemType])+1)); ASSERT_EFI_ERROR (Status); } else { DEBUG ((DEBUG_INFO, "change acpi memory hob \n")); Status = FdtSetProperty (Fdt, TempNode, "compatible", mMemoryAllocType[4], (UINT32)(AsciiStrLen (mMemoryAllocType[4])+1)); ASSERT_EFI_ERROR (Status); } } else { DEBUG ((DEBUG_INFO, "other memory hob \n")); Status = FdtSetProperty (Fdt, TempNode, "compatible", mMemoryAllocType[AllocMemType], (UINT32)(AsciiStrLen (mMemoryAllocType[AllocMemType])+1)); ASSERT_EFI_ERROR (Status); } } } return Status; } /** It will build FDT based on serial information. @param[in] ISANode ISANode. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForSerial ( IN INT32 ISANode, IN VOID *FdtBase ) { EFI_STATUS Status; VOID *Fdt; INT32 TempNode; UINT64 RegisterBase; CHAR8 TempStr[32]; UINT32 RegData[3]; UINT32 Data32; UINT64 Data64; Fdt = FdtBase; RegisterBase = 0; // // Create SerialPortInfo FDT node. // Status = AsciiSPrint (TempStr, sizeof (TempStr), "serial@%lX", (RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase); TempNode = FdtAddSubnode (Fdt, ISANode, TempStr); ASSERT (TempNode > 0); Data32 = CpuToFdt32 (PcdGet32 (PcdSerialBaudRate)); Status = FdtSetProperty (Fdt, TempNode, "current-speed", &Data32, sizeof (Data32)); ASSERT_EFI_ERROR (Status); if (PcdGetBool (PcdSerialUseMmio)) { Data32 = 0; RegData[0] = CpuToFdt32 (Data32); } else { Data32 = 1; RegData[0] = CpuToFdt32 (Data32); } Data64 = (RegisterBase == 0) ? PcdGet64 (PcdSerialRegisterBase) : RegisterBase; Data32 = (UINT32)((Data64 & 0x0FFFFFFFF)); RegData[1] = CpuToFdt32 (Data32); RegData[2] = CpuToFdt32 (8); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegData, sizeof (RegData)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (1); Status = FdtSetProperty (Fdt, TempNode, "reg-io-width", &Data32, sizeof (Data32)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "compatible", "isa", (UINT32)(AsciiStrLen ("isa")+1)); ASSERT_EFI_ERROR (Status); return Status; } /** It will build FDT based on serial information. @param[in] ISANode ISANode. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForSerialLpss ( IN INT32 ISANode, IN VOID *FdtBase ) { EFI_HOB_GUID_TYPE *GuidHob; EFI_STATUS Status; UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *SerialPortInfo; VOID *Fdt; INT32 TempNode; UINT32 Data32; UINT32 RegData[2]; CHAR8 TempStr[32]; Status = EFI_SUCCESS; SerialPortInfo = NULL; Fdt = FdtBase; DEBUG ((DEBUG_INFO, "BuildFdtForSerialLpss start \n")); GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortInfoGuid); while (GuidHob != NULL) { SerialPortInfo = (UNIVERSAL_PAYLOAD_SERIAL_PORT_INFO *)GET_GUID_HOB_DATA (GuidHob); if (!SerialPortInfo->UseMmio) { GuidHob = GET_NEXT_HOB (GuidHob); GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); continue; } DEBUG ((DEBUG_INFO, "Create SerialPortInfo LPSS FDT node \n")); // // Create SerialPortInfo FDT node. // Status = AsciiSPrint (TempStr, sizeof (TempStr), "serial@%lX", SerialPortInfo->RegisterBase); TempNode = FdtAddSubnode (Fdt, ISANode, TempStr); ASSERT (TempNode > 0); Data32 = CpuToFdt32 (SerialPortInfo->BaudRate); Status = FdtSetProperty (Fdt, TempNode, "current-speed", &Data32, sizeof (Data32)); ASSERT_EFI_ERROR (Status); RegData[0] = CpuToFdt32 ((UINT32)SerialPortInfo->RegisterBase); RegData[1] = CpuToFdt32 (0x80); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegData, sizeof (RegData)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (4); Status = FdtSetProperty (Fdt, TempNode, "reg-io-width", &Data32, sizeof (Data32)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "compatible", "ns16550a", (UINT32)(AsciiStrLen ("ns16550a")+1)); ASSERT_EFI_ERROR (Status); GuidHob = GET_NEXT_HOB (GuidHob); GuidHob = GetNextGuidHob (&gUniversalPayloadSerialPortInfoGuid, GuidHob); } return Status; } /** It will build FDT based on BuildFdtForPciRootBridge information. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForPciRootBridge ( IN VOID *FdtBase ) { EFI_STATUS Status; VOID *Fdt; INT32 TempNode; INT32 GmaNode; INT32 eSPINode; CHAR8 TempStr[32]; CHAR8 GmaStr[32]; CHAR8 eSPIStr[32]; UINT32 RegTmp[2]; UINT32 RegData[21]; UINT32 DMARegData[8]; UINT64 Reg64Data[2]; UINT32 Data32; UINT64 Data64; UINT8 BusNumber; UINT8 BusLimit; UINT8 BusBase; UINT8 DevBase; UINT8 FunBase; EFI_HOB_GUID_TYPE *GuidHob; UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader; UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo; UINT8 Index; PCI_TYPE00 PciData; UNIVERSAL_PAYLOAD_SERIAL_PORT_PARENT_DEVICE_INFO *SerialParent; Fdt = FdtBase; BusNumber = 0; BusLimit = 0; BusBase = 0x80; DevBase = 0x31; FunBase = 0; Status = EFI_SUCCESS; PciRootBridgeInfo = NULL; DEBUG ((DEBUG_INFO, "%a: #1 \n", __func__)); // // Create BuildFdtForPciRootBridge FDT node. // GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid); if (GuidHob != NULL) { GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob); if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) { if ((GenericHeader->Revision == UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) && (GenericHeader->Length >= sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) { DEBUG ((DEBUG_INFO, "%a: #2 \n", __func__)); // // UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION // PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *)GET_GUID_HOB_DATA (GuidHob); } } } GuidHob = GetFirstGuidHob (&gUniversalPayloadSerialPortParentDeviceInfoGuid); if (GuidHob != NULL) { SerialParent = (UNIVERSAL_PAYLOAD_SERIAL_PORT_PARENT_DEVICE_INFO *)GET_GUID_HOB_DATA (GuidHob); BusBase = (SerialParent->ParentDevicePcieBaseAddress >> 20) & 0xFF; DevBase = (SerialParent->ParentDevicePcieBaseAddress >> 15) & 0x1F; FunBase = (SerialParent->ParentDevicePcieBaseAddress >> 12) & 0x07; } DEBUG ((DEBUG_INFO, "PciRootBridgeInfo->Count %x\n", PciRootBridgeInfo->Count)); DEBUG ((DEBUG_INFO, "PciRootBridge->Segment %x, \n", PciRootBridgeInfo->RootBridge[0].Segment)); DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, \n", PciRootBridgeInfo->RootBridge[0].Bus.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, \n", PciRootBridgeInfo->RootBridge[0].Bus.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", PciRootBridgeInfo->RootBridge[0].Mem.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", PciRootBridgeInfo->RootBridge[0].Mem.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", PciRootBridgeInfo->RootBridge[0].MemAbove4G.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", PciRootBridgeInfo->RootBridge[0].MemAbove4G.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.Base %llx, \n", PciRootBridgeInfo->RootBridge[0].PMem.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.limit %llx, \n", PciRootBridgeInfo->RootBridge[0].PMem.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.Base %x, \n", PciRootBridgeInfo->RootBridge[1].Bus.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->Bus.limit %x, \n", PciRootBridgeInfo->RootBridge[1].Bus.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base %x, \n", PciRootBridgeInfo->RootBridge[1].Mem.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.limit %x, \n", PciRootBridgeInfo->RootBridge[1].Mem.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base %llx, \n", PciRootBridgeInfo->RootBridge[1].MemAbove4G.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.limit %llx, \n", PciRootBridgeInfo->RootBridge[1].MemAbove4G.Limit)); DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.Base %x, \n", PciRootBridgeInfo->RootBridge[1].PMem.Base)); DEBUG ((DEBUG_INFO, "PciRootBridge->PMem.limit %x, \n", PciRootBridgeInfo->RootBridge[1].PMem.Limit)); if (PciRootBridgeInfo != NULL) { for (Index = 0; Index < PciRootBridgeInfo->Count; Index++) { UINTN PciExpressBaseAddress; mResourceAssigned = PciRootBridgeInfo->ResourceAssigned; PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress) + (PCI_LIB_ADDRESS (PciRootBridgeInfo->RootBridge[Index].Bus.Base, 0, 0, 0)); Status = AsciiSPrint (TempStr, sizeof (TempStr), "pci-rb%d@%lX", Index, PciExpressBaseAddress); TempNode = FdtAddSubnode (Fdt, 0, TempStr); ASSERT (TempNode > 0); SetMem (RegData, sizeof (RegData), 0); // non-reloc/non-prefetch/mmio, child-addr, parent-addr, length Data32 = (N_NON_RELOCATABLE + SS_32BIT_MEMORY_SPACE); RegData[0] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[0] %x, \n", Data32)); // child-addr RegData[1] = CpuToFdt32 (0); Data32 = (UINT32)PciRootBridgeInfo->RootBridge[Index].Mem.Base; RegData[2] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[2] %x, \n", Data32)); // parent-addr RegData[3] = CpuToFdt32 (0); RegData[4] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.Base RegData[4] %x, \n", Data32)); // size Data64 = (PciRootBridgeInfo->RootBridge[Index].Mem.Limit - PciRootBridgeInfo->RootBridge[Index].Mem.Base + 1); if (Data64 & 0xFFFFFFFF00000000) { Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 31); } else { Data32 = 0; } DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.size RegData[5] %x, \n", Data32)); RegData[5] = CpuToFdt32 (Data32); Data32 = (UINT32)((Data64 & 0x0FFFFFFFF)); DEBUG ((DEBUG_INFO, "PciRootBridge->Mem.size RegData[6] %x, \n", Data32)); RegData[6] = CpuToFdt32 (Data32); // non-reloc/non-prefetch/64 mmio, child-addr, parent-addr, length Data32 = (N_NON_RELOCATABLE + SS_64BIT_MEMORY_SPACE); RegData[7] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[7] %x, \n", Data32)); // child-addr Data64 = PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Base; Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32); RegData[8] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[8] %x, \n", Data32)); Data32 = (UINT32)((Data64 & 0x0FFFFFFFF)); RegData[9] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.Base RegData[9] %x, \n", Data32)); // parent-addr RegData[10] = RegData[8]; RegData[11] = RegData[9]; // size Data64 = (PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Limit - PciRootBridgeInfo->RootBridge[Index].MemAbove4G.Base + 1); if (Data64 & 0xFFFFFFFF00000000) { Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32); } else { Data32 = 0; } RegData[12] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.size RegData[12] %x, \n", Data32)); Data32 = (UINT32)((Data64 & 0x0FFFFFFFF)); RegData[13] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->MemAbove4G.size RegData[13] %x, \n", Data32)); // non-reloc/32bit/io, child-addr, parent-addr, length Data32 = (N_NON_RELOCATABLE + SS_IO_SPACE); RegData[14] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base RegData[14] %x, \n", Data32)); Data32 = (UINT32)PciRootBridgeInfo->RootBridge[Index].Io.Base; // child-addr RegData[15] = CpuToFdt32 (0); RegData[16] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base RegData[16] %x, \n", Data32)); // parent-addr RegData[17] = CpuToFdt32 (0); RegData[18] = CpuToFdt32 (Data32); // size Data64 = (PciRootBridgeInfo->RootBridge[Index].Io.Limit - PciRootBridgeInfo->RootBridge[Index].Io.Base + 1); if (Data64 & 0xFFFFFFFF00000000) { Data32 = (UINT32)RShiftU64 ((Data64 & 0xFFFFFFFF00000000), 32); } else { Data32 = 0; } RegData[19] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base size [19] %x, \n", Data32)); Data32 = (UINT32)((Data64 & 0x0FFFFFFFF)); RegData[20] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->Io.base size [20] %x, \n", Data32)); Status = FdtSetProperty (Fdt, TempNode, "ranges", &RegData, sizeof (RegData)); ASSERT_EFI_ERROR (Status); // non-reloc/non-prefetch/memory, child-addr, parent-addr, length // indicate rb1 does not support above 4GB DMA Data32 = (N_NON_RELOCATABLE + SS_32BIT_MEMORY_SPACE); DMARegData[0] = CpuToFdt32 (Data32); DEBUG ((DEBUG_INFO, "PciRootBridge->DMA base RegData[0] %x, \n", Data32)); // child-addr DMARegData[2] = CpuToFdt32 (0); DMARegData[3] = CpuToFdt32 (0); // parent-addr DMARegData[4] = CpuToFdt32 (0); DMARegData[5] = CpuToFdt32 (0); // size DMARegData[6] = CpuToFdt32 (1); DMARegData[7] = CpuToFdt32 (0); Status = FdtSetProperty (Fdt, TempNode, "dma-ranges", &DMARegData, sizeof (DMARegData)); ASSERT_EFI_ERROR (Status); ASSERT (PciRootBridgeInfo->RootBridge[Index].Bus.Base <= 0xFF); ASSERT (PciRootBridgeInfo->RootBridge[Index].Bus.Limit <= 0xFF); Reg64Data[0] = CpuToFdt64 (PciExpressBaseAddress + LShiftU64 (PciRootBridgeInfo->RootBridge[Index].Bus.Base, 20)); Reg64Data[1] = CpuToFdt64 (LShiftU64 (PciRootBridgeInfo->RootBridge[Index].Bus.Limit +1, 20)); Status = FdtSetProperty (Fdt, TempNode, "reg", &Reg64Data, sizeof (Reg64Data)); ASSERT_EFI_ERROR (Status); BusNumber = PciRootBridgeInfo->RootBridge[Index].Bus.Base & 0xFF; RegTmp[0] = CpuToFdt32 (BusNumber); BusLimit = PciRootBridgeInfo->RootBridge[Index].Bus.Limit & 0xFF; RegTmp[1] = CpuToFdt32 (BusLimit); DEBUG ((DEBUG_INFO, "PciRootBridge->BusNumber %x, \n", BusNumber)); DEBUG ((DEBUG_INFO, "PciRootBridge->BusLimit %x, \n", BusLimit)); Status = FdtSetProperty (Fdt, TempNode, "bus-range", &RegTmp, sizeof (RegTmp)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (2); Status = FdtSetProperty (Fdt, TempNode, "#size-cells", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (3); Status = FdtSetProperty (Fdt, TempNode, "#address-cells", &Data32, sizeof (UINT32)); Status = FdtSetProperty (Fdt, TempNode, "compatible", "pci-rb", (UINT32)(AsciiStrLen ("pci-rb")+1)); ASSERT_EFI_ERROR (Status); if (Index == 0) { PciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress) + (PCI_LIB_ADDRESS (IGD_BUS_NUM, IGD_DEV_NUM, IGD_FUN_NUM, 0)); Status = AsciiSPrint (GmaStr, sizeof (GmaStr), "gma@%lX", PciExpressBaseAddress); GmaNode = FdtAddSubnode (Fdt, TempNode, GmaStr); Status = LocatePciDevicePpi (); if (!EFI_ERROR (Status)) { Status = mPciDevicePpi->PciIo.Pci.Read ( &mPciDevicePpi->PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16, PCI_VENDOR_ID_OFFSET, sizeof (PciData.Hdr.VendorId), &(PciData.Hdr.VendorId) ); Status = mPciDevicePpi->PciIo.Pci.Read ( &mPciDevicePpi->PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16, PCI_DEVICE_ID_OFFSET, sizeof (PciData.Hdr.DeviceId), &(PciData.Hdr.DeviceId) ); Status = mPciDevicePpi->PciIo.Pci.Read ( &mPciDevicePpi->PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint8, PCI_REVISION_ID_OFFSET, sizeof (PciData.Hdr.RevisionID), &(PciData.Hdr.RevisionID) ); Status = mPciDevicePpi->PciIo.Pci.Read ( &mPciDevicePpi->PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16, PCI_SVID_OFFSET, sizeof (PciData.Device.SubsystemVendorID), &(PciData.Device.SubsystemVendorID) ); Status = mPciDevicePpi->PciIo.Pci.Read ( &mPciDevicePpi->PciIo, (EFI_PCI_IO_PROTOCOL_WIDTH)EfiPciWidthUint16, PCI_SID_OFFSET, sizeof (PciData.Device.SubsystemID), &(PciData.Device.SubsystemID) ); } Data32 = CpuToFdt32 (PciData.Device.SubsystemID); Status = FdtSetProperty (Fdt, GmaNode, "subsystem-id", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (PciData.Device.SubsystemVendorID); Status = FdtSetProperty (Fdt, GmaNode, "subsystem-vendor-id", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (PciData.Hdr.RevisionID); Status = FdtSetProperty (Fdt, GmaNode, "revision-id", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (PciData.Hdr.DeviceId); Status = FdtSetProperty (Fdt, GmaNode, "device-id", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (PciData.Hdr.VendorId); Status = FdtSetProperty (Fdt, GmaNode, "vendor-id", &Data32, sizeof (UINT32)); } if (SerialParent != NULL) { DEBUG ((DEBUG_INFO, "SerialParent->IsIsaCompatible :%x , SerialParent->ParentDevicePcieBaseAddress :%x\n", SerialParent->IsIsaCompatible, SerialParent->ParentDevicePcieBaseAddress)); DEBUG ((DEBUG_INFO, "BusBase :%x , PciRootBridgeInfo->RootBridge[Index].Bus.Base :%x\n", BusBase, PciRootBridgeInfo->RootBridge[Index].Bus.Base)); } { if ((BusBase >= PciRootBridgeInfo->RootBridge[Index].Bus.Base) && (BusBase <= PciRootBridgeInfo->RootBridge[Index].Bus.Limit)) { eSPINode = TempNode; if (SerialParent != NULL) { if (SerialParent->IsIsaCompatible) { Status = AsciiSPrint (eSPIStr, sizeof (eSPIStr), "isa@%X,%X", DevBase, FunBase); eSPINode = FdtAddSubnode (Fdt, TempNode, eSPIStr); Status = FdtSetProperty (Fdt, eSPINode, "compatible", "isa", (UINT32)(AsciiStrLen ("isa")+1)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (1); Status = FdtSetProperty (Fdt, eSPINode, "#size-cells", &Data32, sizeof (UINT32)); Data32 = CpuToFdt32 (2); Status = FdtSetProperty (Fdt, eSPINode, "#address-cells", &Data32, sizeof (UINT32)); Status = BuildFdtForSerial (eSPINode, FdtBase); ASSERT_EFI_ERROR (Status); } } else { Status = BuildFdtForSerialLpss (eSPINode, FdtBase); ASSERT_EFI_ERROR (Status); } } } } } DEBUG ((DEBUG_INFO, "%a: #3 \n", __func__)); return Status; } /** It will build FDT based on FrameBuffer. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForFrameBuffer ( IN VOID *FdtBase ) { EFI_STATUS Status; VOID *Fdt; INT32 TempNode; UINT32 Data32; CHAR8 TempStr[32]; UINT64 RegData[2]; EFI_HOB_GUID_TYPE *GuidHob; EFI_PEI_GRAPHICS_INFO_HOB *GraphicsInfo; Fdt = FdtBase; GuidHob = GetFirstGuidHob (&gEfiGraphicsInfoHobGuid); if (GuidHob != NULL) { GraphicsInfo = (EFI_PEI_GRAPHICS_INFO_HOB *)(GET_GUID_HOB_DATA (GuidHob)); Status = AsciiSPrint (TempStr, sizeof (TempStr), "framebuffer@%lX", GraphicsInfo->FrameBufferBase); TempNode = FdtAddSubnode (Fdt, 0, TempStr); ASSERT (TempNode > 0); Status = FdtSetProperty (Fdt, TempNode, "display", "&gma", (UINT32)(AsciiStrLen ("&gma")+1)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "format", "a8r8g8b8", (UINT32)(AsciiStrLen ("a8r8g8b8")+1)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (GraphicsInfo->GraphicsMode.VerticalResolution); Status = FdtSetProperty (Fdt, TempNode, "height", &Data32, sizeof (UINT32)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (GraphicsInfo->GraphicsMode.HorizontalResolution); Status = FdtSetProperty (Fdt, TempNode, "width", &Data32, sizeof (UINT32)); ASSERT_EFI_ERROR (Status); RegData[0] = CpuToFdt64 (GraphicsInfo->FrameBufferBase); RegData[1] = CpuToFdt64 (GraphicsInfo->FrameBufferSize); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegData, sizeof (RegData)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "compatible", "simple-framebuffer", (UINT32)(AsciiStrLen ("simple-framebuffer")+1)); ASSERT_EFI_ERROR (Status); } else { Status = AsciiSPrint (TempStr, sizeof (TempStr), "framebuffer@%lX", 0xB0000000); TempNode = FdtAddSubnode (Fdt, 0, TempStr); ASSERT (TempNode > 0); Status = FdtSetProperty (Fdt, TempNode, "display", "&gma", (UINT32)(AsciiStrLen ("&gma")+1)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "format", "a8r8g8b8", (UINT32)(AsciiStrLen ("a8r8g8b8")+1)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (1024); Status = FdtSetProperty (Fdt, TempNode, "height", &Data32, sizeof (UINT32)); ASSERT_EFI_ERROR (Status); Data32 = CpuToFdt32 (1280); Status = FdtSetProperty (Fdt, TempNode, "width", &Data32, sizeof (UINT32)); ASSERT_EFI_ERROR (Status); RegData[0] = CpuToFdt64 (0xB0000000); RegData[1] = CpuToFdt64 (0x500000); Status = FdtSetProperty (Fdt, TempNode, "reg", &RegData, sizeof (RegData)); ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, TempNode, "compatible", "simple-framebuffer", (UINT32)(AsciiStrLen ("simple-framebuffer")+1)); ASSERT_EFI_ERROR (Status); } return Status; } /** It will build FDT for UPL required data. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForUplRequired ( IN VOID *FdtBase ) { EFI_STATUS Status; VOID *Fdt; VOID *Fit; INT32 ParentNode; INT32 CustomNode; INT32 UPLParaNode; INT32 UPLImageNode; EFI_HOB_CPU *CpuHob; UINT64 Data64; UINT32 Data32; VOID *HobPtr; EFI_BOOT_MODE BootMode; CHAR8 TempStr[32]; UINT8 *GuidHob; UNIVERSAL_PAYLOAD_BASE *PayloadBase; Fdt = FdtBase; Fit = NULL; // // Create Hob list FDT node. // ParentNode = FdtAddSubnode (Fdt, 0, "options"); ASSERT (ParentNode > 0); UPLParaNode = FdtAddSubnode (Fdt, ParentNode, "upl-params"); ASSERT (UPLParaNode > 0); // // Create CPU info FDT node // CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU); ASSERT (CpuHob != NULL); if (mResourceAssigned) { Status = FdtSetProperty (Fdt, UPLParaNode, "pci-enum-done", NULL, 0); ASSERT_EFI_ERROR (Status); } BootMode = GetBootModeHob (); Data32 = CpuToFdt32 ((UINT32)CpuHob->SizeOfMemorySpace); Status = FdtSetProperty (Fdt, UPLParaNode, "addr-width", &Data32, sizeof (Data32)); ASSERT_EFI_ERROR (Status); if (BootMode == BOOT_WITH_FULL_CONFIGURATION) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "normal", (UINT32)(AsciiStrLen ("normal")+1)); } else if (BootMode == BOOT_WITH_MINIMAL_CONFIGURATION) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "fast", (UINT32)(AsciiStrLen ("fast")+1)); } else if (BootMode == BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "full", (UINT32)(AsciiStrLen ("full")+1)); } else if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "default", (UINT32)(AsciiStrLen ("default")+1)); } else if (BootMode == BOOT_ON_S4_RESUME) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "s4", (UINT32)(AsciiStrLen ("s4")+1)); } else if (BootMode == BOOT_ON_S3_RESUME) { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "s3", (UINT32)(AsciiStrLen ("s3")+1)); } else { Status = FdtSetProperty (Fdt, UPLParaNode, "boot-mode", "na", (UINT32)(AsciiStrLen ("na")+1)); } ASSERT_EFI_ERROR (Status); Status = FdtSetProperty (Fdt, UPLParaNode, "compatible", "upl", (UINT32)(AsciiStrLen ("upl")+1)); ASSERT_EFI_ERROR (Status); GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid); if (GuidHob != NULL) { PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob); Fit = (VOID *)(UINTN)PayloadBase->Entry; DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry)); Status = AsciiSPrint (TempStr, sizeof (TempStr), "upl-images@%lX", (UINTN)(Fit)); UPLImageNode = FdtAddSubnode (Fdt, ParentNode, TempStr); Data64 = CpuToFdt64 ((UINTN)Fit); Status = FdtSetProperty (FdtBase, UPLImageNode, "addr", &Data64, sizeof (Data64)); } CustomNode = FdtAddSubnode (Fdt, ParentNode, "upl-custom"); ASSERT (CustomNode > 0); HobPtr = GetHobList (); Data64 = CpuToFdt64 ((UINT64)(EFI_PHYSICAL_ADDRESS)HobPtr); Status = FdtSetProperty (Fdt, CustomNode, "hoblistptr", &Data64, sizeof (Data64)); ASSERT_EFI_ERROR (Status); return Status; } /** It will build FDT for UPL consumed. @param[in] FdtBase Address of the Fdt data. @retval EFI_SUCCESS If it completed successfully. @retval Others If it failed to build required FDT. **/ EFI_STATUS BuildFdtForUPL ( IN VOID *FdtBase ) { EFI_STATUS Status; // // Build FDT for memory related // Status = BuildFdtForMemory (FdtBase); ASSERT_EFI_ERROR (Status); Status = BuildFdtForMemAlloc (FdtBase); ASSERT_EFI_ERROR (Status); Status = BuildFdtForPciRootBridge (FdtBase); ASSERT_EFI_ERROR (Status); Status = BuildFdtForFrameBuffer (FdtBase); ASSERT_EFI_ERROR (Status); Status = BuildFdtForUplRequired (FdtBase); ASSERT_EFI_ERROR (Status); return Status; }