STATIC EFI_STATUS PrepareFdt ( IN OUT VOID *Fdt, IN UINTN FdtSize ) { EFI_STATUS Status; INT32 Node; INT32 CpuNode; UINTN Index; ARM_CORE_INFO *ArmCoreInfoTable; UINTN ArmCoreCount; INT32 MapNode; INT32 ClusterNode; INT32 PmuNode; PMU_INTERRUPT PmuInt; INT32 Phandle[NUM_CORES]; UINT32 ClusterIndex; UINT32 CoreIndex; UINT32 ClusterCount; UINT32 CoresInCluster; UINT32 ClusterId; UINTN MpId; CHAR8 Name[10]; AMD_MP_CORE_INFO_PROTOCOL *AmdMpCoreInfoProtocol; // // Setup Arm Mpcore Info if it is a multi-core or multi-cluster platforms. // // For 'cpus' and 'cpu' device tree nodes bindings, refer to this file // in the kernel documentation: // Documentation/devicetree/bindings/arm/cpus.txt // Status = gBS->LocateProtocol ( &gAmdMpCoreInfoProtocolGuid, NULL, (VOID **)&AmdMpCoreInfoProtocol ); ASSERT_EFI_ERROR (Status); // Get pointer to ARM core info table ArmCoreInfoTable = AmdMpCoreInfoProtocol->GetArmCoreInfoTable (&ArmCoreCount); ASSERT (ArmCoreInfoTable != NULL); ASSERT (ArmCoreCount <= NUM_CORES); // Get Id from primary CPU MpId = (UINTN)ArmReadMpidr (); // Create /pmu node PmuNode = fdt_add_subnode(Fdt, 0, "pmu"); if (PmuNode >= 0) { fdt_setprop_string (Fdt, PmuNode, "compatible", "arm,armv8-pmuv3"); // append PMU interrupts for (Index = 0; Index < ArmCoreCount; Index++) { MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, ArmCoreInfoTable[Index].CoreId); Status = AmdMpCoreInfoProtocol->GetPmuSpiFromMpId (MpId, &PmuInt.IntId); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "FDT: Error getting PMU interrupt for MpId '0x%x'\n", MpId)); return Status; } PmuInt.Flag = cpu_to_fdt32 (PMU_INT_FLAG_SPI); PmuInt.IntId = cpu_to_fdt32 (PmuInt.IntId); PmuInt.Type = cpu_to_fdt32 (PMU_INT_TYPE_HIGH_LEVEL); fdt_appendprop (Fdt, PmuNode, "interrupts", &PmuInt, sizeof(PmuInt)); } } else { DEBUG ((DEBUG_ERROR, "FDT: Error creating 'pmu' node\n")); return EFI_INVALID_PARAMETER; } // Create /cpus noide Node = fdt_add_subnode (Fdt, 0, "cpus"); if (Node >= 0) { // Configure the 'cpus' node fdt_setprop_string (Fdt, Node, "name", "cpus"); fdt_setprop_cell (Fdt, Node, "#address-cells", sizeof (UINTN) / 4); fdt_setprop_cell (Fdt, Node, "#size-cells", 0); } else { DEBUG ((DEBUG_ERROR, "FDT: Error creating 'cpus' node\n")); return EFI_INVALID_PARAMETER; } // // Walk the processor table in reverse order for proper listing in FDT // Index = ArmCoreCount; while (Index--) { // Create 'cpu' node AsciiSPrint (Name, sizeof (Name), "CPU%d", Index); CpuNode = fdt_add_subnode (Fdt, Node, Name); if (CpuNode < 0) { DEBUG ((DEBUG_ERROR, "FDT: Error on creating '%a' node\n", Name)); return EFI_INVALID_PARAMETER; } Phandle[Index] = fdt_alloc_phandle (Fdt); fdt_setprop_cell (Fdt, CpuNode, "phandle", Phandle[Index]); fdt_setprop_cell (Fdt, CpuNode, "linux,phandle", Phandle[Index]); fdt_setprop_string (Fdt, CpuNode, "enable-method", "psci"); MpId = (UINTN)GET_MPID (ArmCoreInfoTable[Index].ClusterId, ArmCoreInfoTable[Index].CoreId); MpId = cpu_to_fdt64 (MpId); fdt_setprop (Fdt, CpuNode, "reg", &MpId, sizeof (MpId)); fdt_setprop_string (Fdt, CpuNode, "compatible", "arm,armv8"); fdt_setprop_string (Fdt, CpuNode, "device_type", "cpu"); } // Create /cpu-map node MapNode = fdt_add_subnode (Fdt, Node, "cpu-map"); if (MapNode >= 0) { ClusterIndex = ArmCoreCount - 1; ClusterCount = NumberOfClustersInTable (ArmCoreInfoTable, ArmCoreCount); while (ClusterCount--) { // Create 'cluster' node AsciiSPrint (Name, sizeof (Name), "cluster%d", ClusterCount); ClusterNode = fdt_add_subnode (Fdt, MapNode, Name); if (ClusterNode < 0) { DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); return EFI_INVALID_PARAMETER; } ClusterId = ArmCoreInfoTable[ClusterIndex].ClusterId; CoreIndex = ClusterIndex; CoresInCluster = NumberOfCoresInCluster (ArmCoreInfoTable, ArmCoreCount, ClusterId); while (CoresInCluster--) { // Create 'core' node AsciiSPrint (Name, sizeof (Name), "core%d", CoresInCluster); CpuNode = fdt_add_subnode (Fdt, ClusterNode, Name); if (CpuNode < 0) { DEBUG ((DEBUG_ERROR, "FDT: Error creating '%a' node\n", Name)); return EFI_INVALID_PARAMETER; } fdt_setprop_cell (Fdt, CpuNode, "cpu", Phandle[CoreIndex]); // iterate to next core in cluster if (CoresInCluster) { do { --CoreIndex; } while (ClusterId != ArmCoreInfoTable[CoreIndex].ClusterId); } } // iterate to next cluster if (ClusterCount) { do { --ClusterIndex; } while (ClusterInRange (ArmCoreInfoTable, ArmCoreInfoTable[ClusterIndex].ClusterId, ClusterIndex + 1, ArmCoreCount - 1)); } } } else { DEBUG ((DEBUG_ERROR,"FDT: Error creating 'cpu-map' node\n")); return EFI_INVALID_PARAMETER; } SetSocIdStatus (Fdt); SetXgbeStatus (Fdt); // Update the real size of the Device Tree fdt_pack (Fdt); return EFI_SUCCESS; }
// Boot architecture information { EFI_ACPI_6_2_ARM_PSCI_COMPLIANT }, // BootArchFlags #ifdef HEADLESS_PLATFORM // Fixed feature flag information { EFI_ACPI_6_2_HEADLESS }, // Fixed feature flags #endif // Power management profile information { EFI_ACPI_6_2_PM_PROFILE_ENTERPRISE_SERVER }, // PowerManagement Profile /* GIC CPU Interface information GIC_ENTRY (CPUInterfaceNumber, Mpidr, PmuIrq, VGicIrq, EnergyEfficiency) */ { GICC_ENTRY (0, GET_MPID (0, 0), 92, 25, 0), GICC_ENTRY (1, GET_MPID (0, 1), 93, 25, 0), GICC_ENTRY (2, GET_MPID (0, 2), 94, 25, 0), GICC_ENTRY (3, GET_MPID (0, 3), 95, 25, 0), GICC_ENTRY (4, GET_MPID (1, 0), 96, 25, 0), GICC_ENTRY (5, GET_MPID (1, 1), 97, 25, 0), GICC_ENTRY (6, GET_MPID (1, 2), 98, 25, 0), GICC_ENTRY (7, GET_MPID (1, 3), 99, 25, 0) }, // GIC Distributor Info { FixedPcdGet64 (PcdGicDistributorBase), // UINT64 PhysicalBaseAddress 0, // UINT32 SystemVectorBase 3 // UINT8 GicVersion