Hi Ilias,
Here is the rest of the review. Sorry to do it in 2 times.
Regards,
Pierre
+/**
+ Fixup the Pcd values for variable storage
+
+ Since the upper layers of EDK2 expect a memory mapped interface and
we can't
+ offer that from an RPMB, the driver allocates memory on init and
passes that
+ on the upper layers. Since the memory is dynamically allocated and
we can't set the
+ PCD is StMM context, we need to patch it correctly on each access
+
+ @retval EFI_SUCCESS Protocol was found and PCDs patched up
The error codes are missing.
+
+ **/
+EFI_STATUS
+EFIAPI
+FixPcdMemory (
+ VOID
+ )
+{
+ EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol;
+ MEM_INSTANCE *Instance;
+ EFI_STATUS Status;
+
+ //
+ // Locate SmmFirmwareVolumeBlockProtocol
+ //
+ Status = gMmst->MmLocateProtocol (
+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+ NULL,
+ (VOID **) &FvbProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Instance = INSTANCE_FROM_FVB_THIS (FvbProtocol);
+ // The Pcd is user defined, so make sure we don't overflow
+ if (Instance->MemBaseAddress > MAX_UINT64 - PcdGet32
(PcdFlashNvStorageVariableSize)) {
I think this can be removed since the next condition is more strict.
+ return EFI_INVALID_PARAMETER;
+ }
+
[...]
+STATIC
+EFI_STATUS
+ReadWriteRpmb (
+ UINTN SvcAct,
+ UINTN Addr,
+ UINTN NumBytes,
+ UINTN Offset
+ )
+{
+ ARM_SVC_ARGS SvcArgs;
+ EFI_STATUS Status;
+
+ ZeroMem (&SvcArgs, sizeof (SvcArgs));
+
+ SvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;
If this is an FFA call, is it possible to:
- put a reference in the header to the spec (it should be similar to
the one at
edk2/ArmPkg/Library/StandaloneMmMmuLib/AArch64/ArmMmuStandaloneMmLib.c)
- check the return status of the SVC call against the ones available
at edk2/ArmPkg/Include/IndustryStandard/ArmFfaSvc.h
- if possible, remove the dependency to <IndustryStandard/ArmMmSvc.h>
+ SvcArgs.Arg1 = mStorageId;
+ SvcArgs.Arg2 = 0;
+ SvcArgs.Arg3 = SvcAct;
+ SvcArgs.Arg4 = Addr;
+ SvcArgs.Arg5 = NumBytes;
+ SvcArgs.Arg6 = Offset;
+
+ ArmCallSvc (&SvcArgs);
+ if (SvcArgs.Arg3) {
+ DEBUG ((DEBUG_ERROR, "%a: Svc Call 0x%08x Addr: 0x%08x len: 0x%x
Offset: 0x%x failed with 0x%x\n",
+ __func__, SvcAct, Addr, NumBytes, Offset, SvcArgs.Arg3));
+ }
+
+ switch (SvcArgs.Arg3) {
+ case ARM_SVC_SPM_RET_SUCCESS:
+ Status = EFI_SUCCESS;
+ break;
+
+ case ARM_SVC_SPM_RET_NOT_SUPPORTED:
+ Status = EFI_UNSUPPORTED;
+ break;
+
+ case ARM_SVC_SPM_RET_INVALID_PARAMS:
+ Status = EFI_INVALID_PARAMETER;
+ break;
+
+ case ARM_SVC_SPM_RET_DENIED:
+ Status = EFI_ACCESS_DENIED;
+ break;
+
+ case ARM_SVC_SPM_RET_NO_MEMORY:
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+
+ default:
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ return Status;
+}
[...]
+STATIC
+EFI_STATUS
+EFIAPI
+ValidateFvHeader (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
+{
+ UINT16 Checksum;
+ VARIABLE_STORE_HEADER *VariableStoreHeader;
+ UINTN VariableStoreLength;
+ UINTN FvLength;
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ // Verify the header revision, header signature, length
+ // Length of FvBlock cannot be 2**64-1
+ // HeaderLength cannot be an odd number
+ //
+ if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
+ || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
+ || (FwVolHeader->FvLength != FvLength)
+ )
could be on the same line -> ') {'
+ {
+ DEBUG ((DEBUG_INFO, "%a: No Firmware Volume header present\n",
+ __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+
+ // Check the Firmware Volume Guid
+ if (!CompareGuid (&FwVolHeader->FileSystemGuid,
&gEfiSystemNvDataFvGuid)) {
+ DEBUG ((DEBUG_INFO, "%a: Firmware Volume Guid non-compatible\n",
+ __FUNCTION__));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ // Verify the header checksum
+ Checksum = CalculateSum16((UINT16*)FwVolHeader,
FwVolHeader->HeaderLength);
+ if (Checksum != 0) {
+ DEBUG ((DEBUG_INFO, "%a: FV checksum is invalid (Checksum:0x%X)\n",
+ __FUNCTION__, Checksum));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader +
+ FwVolHeader->HeaderLength);
+
+ // Check the Variable Store Guid
+ if (!CompareGuid (&VariableStoreHeader->Signature,
&gEfiVariableGuid) &&
+ !CompareGuid (&VariableStoreHeader->Signature,
&gEfiAuthenticatedVariableGuid)) {
+ DEBUG ((DEBUG_INFO, "%a: Variable Store Guid non-compatible\n",
__FUNCTION__));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) -
+ FwVolHeader->HeaderLength;
+ if (VariableStoreHeader->Size != VariableStoreLength) {
+ DEBUG ((DEBUG_INFO, "%a: Variable Store Length does not match\n",
+ __FUNCTION__));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ return EFI_SUCCESS;
empty line, could be removed
+
+}
+
[...]
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FvbInitialize (
+ MEM_INSTANCE *Instance
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
+ EFI_STATUS Status;
+
+ if (Instance->Initialized) {
+ return EFI_SUCCESS;
+ }
+
+ // FirmwareVolumeHeader->FvLength is declared to have the Variable area
+ // AND the FTW working area AND the FTW Spare contiguous.
+ ASSERT (
+ (PcdGet64 (PcdFlashNvStorageVariableBase64) +
+ PcdGet32 (PcdFlashNvStorageVariableSize)) ==
+ PcdGet64 (PcdFlashNvStorageFtwWorkingBase64)
+ );
+ ASSERT (
+ (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) +
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) ==
+ PcdGet64 (PcdFlashNvStorageFtwSpareBase64));
+
+ // Check if the size of the area is at least one block size
+ ASSERT (
+ (PcdGet32 (PcdFlashNvStorageVariableSize) > 0) &&
I think the first check (Size > 0) is redundant with the second one
(Size > BlockSize).
+ (PcdGet32 (PcdFlashNvStorageVariableSize) / Instance->BlockSize > 0)
+ );
+ ASSERT (
+ (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) > 0) &&
+ (PcdGet32 (PcdFlashNvStorageFtwWorkingSize) / Instance->BlockSize
> 0)
+ );
+ ASSERT (
+ (PcdGet32 (PcdFlashNvStorageFtwSpareSize) > 0) &&
+ (PcdGet32 (PcdFlashNvStorageFtwSpareSize) / Instance->BlockSize > 0)
+ );
+
+ // Ensure the Variable areas are aligned on block size boundaries
+ ASSERT ((PcdGet64 (PcdFlashNvStorageVariableBase64) %
Instance->BlockSize) == 0);
+ ASSERT ((PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) %
Instance->BlockSize) == 0);
+ ASSERT ((PcdGet64 (PcdFlashNvStorageFtwSpareBase64) %
Instance->BlockSize) == 0);
+
+ // Read the file from disk and copy it to memory
+ ReadEntireFlash (Instance);
+
+ FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->MemBaseAddress;
+ Status = ValidateFvHeader (FwVolHeader);
+ if (EFI_ERROR (Status)) {
+ // There is no valid header, so time to install one.
+ DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n",
__FUNCTION__));
+
+ // Reset memory
+ SetMem64 ((VOID *)Instance->MemBaseAddress, Instance->NBlocks *
Instance->BlockSize, ~0UL);
+ DEBUG ((DEBUG_INFO, "%a: Erasing Flash.\n", __FUNCTION__));
+ Status = ReadWriteRpmb (
+ SP_SVC_RPMB_WRITE,
+ Instance->MemBaseAddress,
+ PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize),
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ // Install all appropriate headers
+ DEBUG ((DEBUG_INFO, "%a: Installing a correct one for this
volume.\n",
+ __FUNCTION__));
+ Status = InitializeFvAndVariableStoreHeaders (Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: Found valid FVB Header.\n", __FUNCTION__));
+ }
+ Instance->Initialized = TRUE;
+
+ return Status;
+}
+
+/**
+ Since the RPMB is not byte addressable we need to allocate memory
+ and sync that on reads/writes. Initialize the memory and install the
+ Fvb protocol.
+
+ @param ImageHandle The EFI image handle
+ @param SystemTable MM system table
+
+ @retval EFI_SUCCESS Protocol installed
+
+ @retval EFI_INVALID_PARAMETER Invalid Pcd values specified
+
+ @retval EFI_OUT_OF_RESOURCES Can't allocate necessary memory
+**/
+EFI_STATUS
+EFIAPI
+OpTeeRpmbFvbInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ VOID *Addr;
+ UINTN FvLength;
+ UINTN NBlocks;
+
+ FvLength = PcdGet32(PcdFlashNvStorageVariableSize) +
+ PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
+ PcdGet32(PcdFlashNvStorageFtwSpareSize);
+
+ NBlocks = EFI_SIZE_TO_PAGES (ALIGN_VARIABLE (FvLength));
+ Addr = AllocatePages (NBlocks);
+ if (Addr == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SetMem (&mInstance, sizeof (mInstance), 0);
NIT: you can use ZeroMem()
+
+ mInstance.FvbProtocol.GetPhysicalAddress =
OpTeeRpmbFvbGetPhysicalAddress;
+ mInstance.FvbProtocol.GetAttributes = OpTeeRpmbFvbGetAttributes;
+ mInstance.FvbProtocol.SetAttributes = OpTeeRpmbFvbSetAttributes;
+ mInstance.FvbProtocol.GetBlockSize = OpTeeRpmbFvbGetBlockSize;
+ mInstance.FvbProtocol.EraseBlocks = OpTeeRpmbFvbErase;
+ mInstance.FvbProtocol.Write = OpTeeRpmbFvbWrite;
+ mInstance.FvbProtocol.Read = OpTeeRpmbFvbRead;
+
+ mInstance.MemBaseAddress = (EFI_PHYSICAL_ADDRESS)Addr;
+ mInstance.Signature = FLASH_SIGNATURE;
+ mInstance.Initialize = FvbInitialize;
+ mInstance.BlockSize = EFI_PAGE_SIZE;
+ mInstance.NBlocks = NBlocks;
+
+ // The Pcd is user defined, so make sure we don't overflow
+ if (mInstance.MemBaseAddress > MAX_UINT64 - PcdGet32
(PcdFlashNvStorageVariableSize)) {
I don't think this is necessary to do any check here since the memory
has just been allocated with the right size.
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (mInstance.MemBaseAddress > MAX_UINT64 - PcdGet32
(PcdFlashNvStorageVariableSize) -
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the defined PCDs related to Variable Storage
+ PatchPcdSet64 (PcdFlashNvStorageVariableBase64,
mInstance.MemBaseAddress);
+ PatchPcdSet64 (
+ PcdFlashNvStorageFtwWorkingBase64,
+ mInstance.MemBaseAddress + PcdGet32 (PcdFlashNvStorageVariableSize)
+ );
+ PatchPcdSet64 (
+ PcdFlashNvStorageFtwSpareBase64,
+ mInstance.MemBaseAddress +
+ PcdGet32 (PcdFlashNvStorageVariableSize) +
+ PcdGet32 (PcdFlashNvStorageFtwWorkingSize)
+ );
Do we actually need to set these PCDs ? If the PCDs are persistent, we
should not need to patch them in FixupPcd.c. FvbInitialize() is using
them, but it is not called from OpTeeRpmbFvbInit().
+
+ Status = gMmst->MmInstallProtocolInterface (
+ &mInstance.Handle,
+ &gEfiSmmFirmwareVolumeBlockProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mInstance.FvbProtocol
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "%a: Register OP-TEE RPMB Fvb\n", __FUNCTION__));
+ DEBUG ((DEBUG_INFO, "%a: Using NV store FV in-memory copy at 0x%lx\n",
+ __FUNCTION__, PatchPcdGet64 (PcdFlashNvStorageVariableBase64)));
+
+ return Status;
+}
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#72505): https://edk2.groups.io/g/devel/message/72505
Mute This Topic: https://groups.io/mt/80588994/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-