From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.web11.1236.1689086244288038659 for ; Tue, 11 Jul 2023 07:37:24 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: nishant.sharma@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2DA0F2F4; Tue, 11 Jul 2023 07:38:06 -0700 (PDT) Received: from usa.arm.com (iss-desktop02.cambridge.arm.com [10.1.196.79]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 0FB213F740; Tue, 11 Jul 2023 07:37:22 -0700 (PDT) From: "Nishant Sharma" To: devel@edk2.groups.io Cc: Ard Biesheuvel , Sami Mujawar , Thomas Abraham , Sayanta Pattanayak , Achin Gupta Subject: [edk2-platforms][PATCH V1 09/20] StandaloneMmPkg: parse SP manifest and populate new boot information Date: Tue, 11 Jul 2023 15:36:47 +0100 Message-Id: <20230711143658.781597-10-nishant.sharma@arm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230711143658.781597-1-nishant.sharma@arm.com> References: <20230711143658.781597-1-nishant.sharma@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Achin Gupta This patch discovers the SP manifest in DT format passed by the SPMC. It then parses it to obtain the boot information required to initialise the SP. Signed-off-by: Achin Gupta Signed-off-by: Sayanta Pattanayak Signed-off-by: Nishant Sharma --- StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h = | 2 +- StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMmCoreE= ntryPoint.c | 389 +++++++++++++++++++- 2 files changed, 381 insertions(+), 10 deletions(-) diff --git a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoi= nt.h b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h index c965192c702e..90d67a2f25b5 100644 --- a/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h +++ b/StandaloneMmPkg/Include/Library/Arm/StandaloneMmCoreEntryPoint.h @@ -2,7 +2,7 @@ Entry point to the Standalone MM Foundation when initialized during th= e SEC phase on ARM platforms =20 -Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.
+Copyright (c) 2017 - 2023, Arm Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent =20 **/ diff --git a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/Stand= aloneMmCoreEntryPoint.c b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPo= int/Arm/StandaloneMmCoreEntryPoint.c index 9f6af55c86c4..505786aff07c 100644 --- a/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMm= CoreEntryPoint.c +++ b/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/Arm/StandaloneMm= CoreEntryPoint.c @@ -38,6 +38,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #define BOOT_PAYLOAD_VERSION 1 =20 +#define FFA_PAGE_4K 0 +#define FFA_PAGE_16K 1 +#define FFA_PAGE_64K 2 + PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint =3D NULL; =20 /** @@ -106,6 +110,7 @@ GetAndPrintBootinformation ( } =20 return PayloadBootInfo; +} =20 /** An StMM SP implements partial support for FF-A v1.0. The FF-A ABIs are= used to @@ -266,6 +271,308 @@ DelegatedEventLoop ( } } =20 +STATIC +BOOLEAN +CheckDescription ( + IN VOID * DtbAddress, + IN INT32 Offset, + OUT CHAR8 * Description, + OUT UINT32 Size + ) +{ + CONST CHAR8 * Property; + INT32 LenP; + + Property =3D fdt_getprop (DtbAddress, Offset, "description", &LenP); + if (Property =3D=3D NULL) { + return FALSE; + } + + return CompareMem (Description, Property, MIN(Size, (UINT32)LenP)) =3D=3D= 0; + +} + +STATIC +EFI_STATUS +ReadProperty32 ( + IN VOID * DtbAddress, + IN INT32 Offset, + IN CHAR8 * Property, + OUT UINT32 * Value + ) +{ + CONST UINT32 * Property32; + + Property32 =3D fdt_getprop (DtbAddress, Offset, Property, NULL); + if (Property32 =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "%s: Missing in FF-A boot information manifest\n", + Property + )); + return EFI_INVALID_PARAMETER; + } + + *Value =3D fdt32_to_cpu (*Property32); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ReadProperty64 ( + IN VOID * DtbAddress, + IN INT32 Offset, + IN CHAR8 * Property, + OUT UINT64 * Value + ) +{ + CONST UINT64 * Property64; + + Property64 =3D fdt_getprop (DtbAddress, Offset, Property, NULL); + if (Property64 =3D=3D NULL) { + DEBUG (( + DEBUG_ERROR, + "%s: Missing in FF-A boot information manifest\n", + Property + )); + return EFI_INVALID_PARAMETER; + } + + *Value =3D fdt64_to_cpu (*Property64); + + return EFI_SUCCESS; +} + +STATIC +BOOLEAN +ReadRegionInfo ( + IN VOID *DtbAddress, + IN INT32 Node, + IN CHAR8 *Region, + IN UINTN RegionStrSize, + IN UINT32 PageSize, + OUT UINT64 *Address, + OUT UINT64 *Size + ) +{ + BOOLEAN FoundBuffer; + INTN Status =3D 0; + + FoundBuffer =3D CheckDescription ( + DtbAddress, + Node, + Region, + RegionStrSize + ); + if (!FoundBuffer) { + return FALSE; + } + + DEBUG ((DEBUG_INFO, "Found Node: %a\n", Region)); + Status =3D ReadProperty64 ( + DtbAddress, + Node, + "base-address", + Address + ); + if (Status !=3D EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "base-address missing in DTB")); + return FALSE; + } + DEBUG (( + DEBUG_INFO, + "base =3D 0x%llx\n", + *Address + )); + + Status =3D ReadProperty32 ( + DtbAddress, + Node, + "pages-count", + (UINT32*)Size + ); + if (Status !=3D EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "pages-count missing in DTB")); + return FALSE; + } + + DEBUG ((DEBUG_ERROR, "pages-count: 0x%lx\n", *Size)); + + *Size =3D *Size * PageSize; + DEBUG (( + DEBUG_INFO, + "Size =3D 0x%llx\n", + *Size + )); + + return TRUE; +} + +/** + + Populates FF-A boot information structure. + + This function receives the address of a DTB from which boot informatio= n defind + by FF-A and required to initialize the standalone environment is extra= cted. + + @param [in, out] StmmBootInfo Pointer to a pre-allocated boot info st= ructure to be + populated. + @param [in] DtbAddress Address of the Device tree from where b= oot + information will be fetched. +**/ +STATIC +EFI_STATUS +PopulateBootinformation ( + IN OUT EFI_STMM_BOOT_INFO *StmmBootInfo, + IN VOID *DtbAddress +) +{ + INTN Status; + INT32 Offset; + INT32 Node; + BOOLEAN FoundNsCommBuffer =3D FALSE; + BOOLEAN FoundSharedBuffer =3D FALSE; + BOOLEAN FoundHeap =3D FALSE; + UINT32 PageSize; + + Offset =3D fdt_node_offset_by_compatible (DtbAddress, -1, "arm,ffa-man= ifest-1.0"); + DEBUG ((DEBUG_INFO, "Offset =3D %d \n", Offset)); + if (Offset < 0) { + DEBUG ((DEBUG_ERROR, "Missing FF-A boot information in manifest\n"))= ; + return EFI_NOT_FOUND; + } + + Status =3D ReadProperty64 ( + DtbAddress, + Offset, + "load-address", + &StmmBootInfo->SpMemBase + ); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + DEBUG ((DEBUG_INFO, "sp mem base =3D 0x%llx\n", StmmBootInfo->SpMemBa= se)); + + Status =3D ReadProperty64 ( + DtbAddress, + Offset, + "image-size", + &StmmBootInfo->SpMemSize + ); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + DEBUG ((DEBUG_INFO, "sp mem size =3D 0x%llx\n", StmmBootInfo->SpMemSi= ze)); + + Status =3D ReadProperty32 (DtbAddress, Offset, "xlat-granule", &PageSi= ze); + if (Status !=3D EFI_SUCCESS) { + return Status; + } + + /* EFI_PAGE_SIZE is 4KB */ + switch (PageSize) { + case FFA_PAGE_4K: + PageSize =3D EFI_PAGE_SIZE; + break; + + case FFA_PAGE_16K: + PageSize =3D 4 * EFI_PAGE_SIZE; + break; + + case FFA_PAGE_64K: + PageSize =3D 16 * EFI_PAGE_SIZE; + break; + + default: + DEBUG ((DEBUG_ERROR, "Invalid page type =3D %lu\n", PageSize)); + return EFI_INVALID_PARAMETER; + break; + }; + + DEBUG ((DEBUG_INFO, "Page Size =3D 0x%lx\n", PageSize)); + + Offset =3D fdt_subnode_offset_namelen ( + DtbAddress, + Offset, + "memory-regions", + sizeof("memory-regions") - 1 + ); + if (Offset < 1) { + DEBUG (( + DEBUG_ERROR, + "%s: Missing in FF-A boot information manifest\n", + "memory-regions" + )); + return EFI_INVALID_PARAMETER; + } + + for ( + Node =3D fdt_first_subnode (DtbAddress, Offset); + Node > 0; + Node =3D fdt_next_subnode (DtbAddress, Node)) { + if (!FoundNsCommBuffer) { + FoundNsCommBuffer =3D ReadRegionInfo ( + DtbAddress, + Node, + "ns-comm", + sizeof ("ns-comm") - 1, + PageSize, + &StmmBootInfo->SpNsCommBufBase, + &StmmBootInfo->SpNsCommBufSize + ); + } + + if (!FoundHeap) { + FoundHeap =3D ReadRegionInfo ( + DtbAddress, + Node, + "heap", + sizeof ("heap") - 1, + PageSize, + &StmmBootInfo->SpHeapBase, + &StmmBootInfo->SpHeapSize + ); + } + + if (!FoundSharedBuffer) { + FoundSharedBuffer =3D ReadRegionInfo ( + DtbAddress, + Node, + "shared-buff", + sizeof ("shared-buff") - 1, + PageSize, + &StmmBootInfo->SpSharedBufBase, + &StmmBootInfo->SpSharedBufSize + ); + } + } + + if (!FoundNsCommBuffer) { + DEBUG ((DEBUG_ERROR, "Failed to find ns-comm buffer info\n")); + return EFI_INVALID_PARAMETER; + } + + if (!FoundHeap) { + DEBUG ((DEBUG_ERROR, "Failed to find heap buffer info\n")); + return EFI_INVALID_PARAMETER; + } + + if (!FoundSharedBuffer) { + DEBUG ((DEBUG_ERROR, "Failed to find shared buffer info\n")); + return EFI_INVALID_PARAMETER; + } + + // Populate CPU information under the assumption made in the FF-A spec= that + // this is a uniprocessor SP that is capable of migration. So, it is f= ine if + // it sees 0 as both its physical and linear cpu id + StmmBootInfo->CpuInfo.Mpidr =3D 0; + StmmBootInfo->CpuInfo.LinearId =3D 0; + StmmBootInfo->CpuInfo.Flags =3D 0; + + return EFI_SUCCESS; +} + /** Query the SPM version, check compatibility and return success if compa= tible. =20 @@ -343,6 +650,49 @@ InitArmSvcArgs ( } } =20 + +STATIC +EFI_STATUS +GetSpManifest ( + IN OUT UINT64 **SpManifestAddr, + IN VOID *BootInfoAddr + ) +{ + EFI_FFA_BOOT_INFO_HEADER *FfaBootInfo; + EFI_FFA_BOOT_INFO_DESC *FfaBootInfoDesc; + + // Paranoid check to avoid an inadvertent NULL pointer dereference. + if (BootInfoAddr =3D=3D NULL) { + DEBUG ((DEBUG_ERROR, "FF-A Boot information is NULL\n")); + return EFI_INVALID_PARAMETER; + } + + // Check boot information magic number. + FfaBootInfo =3D (EFI_FFA_BOOT_INFO_HEADER *) BootInfoAddr; + if (FfaBootInfo->Magic !=3D FFA_INIT_DESC_SIGNATURE) { + DEBUG (( + DEBUG_ERROR, "FfaBootInfo Magic no. is invalid 0x%ux\n", + FfaBootInfo->Magic + )); + return EFI_INVALID_PARAMETER; + } + + + FfaBootInfoDesc =3D + (EFI_FFA_BOOT_INFO_DESC *)((UINT8 *)BootInfoAddr + + FfaBootInfo->OffsetBootInfoDesc); + + if (FfaBootInfoDesc->Type =3D=3D + (FFA_BOOT_INFO_TYPE(FFA_BOOT_INFO_TYPE_STD) | + FFA_BOOT_INFO_TYPE_ID(FFA_BOOT_INFO_TYPE_ID_FDT))) { + *SpManifestAddr =3D (UINT64 *) FfaBootInfoDesc->Content; + return EFI_SUCCESS; + } + + DEBUG ((DEBUG_ERROR, "SP manifest not found \n")); + return EFI_NOT_FOUND; +} + /** The entry point of Standalone MM Foundation. =20 @@ -363,6 +713,7 @@ ModuleEntryPoint ( { PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo; + EFI_STMM_BOOT_INFO StmmBootInfo =3D {0}; ARM_SVC_ARGS InitMmFoundationSvcArgs; EFI_STATUS Status; INT32 Ret; @@ -372,6 +723,8 @@ ModuleEntryPoint ( VOID *TeData; UINTN TeDataSize; EFI_PHYSICAL_ADDRESS ImageBase; + UINT64 *DtbAddress; + EFI_FIRMWARE_VOLUME_HEADER *BfvAddress; BOOLEAN UseOnlyFfaAbis =3D FALSE; =20 if (FixedPcdGet32 (PcdFfaEnable) !=3D 0) { @@ -384,18 +737,36 @@ ModuleEntryPoint ( goto finish; } =20 - PayloadBootInfo =3D GetAndPrintBootinformation (SharedBufAddress); - if (PayloadBootInfo =3D=3D NULL) { - Status =3D EFI_UNSUPPORTED; - goto finish; + // If only FF-A is used, the DTB address is passed in the Boot informa= tion + // structure. Else, the Boot info is copied from Sharedbuffer. + if (UseOnlyFfaAbis) { + Status =3D GetSpManifest (&DtbAddress, SharedBufAddress); + if (Status !=3D EFI_SUCCESS) { + goto finish; + } + + // Extract boot information from the DTB + Status =3D PopulateBootinformation (&StmmBootInfo, (VOID *) DtbAddre= ss); + if (Status !=3D EFI_SUCCESS) { + goto finish; + } + + // Stash the base address of the boot firmware volume + BfvAddress =3D (EFI_FIRMWARE_VOLUME_HEADER *) StmmBootInfo.SpMemBase= ; + } else { + PayloadBootInfo =3D GetAndPrintBootinformation (SharedBufAddress); + if (PayloadBootInfo =3D=3D NULL) { + Status =3D EFI_UNSUPPORTED; + goto finish; + } + + // Stash the base address of the boot firmware volume + BfvAddress =3D (EFI_FIRMWARE_VOLUME_HEADER *) PayloadBootInfo->SpIma= geBase; } =20 + // Locate PE/COFF File information for the Standalone MM core module - Status =3D LocateStandaloneMmCorePeCoffData ( - (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PayloadBootInfo->SpIma= geBase, - &TeData, - &TeDataSize - ); + Status =3D LocateStandaloneMmCorePeCoffData (BfvAddress, &TeData, &TeD= ataSize); =20 if (EFI_ERROR (Status)) { goto finish; --=20 2.34.1