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.web12.4845.1614766835880760264 for ; Wed, 03 Mar 2021 02:20:36 -0800 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: pierre.gondois@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 6A02C101E; Wed, 3 Mar 2021 02:20:35 -0800 (PST) Received: from [192.168.1.169] (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 4529C3F73B; Wed, 3 Mar 2021 02:20:34 -0800 (PST) From: "PierreGondois" Subject: Re: [edk2-devel] [PATCH 1/2 v5] Drivers/OpTeeRpmb: Add an OP-TEE backed RPMB driver References: <20210212173459.508205-1-ilias.apalodimas@linaro.org> <20210212173459.508205-2-ilias.apalodimas@linaro.org> To: ilias.apalodimas@linaro.org, devel@edk2.groups.io, Sami.Mujawar@arm.com Message-ID: <51d77291-571b-1635-caa4-590f66c75b56@arm.com> Date: Wed, 3 Mar 2021 10:20:17 +0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.8.0 MIME-Version: 1.0 In-Reply-To: <20210212173459.508205-2-ilias.apalodimas@linaro.org> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable Hello Ilias, My review is mostly about coding style, but I would have some (inlined)=20 remarks about your patch, Regards, Pierre On 3/2/21 3:35 PM, Pierre Gondois wrote: > > -----------------------------------------------------------------------= - > *From:* devel@edk2.groups.io on behalf of Ilias=20 > Apalodimas via groups.io > *Sent:* Friday, February 12, 2021 5:34 PM > *To:* devel@edk2.groups.io ; Sami Mujawar=20 > > *Cc:* ardb+tianocore@kernel.org ;=20 > sughosh.ganu@linaro.org ; leif@nuviainc.com=20 > ; Ilias Apalodimas > *Subject:* [edk2-devel] [PATCH 1/2 v5] Drivers/OpTeeRpmb: Add an=20 > OP-TEE backed RPMB driver > A following patch is adding support for building StMM in order to run i= t > from OP-TEE. > OP-TEE in combination with a NS-world supplicant can use the RPMB > partition of an eMMC to store EFI variables. The supplicant > functionality is currently available in U-Boot only but can be ported > into EDK2. Assuming similar functionality is added in EDK2, this will > allow any hardware with an RPMB partition to store EFI variables > securely. > > So let's add a driver that enables access of the RPMB partition through > OP-TEE. Since the upper layers expect a byte addressable interface, > the driver allocates memory and patches the PCDs, while syncing the > memory/hardware on read/write callbacks. > > Signed-off-by: Ilias Apalodimas > --- > =A0Drivers/OpTeeRpmb/FixupPcd.c=A0=A0=A0=A0=A0 |=A0 89 +++ > =A0Drivers/OpTeeRpmb/FixupPcd.inf=A0=A0=A0 |=A0 43 ++ > =A0Drivers/OpTeeRpmb/OpTeeRpmbFv.inf |=A0 58 ++ > =A0Drivers/OpTeeRpmb/OpTeeRpmbFvb.c=A0 | 920 ++++++++++++++++++++++++++= ++++ > =A0Drivers/OpTeeRpmb/OpTeeRpmbFvb.h=A0 |=A0 52 ++ > =A05 files changed, 1162 insertions(+) > =A0create mode 100644 Drivers/OpTeeRpmb/FixupPcd.c > =A0create mode 100644 Drivers/OpTeeRpmb/FixupPcd.inf > =A0create mode 100644 Drivers/OpTeeRpmb/OpTeeRpmbFv.inf > =A0create mode 100644 Drivers/OpTeeRpmb/OpTeeRpmbFvb.c > =A0create mode 100644 Drivers/OpTeeRpmb/OpTeeRpmbFvb.h > > diff --git a/Drivers/OpTeeRpmb/FixupPcd.c b/Drivers/OpTeeRpmb/FixupPcd.= c > new file mode 100644 > index 000000000000..6cd503b71c6d > --- /dev/null > +++ b/Drivers/OpTeeRpmb/FixupPcd.c > @@ -0,0 +1,89 @@ > +/** @file > > + > > +=A0 Update the patched PCDs to their correct value > > + > > +=A0 Copyright (c) 2020, Linaro Ltd. All rights reserved.
> > + > > +=A0 SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +/** > > + * Patch the relevant PCDs of the RPMB driver with the correct=20 > address of the > > + * allocated memory > > + * > > +**/ > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > + > > +#include "OpTeeRpmbFvb.h" > > + > > +/** > > +=A0 Fixup the Pcd values for variable storage > > + > > +=A0 Since the upper layers of EDK2 expect a memory mapped interface an= d=20 > we can't > > +=A0 offer that from an RPMB, the driver allocates memory on init and=20 > passes that > > +=A0 on the upper layers. Since the memory is dynamically allocated and= =20 > we can't set the > > +=A0 PCD is StMM context, we need to patch it correctly on each access I think: is -> in > > + > > +=A0 @retval EFI_SUCCESS Protocol was found and PCDs patched up > > + > > + **/ I think there should not be a space here. > > +EFI_STATUS > > +EFIAPI > > +FixPcdMemory ( > > +=A0 VOID > > +=A0 ) > > +{ > > +=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL=A0 *FvbProtocol; > > +=A0 MEM_INSTANCE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 *Instance; > > +=A0 EFI_STATUS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 Status; > > + > > +=A0 // > > +=A0 // Locate SmmFirmwareVolumeBlockProtocol > > +=A0 // > > +=A0 Status =3D gMmst->MmLocateProtocol ( > > + &gEfiSmmFirmwareVolumeBlockProtocolGuid, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 NULL, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (VOID **) &F= vbProtocol > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > +=A0 ASSERT_EFI_ERROR (Status); > > + > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (FvbProtocol); > > +=A0 // The Pcd is user defined, so make sure we don't overflow > > +=A0 if (Instance->MemBaseAddress > MAX_UINT64 - PcdGet32=20 > (PcdFlashNvStorageVariableSize)) { > > +=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0 } > > + > > +=A0 if (Instance->MemBaseAddress > MAX_UINT64 - PcdGet32=20 > (PcdFlashNvStorageVariableSize) - > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) { > > +=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0 } > > + > > +=A0 // Patch PCDs with the the correct values I think it s 'the the' -> the > > +=A0 PatchPcdSet64 (PcdFlashNvStorageVariableBase64,=20 > Instance->MemBaseAddress); > > +=A0 PatchPcdSet64 ( > > +=A0=A0=A0 PcdFlashNvStorageFtwWorkingBase64, > > +=A0=A0=A0 Instance->MemBaseAddress + PcdGet32 (PcdFlashNvStorageVariab= leSize) > > +=A0=A0=A0 ); > > +=A0 PatchPcdSet64 ( > > +=A0=A0=A0 PcdFlashNvStorageFtwSpareBase64, > > +=A0=A0=A0 Instance->MemBaseAddress + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageVariableSize) + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > > +=A0=A0=A0 ); > > + > > +=A0 DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageVariableBase64:=20 > 0x%lx\n", > > +=A0=A0=A0 __FUNCTION__, PcdGet64 (PcdFlashNvStorageVariableBase64))); > > +=A0 DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageFtwWorkingBase64:=20 > 0x%lx\n", > > +=A0=A0=A0 __FUNCTION__, PcdGet64 (PcdFlashNvStorageFtwWorkingBase64)))= ; > > +=A0 DEBUG ((DEBUG_INFO, "%a: Fixup PcdFlashNvStorageFtwSpareBase64:=20 > 0x%lx\n", > > +=A0=A0=A0 __FUNCTION__, PcdGet64 (PcdFlashNvStorageFtwSpareBase64))); > > + > > +=A0 return Status; > > +} > > diff --git a/Drivers/OpTeeRpmb/FixupPcd.inf=20 > b/Drivers/OpTeeRpmb/FixupPcd.inf > new file mode 100644 > index 000000000000..5146257993ef > --- /dev/null > +++ b/Drivers/OpTeeRpmb/FixupPcd.inf > @@ -0,0 +1,43 @@ > +## @file > > +#=A0 Instance of Base Memory Library without assembly. > > +# > > +#=A0 Copyright (c) 2020, Linaro Ltd. All rights reserved.
> > +# > > +#=A0 SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +# > > +## > > + > > +[Defines] > > +=A0 INF_VERSION=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D 0x0001001A > > +=A0 BASE_NAME=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 =3D FixupPcd > > +=A0 FILE_GUID=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 =3D a827c337-a9c6-301b-aeb7-acbc95d8da22 > > +=A0 MODULE_TYPE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D BASE > > +=A0 VERSION_STRING=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =3D= 0.1 > > +=A0 LIBRARY_CLASS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =3D= RpmbPcdFixup|MM_STANDALONE > > +=A0 CONSTRUCTOR=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D FixPcdMemory > > + > > +[Sources] > > +=A0 FixupPcd.c > > +=A0 OpTeeRpmbFvb.h > > + > > +[Packages] > > +=A0 MdeModulePkg/MdeModulePkg.dec > > +=A0 MdePkg/MdePkg.dec > > + > > +[LibraryClasses] > > +=A0 BaseLib > > +=A0 DebugLib > > +=A0 MmServicesTableLib > > +=A0 PcdLib > > + > > +[Pcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > > + > > +[Protocols] > > +=A0 gEfiSmmFirmwareVolumeBlockProtocolGuid=A0=A0=A0=A0=A0=A0=A0=A0=A0 = ## CONSUMES > > diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFv.inf=20 > b/Drivers/OpTeeRpmb/OpTeeRpmbFv.inf > new file mode 100644 > index 000000000000..c3580859ffde > --- /dev/null > +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFv.inf > @@ -0,0 +1,58 @@ > +## @file > > +# > > +#=A0 Component description file for OpTeeRpmbFv module > > +# > > +#=A0 Copyright (c) 2020, Linaro Ltd. All rights reserved.
> > +# > > +#=A0 SPDX-License-Identifier: BSD-2-Clause-Patent > > +# > > +## > > + > > +[Defines] > > +=A0 INF_VERSION=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D 0x0001001A > > +=A0 BASE_NAME=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 =3D OpTeeRpmbFv > > +=A0 FILE_GUID=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 =3D 4803FC20-E583-3BCD-8C60-141E85C9A2CF > > +=A0 MODULE_TYPE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D MM_STANDALONE > > +=A0 VERSION_STRING=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =3D= 0.1 > > +=A0 PI_SPECIFICATION_VERSION=A0=A0=A0=A0=A0=A0 =3D 0x00010032 > > +=A0 ENTRY_POINT=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D OpTeeRpmbFvbInit > > + > > +[Sources] > > +=A0 OpTeeRpmbFvb.c > > +=A0 OpTeeRpmbFvb.h > > + > > +[Packages] > > +=A0 ArmPkg/ArmPkg.dec > > +=A0 ArmPlatformPkg/ArmPlatformPkg.dec > > +=A0 MdeModulePkg/MdeModulePkg.dec > > +=A0 MdePkg/MdePkg.dec > > +=A0 StandaloneMmPkg/StandaloneMmPkg.dec > > + > > +[LibraryClasses] > > +=A0 ArmSvcLib > > +=A0 BaseLib > > +=A0 BaseMemoryLib > > +=A0 DebugLib > > +=A0 MemoryAllocationLib > > +=A0 MmServicesTableLib > > +=A0 PcdLib > > +=A0 StandaloneMmDriverEntryPoint > > + > > +[Guids] > > +=A0 gEfiAuthenticatedVariableGuid > > +=A0 gEfiSystemNvDataFvGuid > > +=A0 gEfiVariableGuid > > + > > +[Pcd] > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 > > + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize > > + > > +[Protocols] > > +=A0 gEfiSmmFirmwareVolumeBlockProtocolGuid=A0=A0=A0=A0=A0=A0=A0=A0=A0 = ## PRODUCES > > + > > +[Depex] > > +=A0 TRUE > > diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFvb.c=20 > b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.c > new file mode 100644 > index 000000000000..950082cf6df4 > --- /dev/null > +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.c > @@ -0,0 +1,920 @@ > +/** @file > > + > > +=A0 FV block I/O protocol driver for RPMB eMMC accessed via OP-TEE > > + > > +=A0 Copyright (c) 2020, Linaro Ltd. All rights reserved.
> > + > > +=A0 SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#include "OpTeeRpmbFvb.h" > > + > > +// These are what OP-TEE expects in ./core/arch/arm/kernel/stmm_sp.c > > +// Since the FFA autodiscovery mechanism is not yet implemented we are > > +// hardcoding the ID values for the two operations OP-TEE currently=20 > supports > > +// > > +// mMemMgrId is used to set the page permissions after relocating the=20 > executable > > +// mStorageId is used to access the RPMB partition via OP-TEE > > +// In both cases the return value is located in x3. Once the=20 > autodiscovery mechanism > > +// is in place, we'll have to account for an error value in x2 as=20 > well, handling > > +// the autodiscovery failed scenario > +STATIC CONST UINT16 mMemMgrId =3D 3U; > > +STATIC CONST UINT16 mStorageId =3D 4U; > > + > > +STATIC MEM_INSTANCE mInstance; > > + > > +/** > > +=A0 Sends an SVC call to OP-TEE for reading/writing an RPMB partition > > + > > +=A0 @param SvcAct=A0=A0=A0=A0 SVC ID for read/write > > +=A0 @param Addr=A0=A0=A0=A0=A0=A0 Base address of the buffer. When rea= ding contents=20 > will be > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 copied to th= at buffer after reading them from the=20 > device. > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 When writing= , the buffer holds the contents we=20 > want to > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 write cwtoin= the device > > +=A0 @param NumBytes=A0=A0 Number of bytes to read/write > > +=A0 @param Offset=A0=A0=A0=A0 Offset into the RPMB file > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_SUCCESS read/write ok > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_UNSUPPORTED SVC to op-te= e not supported > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_INVALID_PARAMETER SVC to= op-tee had an=20 > invalid param > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_ACCESS_DENIED SVC to op-= tee was denied > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_OUT_OF_RESOURCES op-tee = out of memory > > +**/ > > +STATIC > > +EFI_STATUS > > +ReadWriteRpmb ( > > +=A0 UINTN=A0 SvcAct, > > +=A0 UINTN=A0 Addr, > > +=A0 UINTN=A0 NumBytes, > > +=A0 UINTN=A0 Offset > > +=A0 ) I think the parameters should have IN/OUT indications, and the function=20 header aswell (cf=20 https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/6_do= cumenting_software/62_comments#6-2-1-only-use-c-style-comments-on-the-sam= e-line-as-pre-processor-directives-and-in-doxygen-style-file-and-function= -header-comment-blocks). There are other functions with missing IN/OUT parameters. > > +{ > > +=A0 ARM_SVC_ARGS=A0 SvcArgs; > > +=A0 EFI_STATUS=A0=A0=A0 Status; > > + > > +=A0 ZeroMem (&SvcArgs, sizeof (SvcArgs)); > > + > > +=A0 SvcArgs.Arg0 =3D ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64; > > +=A0 SvcArgs.Arg1 =3D mStorageId; > > +=A0 SvcArgs.Arg2 =3D 0; > > +=A0 SvcArgs.Arg3 =3D SvcAct; > > +=A0 SvcArgs.Arg4 =3D Addr; > > +=A0 SvcArgs.Arg5 =3D NumBytes; > > +=A0 SvcArgs.Arg6 =3D Offset; > > + > > +=A0 ArmCallSvc (&SvcArgs); > > +=A0 if (SvcArgs.Arg3) { > > +=A0=A0=A0 DEBUG ((DEBUG_ERROR, "%a: Svc Call 0x%08x Addr: 0x%08x len: = 0x%x=20 > Offset: 0x%x failed with 0x%x\n", > > +=A0=A0=A0=A0=A0 __func__, SvcAct, Addr, NumBytes, Offset, SvcArgs.Arg3= )); > > +=A0 } > > + > > +=A0 switch (SvcArgs.Arg3) { > > +=A0 case ARM_SVC_SPM_RET_SUCCESS: > > +=A0=A0=A0 Status =3D EFI_SUCCESS; > > +=A0=A0=A0 break; > > + > > +=A0 case ARM_SVC_SPM_RET_NOT_SUPPORTED: > > +=A0=A0=A0 Status =3D EFI_UNSUPPORTED; > > +=A0=A0=A0 break; > > + > > +=A0 case ARM_SVC_SPM_RET_INVALID_PARAMS: > > +=A0=A0=A0 Status =3D EFI_INVALID_PARAMETER; > > +=A0=A0=A0 break; > > + > > +=A0 case ARM_SVC_SPM_RET_DENIED: > > +=A0=A0=A0 Status =3D EFI_ACCESS_DENIED; > > +=A0=A0=A0 break; > > + > > +=A0 case ARM_SVC_SPM_RET_NO_MEMORY: > > +=A0=A0=A0 Status =3D EFI_OUT_OF_RESOURCES; > > +=A0=A0=A0 break; > > + > > +=A0 default: > > +=A0=A0=A0 Status =3D EFI_ACCESS_DENIED; > > +=A0 } > > + > > +=A0 return Status; > > +} > > + > > +/** > > +=A0 The GetAttributes() function retrieves the attributes and > > +=A0 current settings of the block. > > + > > +=A0 @param This=A0=A0=A0=A0=A0=A0 Indicates the EFI_FIRMWARE_VOLUME_BL= OCK_PROTOCOL=20 > instance. > > + > > +=A0 @param Attributes Pointer to EFI_FVB_ATTRIBUTES_2 in which the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 attributes a= nd current settings are > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 returned. Ty= pe EFI_FVB_ATTRIBUTES_2 is defined > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 in EFI_FIRMW= ARE_VOLUME_HEADER. > > + > > +=A0 @retval EFI_SUCCESS The firmware volume attributes were > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return= ed. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbGetAttributes ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 OUT=A0=A0=A0=A0=A0=A0 EFI_FVB_ATTRIBUTES_2 *Attributes > > +=A0 ) > > +{ > > +=A0 *Attributes =3D EFI_FVB2_READ_ENABLED_CAP=A0=A0 | // Reads may be = enabled > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_READ_STATUS=A0=A0= =A0=A0=A0=A0=A0 | // Reads are currently=20 > enabled > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_WRITE_STATUS=A0= =A0=A0=A0=A0=A0 | // Writes are currently=20 > enabled > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_WRITE_ENABLED_C= AP=A0 | // Writes may be enabled > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_STICKY_WRITE=A0= =A0=A0=A0=A0=A0 | // A block erase is=20 > required to flip bits into EFI_FVB2_ERASE_POLARITY > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_MEMORY_MAPPED=A0= =A0=A0=A0=A0 | // It is memory mapped > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_ERASE_POLARITY;= =A0=A0=A0=A0=A0 // After erasure all=20 > bits take this value (i.e. '1') > > + > > +=A0 return EFI_SUCCESS; > > +} > > + > > +/** > > +=A0 The SetAttributes() function sets configurable firmware volume > > +=A0 attributes and returns the new settings of the firmware volume. > > + > > +=A0 @param This=A0=A0=A0=A0=A0=A0=A0=A0 Indicates the=20 > EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL instance. > > + > > +=A0 @param Attributes=A0=A0 On input, Attributes is a pointer to > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FV= B_ATTRIBUTES_2 that contains the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 desire= d firmware volume settings. On > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 succes= sful return, it contains the new > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 settin= gs of the firmware volume. Type > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FV= B_ATTRIBUTES_2 is defined in > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FI= RMWARE_VOLUME_HEADER. > > + > > +=A0 @retval EFI_UNSUPPORTED Set attributes not supported > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbSetAttributes ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 IN OUT=A0=A0=A0 EFI_FVB_ATTRIBUTES_2 *Attributes Parameters should be aligned. (I think this is valid at other places,=20 like for OpTeeRpmbFvbGetPhysicalAddress()) > > +=A0 ) > > +{ > > +=A0 DEBUG ((DEBUG_ERROR, "FvbSetAttributes(0x%X) is not supported\n",=20 > *Attributes)); > > +=A0 return EFI_UNSUPPORTED; > > +} > > + > > +/** > > +=A0 The GetPhysicalAddress() function retrieves the base address of > > +=A0 a memory-mapped firmware volume. This function should be called > > +=A0 only for memory-mapped firmware volumes. > > + > > +=A0 @param This=A0=A0=A0=A0 Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PR= OTOCOL=20 > instance. > > + > > +=A0 @param Address=A0 Pointer to a caller-allocated > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_PHYSICAL_ADDRE= SS that, on successful > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return from GetPhy= sicalAddress(), contains the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 base address of th= e firmware volume. > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0 The firmware volume base add= ress was=20 > returned. > > + > > +=A0 @retval EFI_UNSUPPORTED=A0=A0 The firmware volume is not memory ma= pped. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbGetPhysicalAddress ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 OUT=A0=A0=A0=A0=A0=A0 EFI_PHYSICAL_ADDRESS=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 *Address > > +=A0 ) > > +{ > > +=A0 MEM_INSTANCE *Instance; > > + > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (This); > > +=A0 *Address =3D Instance->MemBaseAddress; > > + > > +=A0 return EFI_SUCCESS; > > +} > > + > > +/** > > +=A0 The GetBlockSize() function retrieves the size of the requested > > +=A0 block. It also returns the number of additional blocks with > > +=A0 the identical size. The GetBlockSize() function is used to > > +=A0 retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). > > + > > + > > +=A0 @param This=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Indicates the=20 > EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL instance. > > + > > +=A0 @param Lba=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Indicates the block fo= r which to return the size. > > + > > +=A0 @param BlockSize=A0=A0=A0=A0=A0 Pointer to a caller-allocated UINT= N in which > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = the size of the block is returned. > > + > > +=A0 @param NumberOfBlocks Pointer to a caller-allocated UINTN in > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = which the number of consecutive blocks, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = starting with Lba, is returned. All > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = blocks in this range have a size of > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = BlockSize. > > + > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 The firmwa= re volume base address=20 > was returned. > > + > > +=A0 @retval EFI_INVALID_PARAMETER=A0=A0 The requested LBA is out of ra= nge. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbGetBlockSize ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 EFI_LBA=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lba, > > +=A0 OUT=A0=A0=A0=A0=A0=A0 UINTN *BlockSize, > > +=A0 OUT=A0=A0=A0=A0=A0=A0 UINTN *NumberOfBlocks > > +=A0 ) > > +{ > > +=A0 MEM_INSTANCE *Instance; > > + > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (This); > > +=A0 if (Lba > Instance->NBlocks) { > > +=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0 } > > + > > +=A0 *NumberOfBlocks =3D Instance->NBlocks - (UINTN)Lba; > > +=A0 *BlockSize =3D Instance->BlockSize; > > + > > +=A0 return EFI_SUCCESS; > > +} > > + > > +/** > > +=A0 Reads the specified number of bytes into a buffer from the=20 > specified block. > > + > > +=A0 The Read() function reads the requested number of bytes from the > > +=A0 requested block and stores them in the provided buffer. > > +=A0 Implementations should be mindful that the firmware volume > > +=A0 might be in the ReadDisabled state. If it is in this state, > > +=A0 the Read() function must return the status code > > +=A0 EFI_ACCESS_DENIED without modifying the contents of the > > +=A0 buffer. The Read() function must also prevent spanning block > > +=A0 boundaries. If a read is requested that would span a block > > +=A0 boundary, the read must read up to the boundary but not > > +=A0 beyond. The output parameter NumBytes must be set to correctly > > +=A0 indicate the number of bytes actually read. The caller must be > > +=A0 aware that a read may be partially completed. > > + > > +=A0 @param This=A0=A0=A0=A0 Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PR= OTOCOL=20 > instance. > > + > > +=A0 @param Lba=A0=A0=A0=A0=A0 The starting logical block index > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 from which to read= . > > + > > +=A0 @param Offset=A0=A0 Offset into the block at which to begin readin= g. > > + > > +=A0 @param NumBytes Pointer to a UINTN. At entry, *NumBytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 contains the total= size of the buffer. At > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 exit, *NumBytes co= ntains the total number of > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 bytes read. > > + > > +=A0 @param Buffer=A0=A0 Pointer to a caller-allocated buffer that will > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 be used to hold th= e data that is read. > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0=A0=A0 The firmware volume wa= s read successfully, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 and contents are in Buffer. > > + > > +=A0 @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 boundary. On output, NumBytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 contains the total number of bytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 returned in Buffer. > > + > > +=A0 @retval EFI_ACCESS_DENIED=A0=A0 The firmware volume is in the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 ReadDisabled state. > > + > > +=A0 @retval EFI_DEVICE_ERROR=A0=A0=A0 The block device is not > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 functioning correctly and could > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 not be read. > I think one new line should be enough. And would it be possible to align=20 the return codes comments ? > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbRead ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 EFI_LBA=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lba, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 UINTN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Offset, > > +=A0 IN OUT=A0=A0=A0 UINTN *NumBytes, > > +=A0 IN OUT=A0=A0=A0 UINT8=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 *Buffer > > +=A0 ) > > +{ > > +=A0 EFI_STATUS=A0=A0 Status; > > +=A0 MEM_INSTANCE *Instance; > > +=A0 VOID=A0=A0=A0=A0=A0=A0=A0=A0 *Base; > > + > > +=A0 Status =3D EFI_SUCCESS; > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (This); > > +=A0 if (!Instance->Initialized) { > > +=A0=A0=A0 Status =3D Instance->Initialize (Instance); > > +=A0=A0=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0=A0=A0 return Status; > > +=A0=A0=A0 } > > +=A0 } > > + > > +=A0 Base =3D (VOID *)Instance->MemBaseAddress + (Lba *=20 > Instance->BlockSize) + Offset; > > +=A0 // We could read the data from the RPMB instead of memory > > +=A0 // The 2 copies should already be identical > > +=A0 // Copy from memory image > > +=A0 CopyMem (Buffer, Base, *NumBytes); > > + > > +=A0 return Status; > > +} > > + > > +/** > > +=A0 Writes the specified number of bytes from the input buffer to the=20 > block. > > + > > +=A0 The Write() function writes the specified number of bytes from > > +=A0 the provided buffer to the specified block and offset. If the > > +=A0 firmware volume is sticky write, the caller must ensure that > > +=A0 all the bits of the specified range to write are in the > > +=A0 EFI_FVB_ERASE_POLARITY state before calling the Write() > > +=A0 function, or else the result will be unpredictable. This > > +=A0 unpredictability arises because, for a sticky-write firmware > > +=A0 volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY > > +=A0 state but cannot flip it back again.=A0 Before calling the > > +=A0 Write() function,=A0 it is recommended for the caller to first cal= l > > +=A0 the EraseBlocks() function to erase the specified block to > > +=A0 write. A block erase cycle will transition bits from the > > +=A0 (NOT)EFI_FVB_ERASE_POLARITY state back to the > > +=A0 EFI_FVB_ERASE_POLARITY state. Implementations should be > > +=A0 mindful that the firmware volume might be in the WriteDisabled > > +=A0 state. If it is in this state, the Write() function must > > +=A0 return the status code EFI_ACCESS_DENIED without modifying the > > +=A0 contents of the firmware volume. The Write() function must > > +=A0 also prevent spanning block boundaries. If a write is > > +=A0 requested that spans a block boundary, the write must store up > > +=A0 to the boundary but not beyond. The output parameter NumBytes > > +=A0 must be set to correctly indicate the number of bytes actually > > +=A0 written. The caller must be aware that a write may be > > +=A0 partially completed. All writes, partial or otherwise, must be > > +=A0 fully flushed to the hardware before the Write() service > > +=A0 returns. > > + > > +=A0 @param This=A0=A0=A0=A0 Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PR= OTOCOL=20 > instance. > > + > > +=A0 @param Lba=A0=A0=A0=A0=A0 The starting logical block index to writ= e to. > > + > > +=A0 @param Offset=A0=A0 Offset into the block at which to begin writin= g. > > + > > +=A0 @param NumBytes The pointer to a UINTN. At entry, *NumBytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 contains the total= size of the buffer. At > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 exit, *NumBytes co= ntains the total number of > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 bytes actually wri= tten. > > + > > +=A0 @param Buffer=A0=A0 The pointer to a caller-allocated buffer that > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 contains the sourc= e for the write. > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0=A0=A0 The firmware volume wa= s written=20 > successfully. > > + > > +=A0 @retval EFI_BAD_BUFFER_SIZE The write was attempted across an > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 LBA boundary. On output, NumBytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 contains the total number of bytes > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 actually written. > > + > > +=A0 @retval EFI_ACCESS_DENIED=A0=A0 The firmware volume is in the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 WriteDisabled state. > > + > > +=A0 @retval EFI_DEVICE_ERROR=A0=A0=A0 The block device is malfunctioni= ng > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 and could not be written. > > + > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbWrite ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 EFI_LBA=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Lba, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 UINTN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Offset, > > +=A0 IN OUT=A0=A0=A0 UINTN *NumBytes, > > +=A0 IN=A0=A0=A0=A0=A0=A0=A0 UINT8=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 *Buffer > > +=A0 ) > > +{ > > +=A0 MEM_INSTANCE *Instance; > > +=A0 EFI_STATUS=A0=A0 Status; > > +=A0 VOID=A0=A0=A0=A0=A0=A0=A0=A0 *Base; > > + > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (This); > > +=A0 if (!Instance->Initialized) { > > +=A0=A0=A0 Status =3D Instance->Initialize (Instance); > > +=A0=A0=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0=A0=A0 return Status; > > +=A0=A0=A0 } > > +=A0 } > > +=A0 Base =3D (VOID *)Instance->MemBaseAddress + Lba * Instance->BlockS= ize=20 > + Offset; > > +=A0 Status =3D ReadWriteRpmb ( > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 SP_SVC_RPMB_WRITE, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (UINTN)Buffer, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 *NumBytes, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (Lba * Instance->BlockSize) + Off= set > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > +=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0 return Status; > > +=A0 } > > + > > +=A0 // Update the memory copy > > +=A0 CopyMem (Base, Buffer, *NumBytes); > > + > > +=A0 return Status; > > +} > > + > > +/** > > +=A0 Erases and initializes a firmware volume block. > > + > > +=A0 The EraseBlocks() function erases one or more blocks as denoted > > +=A0 by the variable argument list. The entire parameter list of > > +=A0 blocks must be verified before erasing any blocks. If a block is > > +=A0 requested that does not exist within the associated firmware > > +=A0 volume (it has a larger index than the last block of the > > +=A0 firmware volume), the EraseBlocks() function must return the > > +=A0 status code EFI_INVALID_PARAMETER without modifying the contents > > +=A0 of the firmware volume. Implementations should be mindful that > > +=A0 the firmware volume might be in the WriteDisabled state. If it > > +=A0 is in this state, the EraseBlocks() function must return the > > +=A0 status code EFI_ACCESS_DENIED without modifying the contents of > > +=A0 the firmware volume. All calls to EraseBlocks() must be fully > > +=A0 flushed to the hardware before the EraseBlocks() service > > +=A0 returns. > > + > > +=A0 @param This=A0=A0 Indicates the EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 instance. > > + > > +=A0 @param ...=A0=A0=A0 The variable argument list is a list of tuples= . > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Each tuple describes a r= ange of LBAs to erase > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 and consists of the foll= owing: > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 - An EFI_LBA that indica= tes the starting LBA > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 - A UINTN that indicates= the number of blocks to > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 erase. > > + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 The list is terminated w= ith an > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_LBA_LIST_TERMINATOR.= For example, the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 following indicates that= two ranges of blocks > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (5-7 and 10-11) are to b= e erased: EraseBlocks > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (This, 5, 3, 10, 2, EFI_= LBA_LIST_TERMINATOR); > > + > > +=A0 @retval EFI_SUCCESS The erase request successfully > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 comple= ted. > > + > > +=A0 @retval EFI_ACCESS_DENIED=A0=A0 The firmware volume is in the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 WriteDisabled state. > > +=A0 @retval EFI_DEVICE_ERROR=A0 The block device is not functioning > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 correctly and could not be written. > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 The firmware device may have been > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 partially erased. > > +=A0 @retval EFI_INVALID_PARAMETER One or more of the LBAs listed > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 in the variable argument list do > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 not exist in the firmware volume. > > + > > +**/ > > +STATIC > > +EFI_STATUS > > +OpTeeRpmbFvbErase ( > > +=A0 IN CONST=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, > > +=A0 ... > > +=A0 ) > > +{ > > +=A0 MEM_INSTANCE *Instance; > > +=A0 UINTN=A0=A0 NumBytes; > > +=A0 UINTN=A0=A0 NumLba; > > +=A0 EFI_LBA Start; > > +=A0 VOID=A0=A0=A0 *Base; > > +=A0 VOID=A0=A0=A0 *Buf; > > +=A0 VA_LIST Args; > > +=A0 EFI_STATUS Status; > > + > > +=A0 Instance =3D INSTANCE_FROM_FVB_THIS (This); > > + > > +=A0 VA_START (Args, This); > > +=A0 for (Start =3D VA_ARG (Args, EFI_LBA); > > +=A0=A0=A0=A0=A0=A0 Start !=3D EFI_LBA_LIST_TERMINATOR; > > +=A0=A0=A0=A0=A0=A0 Start =3D VA_ARG (Args, EFI_LBA)) { > > +=A0=A0=A0 NumLba =3D VA_ARG (Args, UINTN); > > +=A0=A0=A0 if (NumLba =3D=3D 0 || Start + NumLba > Instance->NBlocks) { > > +=A0=A0=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0=A0=A0 } > > +=A0=A0=A0 NumBytes =3D NumLba * Instance->BlockSize; > > +=A0=A0=A0 Base =3D (VOID *)Instance->MemBaseAddress + Start *=20 > Instance->BlockSize; > > +=A0=A0=A0 Buf =3D AllocatePool (NumLba * Instance->BlockSize); > > +=A0=A0=A0 if (Buf =3D=3D NULL) { > > +=A0=A0=A0=A0=A0 return EFI_DEVICE_ERROR; > > +=A0=A0=A0 } > > +=A0=A0=A0 SetMem64 (Buf, NumLba * Instance->BlockSize, ~0UL); > > +=A0=A0=A0 // Write the device > > +=A0=A0=A0 Status =3D ReadWriteRpmb ( > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 SP_SVC_RPMB_WRITE, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (UINTN)Buf, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 NumBytes, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Start * Instance->BlockSize > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > +=A0=A0=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0=A0=A0 return Status; > > +=A0=A0=A0 } > > +=A0=A0=A0 // Update the in memory copy > > +=A0=A0=A0 SetMem64 (Base, NumLba * Instance->BlockSize, ~0UL); > > +=A0=A0=A0 FreePool (Buf); > > +=A0 } > > + > > +=A0 VA_END (Args); > > + > > +=A0 return EFI_SUCCESS; > > +} > > + > > +/** > > +=A0 Since we use a memory backed storage we need to restore the RPMB=20 > contents > > +=A0 into memory before we register the Fvb protocol. > > + > > +=A0 @param Instance Address to copy flash contents to > > +**/ > > +STATIC > > +VOID > > +ReadEntireFlash ( > > +=A0 MEM_INSTANCE *Instance > > + ) > > +{ > > +=A0 UINTN ReadAddr; > > +=A0 UINTN StorageFtwWorkingSize; > > +=A0 UINTN StorageVariableSize; > > +=A0 UINTN StorageFtwSpareSize; > > + > > +=A0 StorageFtwWorkingSize =3D PcdGet32(PcdFlashNvStorageFtwWorkingSize= ); > > +=A0 StorageVariableSize=A0=A0 =3D PcdGet32(PcdFlashNvStorageVariableSi= ze); > > +=A0 StorageFtwSpareSize=A0=A0 =3D PcdGet32(PcdFlashNvStorageFtwSpareSi= ze); > > + > > +=A0 ReadAddr =3D Instance->MemBaseAddress; > > +=A0 // There's no need to check if the read failed here. The upper EDK= 2=20 > layers > > +=A0 // will initialize the flash correctly if the in-memory copy is wr= ong > > +=A0 ReadWriteRpmb ( ReadWriteRpmb() returns an error code, I think we should return it aswell= . > > +=A0=A0=A0 SP_SVC_RPMB_READ, > > +=A0=A0=A0 ReadAddr, > > +=A0=A0=A0 StorageVariableSize + StorageFtwWorkingSize + StorageFtwSpar= eSize, > > +=A0=A0=A0 0 > > +=A0=A0=A0 ); > > +} > > + > > +/** > > +=A0 Validate the firmware volume header. > > + > > +=A0 @param FwVolHeader Pointer to the firmware volume header for the R= PMB > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 The firmware vol= ume header is correct > > +=A0 @retval EFI_NOT_FOUND=A0=A0=A0=A0=A0=A0=A0=A0 No header present > > +=A0 @retval EFI_VOLUME_CORRUPTED=A0 The firmware volume header CRC was= =20 > invalid > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 or either one of GUID's, Signature=20 > and header > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 length was invalid > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +ValidateFvHeader ( > > +=A0 IN EFI_FIRMWARE_VOLUME_HEADER=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 *Fw= VolHeader > > +=A0 ) > > +{ > > +=A0 UINT16=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 Checksum; > > +=A0 VARIABLE_STORE_HEADER=A0=A0=A0=A0=A0=A0 *VariableStoreHeader; > > +=A0 UINTN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 VariableStoreLength; > > +=A0 UINTN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 FvLength; > > + > > +=A0 FvLength =3D PcdGet32(PcdFlashNvStorageVariableSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageFtwWork= ingSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageFtwSpar= eSize); > > + > > +=A0 // Verify the header revision, header signature, length > > +=A0 // Length of FvBlock cannot be 2**64-1 > > +=A0 // HeaderLength cannot be an odd number > > +=A0 // > > +=A0 if (=A0=A0 (FwVolHeader->Revision=A0 !=3D EFI_FVH_REVISION) > > +=A0=A0=A0=A0=A0 || (FwVolHeader->Signature !=3D EFI_FVH_SIGNATURE) > > +=A0=A0=A0=A0=A0 || (FwVolHeader->FvLength=A0 !=3D FvLength) > > +=A0=A0=A0=A0=A0 ) > > +=A0 { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: No Firmware Volume header present\n= ", > > +=A0=A0=A0=A0=A0 __FUNCTION__)); > > +=A0=A0=A0 return EFI_NOT_FOUND; > > +=A0 } > > + > > +=A0 // Check the Firmware Volume Guid > > +=A0 if (!CompareGuid (&FwVolHeader->FileSystemGuid,=20 > &gEfiSystemNvDataFvGuid)) { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Firmware Volume Guid non-compatible= \n", > > +=A0=A0=A0=A0=A0 __FUNCTION__)); > > +=A0=A0=A0 return EFI_VOLUME_CORRUPTED; > > +=A0 } > > + > > +=A0 // Verify the header checksum > > +=A0 Checksum =3D CalculateSum16((UINT16*)FwVolHeader,=20 > FwVolHeader->HeaderLength); > > +=A0 if (Checksum !=3D 0) { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: FV checksum is invalid (Checksum:0x= %X)\n", > > +=A0=A0=A0=A0=A0 __FUNCTION__, Checksum)); > > +=A0=A0=A0 return EFI_VOLUME_CORRUPTED; > > +=A0 } > > + > > +=A0 VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeade= r + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= FwVolHeader->HeaderLength); > > + > > +=A0 // Check the Variable Store Guid > > +=A0 if (!CompareGuid (&VariableStoreHeader->Signature,=20 > &gEfiVariableGuid) && > > +=A0=A0=A0=A0=A0 !CompareGuid (&VariableStoreHeader->Signature,=20 > &gEfiAuthenticatedVariableGuid)) { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Variable Store Guid non-compatible\= n",=20 > __FUNCTION__)); > > +=A0=A0=A0 return EFI_VOLUME_CORRUPTED; > > +=A0 } > > + > > +=A0 VariableStoreLength =3D PcdGet32 (PcdFlashNvStorageVariableSize) - > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = FwVolHeader->HeaderLength; > > +=A0 if (VariableStoreHeader->Size !=3D VariableStoreLength) { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Variable Store Length does not matc= h\n", > > +=A0=A0=A0=A0=A0 __FUNCTION__)); > > +=A0=A0=A0 return EFI_VOLUME_CORRUPTED; > > +=A0 } > > + > > +=A0 return EFI_SUCCESS; > > + > > +} > > + > > +/** > > +=A0 Initialize Fvb and variable storage headers for the RPMB storage. > > + > > +=A0 @param Instance=A0=A0 MEM_INSTANCE pointer describing the device a= nd the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Firmware Blo= ck Protocol > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_SUCCESS read/write ok > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_UNSUPPORTED SVC to op-te= e not supported > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_INVALID_PARAMETER SVC to= op-tee had an=20 > invalid param > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_ACCESS_DENIED SVC to op-= tee was denied > > + > > +=A0 @retval=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_OUT_OF_RESOURCES op-tee = out of memory > > +**/ > > +STATIC > > +EFI_STATUS > > +InitializeFvAndVariableStoreHeaders ( > > +=A0 MEM_INSTANCE *Instance > > +=A0 ) > > +{ > > +=A0 EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader; > > +=A0 VARIABLE_STORE_HEADER=A0=A0=A0=A0=A0 *VariableStoreHeader; > > +=A0 EFI_STATUS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Status; > > +=A0 UINTN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= HeadersLength; > > +=A0 VOID*=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= Headers; > > + > > +=A0 HeadersLength =3D sizeof (EFI_FIRMWARE_VOLUME_HEADER) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 sizeof (EFI_FV_BLO= CK_MAP_ENTRY) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 sizeof (VARIABLE_S= TORE_HEADER); > > +=A0 Headers =3D AllocateZeroPool (HeadersLength); > > +=A0 if (Headers =3D=3D NULL) { > > +=A0=A0=A0 return EFI_OUT_OF_RESOURCES; > > +=A0 } > > + > > +=A0 // > > +=A0 // EFI_FIRMWARE_VOLUME_HEADER > > +=A0 // > > +=A0 FirmwareVolumeHeader =3D (EFI_FIRMWARE_VOLUME_HEADER*)Headers; > > +=A0 CopyGuid (&FirmwareVolumeHeader->FileSystemGuid,=20 > &gEfiSystemNvDataFvGuid); > > +=A0 FirmwareVolumeHeader->FvLength =3D=20 > PcdGet32(PcdFlashNvStorageVariableSize) + > > + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + > > + PcdGet32(PcdFlashNvStorageFtwSpareSize); > > +=A0 FirmwareVolumeHeader->Signature =3D EFI_FVH_SIGNATURE; > > +=A0 FirmwareVolumeHeader->Attributes =3D EFI_FVB2_READ_ENABLED_CAP | > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_FVB2_READ_STATUS | > > + EFI_FVB2_STICKY_WRITE | > > + EFI_FVB2_MEMORY_MAPPED | > > + EFI_FVB2_ERASE_POLARITY | > > + EFI_FVB2_WRITE_STATUS | > > + EFI_FVB2_WRITE_ENABLED_CAP; > > + > > +=A0 FirmwareVolumeHeader->HeaderLength =3D sizeof=20 > (EFI_FIRMWARE_VOLUME_HEADER) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 sizeof (EFI_FV_BLOCK_MAP_ENTRY= ); > > +=A0 FirmwareVolumeHeader->Revision =3D EFI_FVH_REVISION; > > +=A0 FirmwareVolumeHeader->BlockMap[0].NumBlocks =3D Instance->NBlocks; > > +=A0 FirmwareVolumeHeader->BlockMap[0].Length=A0=A0=A0 =3D Instance->Bl= ockSize; > > +=A0 FirmwareVolumeHeader->BlockMap[1].NumBlocks =3D 0; > > +=A0 FirmwareVolumeHeader->BlockMap[1].Length=A0=A0=A0 =3D 0; > > +=A0 FirmwareVolumeHeader->Checksum =3D CalculateCheckSum16 ( > > + (UINT16*)FirmwareVolumeHeader, > > + FirmwareVolumeHeader->HeaderLength > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > + > > +=A0 // > > +=A0 // VARIABLE_STORE_HEADER > > +=A0 // > > +=A0 VariableStoreHeader =3D (VARIABLE_STORE_HEADER*)((UINTN)Headers + > > + FirmwareVolumeHeader->HeaderLength); > > +=A0 CopyGuid (&VariableStoreHeader->Signature,=20 > &gEfiAuthenticatedVariableGuid); > > +=A0 VariableStoreHeader->Size =3D PcdGet32(PcdFlashNvStorageVariableSi= ze) - > > + FirmwareVolumeHeader->HeaderLength; > > +=A0 VariableStoreHeader->Format =3D VARIABLE_STORE_FORMATTED; > > +=A0 VariableStoreHeader->State =3D VARIABLE_STORE_HEALTHY; > > + > > +=A0 Status =3D ReadWriteRpmb (SP_SVC_RPMB_WRITE, (UINTN)Headers,=20 > HeadersLength, 0); > > +=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0 goto Exit; > > +=A0 } > > +=A0 // Install the combined header in memory > > +=A0 CopyMem ((VOID*)Instance->MemBaseAddress, Headers, HeadersLength); > > + > > +Exit: > > +=A0 FreePool (Headers); > > +=A0 return Status; > > +} > > + > > +/** > > +=A0 Initialize the firmware block protocol for the specified memory. > > + > > +=A0 @param Instance=A0=A0 MEM_INSTANCE pointer describing the device a= nd the > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Firmware Blo= ck Protocol > > + > > +=A0 @retval EFI_SUCCESS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Init= ialized successfully or=20 > already initialized > > +=A0 @retval EFI_UNSUPPORTED=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 SVC to op-te= e not supported > > +=A0 @retval EFI_INVALID_PARAMETER=A0=A0=A0=A0 SVC to op-tee had an inv= alid param > > +=A0 @retval EFI_ACCESS_DENIED=A0=A0=A0=A0=A0=A0=A0=A0 SVC to op-tee wa= s denied > > +=A0 @retval EFI_OUT_OF_RESOURCES=A0=A0=A0=A0=A0 op-tee out of memory > > + > > + > > + I think one new line should be enough. > > +**/ > > +STATIC > > +EFI_STATUS > > +EFIAPI > > +FvbInitialize ( > > +=A0 MEM_INSTANCE *Instance > > +=A0 ) > > +{ > > +=A0 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; > > +=A0 EFI_STATUS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Stat= us; > > + > > +=A0 if (Instance->Initialized) { > > +=A0=A0=A0 return EFI_SUCCESS; > > +=A0 } > > + > > +=A0 // FirmwareVolumeHeader->FvLength is declared to have the Variable= area > > +=A0 // AND the FTW working area AND the FTW Spare contiguous. > > +=A0 ASSERT ( > > +=A0=A0=A0 (PcdGet64 (PcdFlashNvStorageVariableBase64) + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageVariableSize)) =3D=3D > > +=A0=A0=A0 PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) > > +=A0=A0=A0 ); > > +=A0 ASSERT ( > > +=A0=A0=A0 (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) =3D=3D > > +=A0=A0=A0 PcdGet64 (PcdFlashNvStorageFtwSpareBase64)); > > + > > +=A0 // Check if the size of the area is at least one block size > > +=A0 ASSERT ( > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageVariableSize) > 0) && > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageVariableSize) / Instance->BlockS= ize > 0) > > +=A0=A0=A0 ); > > +=A0 ASSERT ( > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) && > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / Instance->Bloc= kSize=20 > > 0) > > +=A0=A0=A0 ); > > +=A0 ASSERT ( > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) && > > +=A0=A0=A0 (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / Instance->BlockS= ize > 0) > > +=A0=A0=A0 ); > > + > > +=A0 // Ensure the Variable areas are aligned on block size boundaries > > +=A0 ASSERT ((PcdGet64 (PcdFlashNvStorageVariableBase64) %=20 > Instance->BlockSize) =3D=3D 0); > > +=A0 ASSERT ((PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) %=20 > Instance->BlockSize) =3D=3D 0); > > +=A0 ASSERT ((PcdGet64 (PcdFlashNvStorageFtwSpareBase64) %=20 > Instance->BlockSize) =3D=3D 0); > > + > > +=A0 // Read the file from disk and copy it to memory > > +=A0 ReadEntireFlash (Instance); > > + > > +=A0 FwVolHeader =3D (EFI_FIRMWARE_VOLUME_HEADER *)Instance->MemBaseAdd= ress; > > +=A0 Status =3D ValidateFvHeader (FwVolHeader); > > +=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0 // There is no valid header, so time to install one. > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n",=20 > __FUNCTION__)); > > + > > +=A0=A0=A0 // Reset memory > > +=A0=A0=A0 SetMem64 ((VOID *)Instance->MemBaseAddress, Instance->NBlock= s *=20 > Instance->BlockSize, ~0UL); > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Erasing Flash.\n", __FUNCTION__)); > > +=A0=A0=A0 Status =3D ReadWriteRpmb ( > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 SP_SVC_RPMB_WRITE, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Instance->MemBaseAddress, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageV= ariableSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageF= twWorkingSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageF= twSpareSize), > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0 > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > +=A0=A0=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0=A0=A0 return Status; > > +=A0=A0=A0 } > > +=A0=A0=A0 // Install all appropriate headers > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this=20 > volume.\n", > > +=A0=A0=A0=A0=A0 __FUNCTION__)); > > +=A0=A0=A0 Status =3D InitializeFvAndVariableStoreHeaders (Instance); > > +=A0=A0=A0 if (EFI_ERROR (Status)) { > > +=A0=A0=A0=A0=A0 return Status; > > +=A0=A0=A0 } > > +=A0 } else { > > +=A0=A0=A0 DEBUG ((DEBUG_INFO, "%a: Found valid FVB Header.\n", __FUNCT= ION__)); > > +=A0 } > > +=A0 Instance->Initialized =3D TRUE; > > + > > +=A0 return Status; > > +} > > + > > +/** > > +=A0 Since the RPMB is not byte addressable we need to allocate memory > > +=A0 and sync that on reads/writes. Initialize the memory and install t= he > > +=A0 Fvb protocol. > > + > > +=A0 @param ImageHandle The EFI image handle > > +=A0 @param SystemTable MM system table > > + > > +=A0 @retval EFI_SUCCESS Protocol installed > > + > > +=A0 @retval EFI_INVALID_PARAMETER Invalid Pcd values specified > > + > > +=A0 @retval EFI_OUT_OF_RESOURCES=A0 Can't allocate necessary memory > > +**/ > > +EFI_STATUS > > +EFIAPI > > +OpTeeRpmbFvbInit ( > > +=A0 IN EFI_HANDLE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ImageHandle, > > +=A0 IN EFI_MM_SYSTEM_TABLE=A0 *SystemTable > > +=A0 ) > > +{ > > +=A0 EFI_STATUS=A0=A0 Status; > > +=A0 VOID=A0=A0=A0=A0=A0=A0=A0=A0 *Addr; > > +=A0 UINTN=A0=A0=A0=A0=A0=A0=A0 FvLength; > > +=A0 UINTN=A0=A0=A0=A0=A0=A0=A0 NBlocks; > > + > > +=A0 FvLength =3D PcdGet32(PcdFlashNvStorageVariableSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageFtwWork= ingSize) + > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 PcdGet32(PcdFlashNvStorageFtwSpar= eSize); > > + > > +=A0 NBlocks =3D EFI_SIZE_TO_PAGES (ALIGN_VARIABLE (FvLength)); > > +=A0 Addr =3D AllocatePages (NBlocks); > > +=A0 if (Addr =3D=3D NULL) { > > +=A0=A0=A0 ASSERT (0); > > +=A0=A0=A0 return EFI_OUT_OF_RESOURCES; > > +=A0 } > > + > > +=A0 SetMem (&mInstance, sizeof (mInstance), 0); > > + > > +=A0 mInstance.FvbProtocol.GetPhysicalAddress =3D=20 > OpTeeRpmbFvbGetPhysicalAddress; > > +=A0 mInstance.FvbProtocol.GetAttributes=A0=A0=A0=A0=A0 =3D OpTeeRpmbFv= bGetAttributes; > > +=A0 mInstance.FvbProtocol.SetAttributes=A0=A0=A0=A0=A0 =3D OpTeeRpmbFv= bSetAttributes; > > +=A0 mInstance.FvbProtocol.GetBlockSize=A0=A0=A0=A0=A0=A0 =3D OpTeeRpmb= FvbGetBlockSize; > > +=A0 mInstance.FvbProtocol.EraseBlocks=A0=A0=A0=A0=A0=A0=A0 =3D OpTeeRp= mbFvbErase; > > +=A0 mInstance.FvbProtocol.Write=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D OpTeeRpmbFvbWrite; > > +=A0 mInstance.FvbProtocol.Read=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =3D OpTeeRpmbFvbRead; > > + > > +=A0 mInstance.MemBaseAddress =3D (EFI_PHYSICAL_ADDRESS)Addr; > > +=A0 mInstance.Signature=A0=A0=A0=A0=A0 =3D FLASH_SIGNATURE; > > +=A0 mInstance.Initialize=A0=A0=A0=A0 =3D FvbInitialize; > > +=A0 mInstance.BlockSize=A0=A0=A0=A0=A0 =3D EFI_PAGE_SIZE; > > +=A0 mInstance.NBlocks=A0=A0=A0=A0=A0=A0=A0 =3D NBlocks; > > + > > +=A0 // The Pcd is user defined, so make sure we don't overflow > > +=A0 if (mInstance.MemBaseAddress > MAX_UINT64 - PcdGet32=20 > (PcdFlashNvStorageVariableSize)) { > > +=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0 } > > + > > +=A0 if (mInstance.MemBaseAddress > MAX_UINT64 - PcdGet32=20 > (PcdFlashNvStorageVariableSize) - > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) { > > +=A0=A0=A0 return EFI_INVALID_PARAMETER; > > +=A0 } > > + > > +=A0 // Update the defined PCDs related to Variable Storage > > +=A0 PatchPcdSet64 (PcdFlashNvStorageVariableBase64,=20 > mInstance.MemBaseAddress); > > +=A0 PatchPcdSet64 ( > > +=A0=A0=A0 PcdFlashNvStorageFtwWorkingBase64, > > +=A0=A0=A0 mInstance.MemBaseAddress + PcdGet32 (PcdFlashNvStorageVariab= leSize) > > +=A0=A0=A0 ); > > +=A0 PatchPcdSet64 ( > > +=A0=A0=A0 PcdFlashNvStorageFtwSpareBase64, > > +=A0=A0=A0 mInstance.MemBaseAddress + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageVariableSize) + > > +=A0=A0=A0 PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > > +=A0=A0=A0 ); It seems this part is really similar to what is=20 FixupPcd.c:FixPcdMemory(), maybe this would be worth re-using it. > > + > > +=A0 Status =3D gMmst->MmInstallProtocolInterface ( > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 &mInstance.H= andle, > > + &gEfiSmmFirmwareVolumeBlockProtocolGuid, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 EFI_NATIVE_I= NTERFACE, > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 &mInstance.F= vbProtocol > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 ); > > +=A0 ASSERT_EFI_ERROR (Status); > > + > > +=A0 DEBUG ((DEBUG_INFO, "%a: Register OP-TEE RPMB Fvb\n", __FUNCTION__= )); > > +=A0 DEBUG ((DEBUG_INFO, "%a: Using NV store FV in-memory copy at 0x%lx= \n", > > +=A0=A0=A0 __FUNCTION__, PatchPcdGet64 (PcdFlashNvStorageVariableBase64= ))); > > + > > +=A0 return Status; > > +} > > diff --git a/Drivers/OpTeeRpmb/OpTeeRpmbFvb.h=20 > b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.h > new file mode 100644 > index 000000000000..8305e776dbb6 > --- /dev/null > +++ b/Drivers/OpTeeRpmb/OpTeeRpmbFvb.h > @@ -0,0 +1,52 @@ > +/** @file > > + > > +=A0 Copyright (c) 2020, Linaro Ltd. All rights reserved.
> > +=A0 SPDX-License-Identifier: BSD-2-Clause-Patent > > + > > +**/ > > + > > +#ifndef OPTEE_RPMB_FVB_H_ > > +#define OPTEE_RPMB_FVB_H_ > > + > > +/** > > + Those are not currently defined in any spec, it's an internal > > + contract between OP-TEE and EDK2. > > + For more details check core/arch/arm/include/kernel/stmm_sp.h in OP-T= EE > > +**/ > > +#define SP_SVC_RPMB_READ=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = 0xC4000066 > > +#define SP_SVC_RPMB_WRITE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 0x= C4000067 > > + > > +#define FLASH_SIGNATURE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 SIGNATURE_32(= 'r', 'p', 'm', 'b') > > +#define INSTANCE_FROM_FVB_THIS(a)=A0 CR(a, MEM_INSTANCE, FvbProtocol, = \ > > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 FLASH_SIGNATURE) > > + > > +typedef struct _MEM_INSTANCE=A0=A0=A0=A0=A0=A0=A0=A0 MEM_INSTANCE; > > +typedef EFI_STATUS (*MEM_INITIALIZE) (MEM_INSTANCE* Instance); > > + > > +/** > > +=A0 This struct is used by the RPMB driver. Since the upper EDK2 layer= s > > +=A0 expect byte addressable memory, we allocate a memory area of certa= in > > +=A0 size and sync it to the hardware on reads/writes. > > + > > +=A0 @param[in] Signature=A0=A0=A0=A0=A0=A0=A0 Internal signature used = to discover the=20 > instance > > +=A0 @param[in] Initialize=A0=A0=A0=A0=A0=A0 Function used to initializ= e the instance > > +=A0 @param[in] Initialized=A0=A0=A0=A0=A0 Set to true if initialized > > +=A0 @param[in] FvbProtocol=A0=A0=A0=A0=A0 FVB protocol of the instance > > +=A0 @param[in] Handle=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Handle to install > > +=A0 @param[in] MemBaseAddress=A0=A0 Physical address of the beggining = of=20 > the allocated memory > > +=A0 @param[in] BlockSize=A0=A0=A0=A0=A0=A0=A0 Blocksize > > +=A0 @param[in] NBlocks=A0=A0=A0=A0=A0=A0=A0=A0=A0 Number of allocated = blocks I think that for doxygen, '@param[in]' is more for functions=20 declarations. For structures, it should be as: /** =A0 * This struct is used by the RPMB driver. Since the upper EDK2 layer= s =A0 * expect byte addressable memory, we allocate a memory area of certa= in =A0 * size and sync it to the hardware on reads/writes. **/ struct _MEM_INSTANCE { =A0=A0=A0 ///=A0 Signature=A0=A0=A0=A0=A0=A0=A0 Internal signature used = to discover the instance =A0=A0=A0 UINT32=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Signature; /// Initialize=A0=A0=A0=A0=A0=A0 Function used to initialize the instance =A0=A0=A0 MEM_INITIALIZE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 Initialize; [...] }; Cf:=20 https://edk2-docs.gitbook.io/edk-ii-c-coding-standards-specification/5_so= urce_files/56_declarations_and_types#5-6-3-2-structure-declaration-with-f= orward-reference-or-self-reference > > +**/ > > +struct _MEM_INSTANCE > > +{ > > +=A0=A0=A0 UINT32=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Signature; > > +=A0=A0=A0 MEM_INITIALIZE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 Initialize; > > +=A0=A0=A0 BOOLEAN=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 Initialized; > > +=A0=A0=A0 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL=A0 FvbProtocol; > > +=A0=A0=A0 EFI_HANDLE=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 Handle; > > +=A0=A0=A0 EFI_PHYSICAL_ADDRESS=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 MemBaseAddress; > > +=A0=A0=A0 UINT16=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 BlockSize; > > +=A0=A0=A0 UINT16=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 NBlocks; > > +}; > > + > > +#endif > > --=20 > 2.30.0 > > > > -=3D-=3D-=3D-=3D-=3D-=3D > Groups.io Links: You receive all messages sent to this group. > View/Reply Online (#71651):=20 > https://edk2.groups.io/g/devel/message/71651=20 > > Mute This Topic: https://groups.io/mt/80588994/1821310=20 > > Group Owner: devel+owner@edk2.groups.io > Unsubscribe: https://edk2.groups.io/g/devel/unsub=20 > [pierre.gondois@arm.com] > -=3D-=3D-=3D-=3D-=3D-=3D > >