DynamicTablesPkg: handle missing 'iommu-map' in root complex parser

Some guests (e.g. kvmtool) do not provide a SMMU, so the PCI node
in the DTB lacks an 'iommu-map'. The current code ASSERTs during
boot with:
"ASSERT [ConfigurationManagerDxe] RootComplexParser.c(244):
(Data != ((void *) 0)) && ((DataSize % (4 * sizeof (UINT32))) == 0)"

Instead, return EFI_NOT_FOUND when 'iommu-map' is absent so firmware
boot can proceed.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Leif Lindholm <leif.lindholm@oss.qualcomm.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Sami Mujawar <sami.mujawar@arm.com>
This commit is contained in:
Sami Mujawar 2025-11-18 15:19:55 +00:00 committed by mergify[bot]
parent ebe7fab41e
commit 18d0c3596e

View file

@ -239,49 +239,56 @@ RootComplexNodeParser (
RootComplexInfo->Identifier = GetNextIortIdentifier ();
Data = FdtGetProp (Fdt, RootComplexNode, "iommu-map", &DataSize);
if ((Data == NULL) || ((DataSize % (IOMMU_MAP_CELL_COUNT * sizeof (UINT32))) != 0)) {
// If error or invalid number of cells (not multiple of IOMMU_MAP_CELL_COUNT).
ASSERT ((Data != NULL) && ((DataSize % (IOMMU_MAP_CELL_COUNT * sizeof (UINT32))) == 0));
return EFI_ABORTED;
if (Data == NULL) {
// Some guests (e.g. kvmtool) do not provide a SMMU, so the PCI node
// in the DTB lacks an 'iommu-map'. In such cases set the Number of
// ID mappings to 0.
RootComplexInfo->IdMappingCount = 0;
} else {
if (((DataSize % (IOMMU_MAP_CELL_COUNT * sizeof (UINT32))) != 0)) {
// If error or invalid number of cells (not multiple of IOMMU_MAP_CELL_COUNT).
ASSERT ((DataSize % (IOMMU_MAP_CELL_COUNT * sizeof (UINT32))) == 0);
return EFI_ABORTED;
}
DataSize /= IOMMU_MAP_CELL_COUNT * sizeof (UINT32);
IdMappings = AllocateZeroPool (DataSize * sizeof (CM_ARM_ID_MAPPING));
if (IdMappings == NULL) {
ASSERT (IdMappings != NULL);
return EFI_OUT_OF_RESOURCES;
}
for (MapIndex = 0; MapIndex < DataSize; MapIndex++) {
IdMappings[MapIndex].InputBase = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT]);
IdMappings[MapIndex].NumIds = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 3]);
IdMappings[MapIndex].OutputBase = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 2]);
IdMappings[MapIndex].OutputReferenceToken = CM_ABSTRACT_TOKEN_MAKE (
ETokenNameSpaceFdtHwInfo,
EFdtHwInfoIortObject,
Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 1])
);
}
// Add the CmObj to the Configuration Manager.
Status = AddSingleCmObjArray (
FdtParserHandle,
CREATE_CM_ARM_OBJECT_ID (EArmObjIdMappingArray),
IdMappings,
sizeof (CM_ARM_ID_MAPPING) * DataSize,
DataSize,
&RootComplexInfo->IdMappingToken
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
FreePool (IdMappings);
return Status;
}
/// Number of ID mappings
RootComplexInfo->IdMappingCount = DataSize;
}
DataSize /= IOMMU_MAP_CELL_COUNT * sizeof (UINT32);
IdMappings = AllocateZeroPool (DataSize * sizeof (CM_ARM_ID_MAPPING));
if (IdMappings == NULL) {
ASSERT (IdMappings != NULL);
return EFI_OUT_OF_RESOURCES;
}
for (MapIndex = 0; MapIndex < DataSize; MapIndex++) {
IdMappings[MapIndex].InputBase = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT]);
IdMappings[MapIndex].NumIds = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 3]);
IdMappings[MapIndex].OutputBase = Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 2]);
IdMappings[MapIndex].OutputReferenceToken = CM_ABSTRACT_TOKEN_MAKE (
ETokenNameSpaceFdtHwInfo,
EFdtHwInfoIortObject,
Fdt32ToCpu (((UINT32 *)Data)[MapIndex * IOMMU_MAP_CELL_COUNT + 1])
);
}
// Add the CmObj to the Configuration Manager.
Status = AddSingleCmObjArray (
FdtParserHandle,
CREATE_CM_ARM_OBJECT_ID (EArmObjIdMappingArray),
IdMappings,
sizeof (CM_ARM_ID_MAPPING) * DataSize,
DataSize,
&RootComplexInfo->IdMappingToken
);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
FreePool (IdMappings);
return Status;
}
/// Number of ID mappings
RootComplexInfo->IdMappingCount = DataSize;
return EFI_SUCCESS;
}
@ -378,7 +385,10 @@ ArmPciRootComplexParser (
Status = RootComplexNodeParser (FdtParserHandle, Fdt, RootComplexNode, &RootComplexInfo);
if (EFI_ERROR (Status)) {
ASSERT_EFI_ERROR (Status);
if (Status != EFI_NOT_FOUND) {
ASSERT_EFI_ERROR (Status);
}
return Status;
}