ArmPlatformPkg/NorFlashDxe: Fixed driver to support UEFI Runtime mode

- Added the NOR Flash region to the Runtime UEFI Memory Mapped IO
- Caught the gEfiEventVirtualAddressChangeGuid event to fixup the NOR Flash pointers

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15438 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Olivier Martin 2014-04-08 18:03:25 +00:00 committed by oliviermartin
parent 2dff0c1ab2
commit 1dbbfc176f
4 changed files with 127 additions and 5 deletions

View File

@ -20,11 +20,13 @@
#include "NorFlashDxe.h"
STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;
//
// Global variable declarations
//
NOR_FLASH_INSTANCE **mNorFlashInstances;
UINT32 mNorFlashDeviceCount;
NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
NOR_FLASH_SIGNATURE, // Signature
@ -792,6 +794,50 @@ NorFlashReset (
return EFI_SUCCESS;
}
/**
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
NorFlashVirtualNotifyEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
{
UINTN Index;
for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->DeviceBaseAddress);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->RegionBaseAddress);
// Convert BlockIo protocol
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.FlushBlocks);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.ReadBlocks);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.Reset);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->BlockIoProtocol.WriteBlocks);
// Convert Fvb
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Read);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbProtocol.Write);
if (mNorFlashInstances[Index]->FvbBuffer != NULL) {
EfiConvertPointer (0x0, (VOID**)&mNorFlashInstances[Index]->FvbBuffer);
}
}
return;
}
EFI_STATUS
EFIAPI
NorFlashInitialise (
@ -802,7 +848,6 @@ NorFlashInitialise (
EFI_STATUS Status;
UINT32 Index;
NOR_FLASH_DESCRIPTION* NorFlashDevices;
UINT32 NorFlashDeviceCount;
BOOLEAN ContainVariableStorage;
Status = NorFlashPlatformInitialization ();
@ -811,15 +856,15 @@ NorFlashInitialise (
return Status;
}
Status = NorFlashPlatformGetDevices (&NorFlashDevices,&NorFlashDeviceCount);
Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);
if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
return Status;
}
mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) * NorFlashDeviceCount);
mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) * mNorFlashDeviceCount);
for (Index = 0; Index < NorFlashDeviceCount; Index++) {
for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
// Check if this NOR Flash device contain the variable storage region
ContainVariableStorage =
(NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&
@ -840,5 +885,18 @@ NorFlashInitialise (
}
}
//
// Register for the virtual address change event
//
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
NorFlashVirtualNotifyEvent,
NULL,
&gEfiEventVirtualAddressChangeGuid,
&mNorFlashVirtualAddrChangeEvent
);
ASSERT_EFI_ERROR (Status);
return Status;
}

View File

@ -19,6 +19,8 @@
#include <Base.h>
#include <PiDxe.h>
#include <Guid/EventGroup.h>
#include <Protocol/BlockIo.h>
#include <Protocol/FirmwareVolumeBlock.h>

View File

@ -42,10 +42,12 @@
UefiDriverEntryPoint
UefiBootServicesTableLib
UefiRuntimeLib
DxeServicesTableLib
[Guids]
gEfiSystemNvDataFvGuid
gEfiVariableGuid
gEfiEventVirtualAddressChangeGuid
[Protocols]
gEfiBlockIoProtocolGuid

View File

@ -20,6 +20,7 @@
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Guid/VariableFormat.h>
@ -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;
}
@ -745,6 +748,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 +776,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 +813,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;
}