X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=ArmPlatformPkg%2FDrivers%2FNorFlashDxe%2FNorFlashFvbDxe.c;h=bf420853b0a173d96cbb37a163f11ae2fac2eec2;hp=b9230c1ee007c8f147bbb86b565e1b5b8a40b65e;hb=452a9ee1a637baf7894943c9f850175f679f8ce6;hpb=2dff0c1ab2be86979ccb99db8b17bd3347b98b59 diff --git a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c index b9230c1ee0..bf420853b0 100644 --- a/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c +++ b/ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashFvbDxe.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,8 @@ #include "NorFlashDxe.h" +STATIC EFI_EVENT mFvbVirtualAddrChangeEvent; +STATIC UINTN mFlashNvStorageVariableBase; /// /// The Firmware Volume Block Protocol is the low-level interface @@ -301,7 +304,7 @@ FvbGetPhysicalAddress ( ASSERT(Address != NULL); - *Address = PcdGet32 (PcdFlashNvStorageVariableBase); + *Address = mFlashNvStorageVariableBase; return EFI_SUCCESS; } @@ -414,7 +417,6 @@ FvbRead ( IN OUT UINT8 *Buffer ) { - EFI_STATUS Status; EFI_STATUS TempStatus; UINTN BlockSize; NOR_FLASH_INSTANCE *Instance; @@ -427,8 +429,7 @@ FvbRead ( Instance->Initialize(Instance); } - Status = EFI_SUCCESS; - TempStatus = Status; + TempStatus = EFI_SUCCESS; // Cache the block size to avoid de-referencing pointers all the time BlockSize = Instance->Media.BlockSize; @@ -449,25 +450,21 @@ FvbRead ( return EFI_BAD_BUFFER_SIZE; } - // Check we did get some memory - if (Instance->FvbBuffer == NULL) { - DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - Buffer not ready\n")); - return EFI_DEVICE_ERROR; - } - - // Read NOR Flash data into shadow buffer - TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer); - if (EFI_ERROR (TempStatus)) { - // Return one of the pre-approved error statuses - return EFI_DEVICE_ERROR; + // Decide if we are doing full block reads or not. + if (*NumBytes % BlockSize != 0) { + TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer); + if (EFI_ERROR (TempStatus)) { + return EFI_DEVICE_ERROR; + } + } else { + // Read NOR Flash data into shadow buffer + TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer); + if (EFI_ERROR (TempStatus)) { + // Return one of the pre-approved error statuses + return EFI_DEVICE_ERROR; + } } - - // Put the data at the appropriate location inside the buffer area - DEBUG ((DEBUG_BLKIO, "FvbRead: CopyMem( Dst=0x%08x, Src=0x%08x, Size=0x%x ).\n", Buffer, (UINTN)Instance->FvbBuffer + Offset, *NumBytes)); - - CopyMem (Buffer, (VOID*)((UINTN)Instance->FvbBuffer + Offset), *NumBytes); - - return Status; + return EFI_SUCCESS; } /** @@ -534,71 +531,11 @@ FvbWrite ( IN UINT8 *Buffer ) { - EFI_STATUS Status; - EFI_STATUS TempStatus; - UINTN BlockSize; NOR_FLASH_INSTANCE *Instance; - Instance = INSTANCE_FROM_FVB_THIS(This); - - if (!Instance->Initialized && Instance->Initialize) { - Instance->Initialize(Instance); - } - - DEBUG ((DEBUG_BLKIO, "FvbWrite(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer)); - - Status = EFI_SUCCESS; - TempStatus = Status; - - // Detect WriteDisabled state - if (Instance->Media.ReadOnly == TRUE) { - DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not write: Device is in WriteDisabled state.\n")); - // It is in WriteDisabled state, return an error right away - return EFI_ACCESS_DENIED; - } - - // Cache the block size to avoid de-referencing pointers all the time - BlockSize = Instance->Media.BlockSize; - - // The write must not span block boundaries. - // We need to check each variable individually because adding two large values together overflows. - if ( ( Offset >= BlockSize ) || - ( *NumBytes > BlockSize ) || - ( (Offset + *NumBytes) > BlockSize ) ) { - DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize )); - return EFI_BAD_BUFFER_SIZE; - } + Instance = INSTANCE_FROM_FVB_THIS (This); - // We must have some bytes to write - if (*NumBytes == 0) { - DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize )); - return EFI_BAD_BUFFER_SIZE; - } - - // Check we did get some memory - if (Instance->FvbBuffer == NULL) { - DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Buffer not ready\n")); - return EFI_DEVICE_ERROR; - } - - // Read NOR Flash data into shadow buffer - TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer); - if (EFI_ERROR (TempStatus)) { - // Return one of the pre-approved error statuses - return EFI_DEVICE_ERROR; - } - - // Put the data at the appropriate location inside the buffer area - CopyMem ((VOID*)((UINTN)Instance->FvbBuffer + Offset), Buffer, *NumBytes); - - // Write the modified buffer back to the NorFlash - TempStatus = NorFlashWriteBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer); - if (EFI_ERROR (TempStatus)) { - // Return one of the pre-approved error statuses - return EFI_DEVICE_ERROR; - } - - return Status; + return NorFlashWriteSingleBlock (Instance, Lba, Offset, NumBytes, Buffer); } /** @@ -745,6 +682,25 @@ EXIT: return Status; } +/** + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + + @param[in] Event The Event that is being processed + @param[in] Context Event Context +**/ +VOID +EFIAPI +FvbVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase); + return; +} + EFI_STATUS EFIAPI NorFlashFvbInitialize ( @@ -754,10 +710,12 @@ NorFlashFvbInitialize ( EFI_STATUS Status; UINT32 FvbNumLba; EFI_BOOT_MODE BootMode; + UINTN RuntimeMmioRegionSize; DEBUG((DEBUG_BLKIO,"NorFlashFvbInitialize\n")); Instance->Initialized = TRUE; + mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase); // Set the index of the first LBA for the FVB Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->RegionBaseAddress) / Instance->Media.BlockSize; @@ -789,5 +747,41 @@ NorFlashFvbInitialize ( return Status; } } + + // + // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME + // + + // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory; + // even if we only use the small block region at the top of the NOR Flash. + // The reason is when the NOR Flash memory is set into program mode, the command + // is written as the base of the flash region (ie: Instance->DeviceBaseAddress) + RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size; + + Status = gDS->AddMemorySpace ( + EfiGcdMemoryTypeMemoryMappedIo, + Instance->DeviceBaseAddress, RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME + ); + ASSERT_EFI_ERROR (Status); + + Status = gDS->SetMemorySpaceAttributes ( + Instance->DeviceBaseAddress, RuntimeMmioRegionSize, + EFI_MEMORY_UC | EFI_MEMORY_RUNTIME); + ASSERT_EFI_ERROR (Status); + + // + // Register for the virtual address change event + // + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + FvbVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mFvbVirtualAddrChangeEvent + ); + ASSERT_EFI_ERROR (Status); + return Status; }