ArmPlatformPkg/NorFlashDxe: Fix coding mistakes that would prevent Runtime mode

- No allocation during Runtime mode (post ExitBootServices())
- Allocate all the persistent data into runtime space
- Do not access BootServices API during Runtime mode

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@15437 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Olivier Martin 2014-04-08 18:02:32 +00:00 committed by oliviermartin
parent 000f80f77b
commit 2dff0c1ab2
4 changed files with 54 additions and 50 deletions

View File

@ -1,6 +1,6 @@
/** @file NorFlashDxe.c /** @file NorFlashDxe.c
Copyright (c) 2011-2013, ARM Ltd. All rights reserved.<BR> Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -72,7 +72,7 @@ NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {
FvbEraseBlocks, // EraseBlocks FvbEraseBlocks, // EraseBlocks
NULL, //ParentHandle NULL, //ParentHandle
}, // FvbProtoccol; }, // FvbProtoccol;
NULL, // FvbBuffer
{ {
{ {
{ {
@ -109,7 +109,7 @@ NorFlashCreateInstance (
ASSERT(NorFlashInstance != NULL); ASSERT(NorFlashInstance != NULL);
Instance = AllocateCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate); Instance = AllocateRuntimeCopyPool (sizeof(NOR_FLASH_INSTANCE),&mNorFlashInstanceTemplate);
if (Instance == NULL) { if (Instance == NULL) {
return EFI_OUT_OF_RESOURCES; return EFI_OUT_OF_RESOURCES;
} }
@ -123,11 +123,15 @@ NorFlashCreateInstance (
Instance->Media.BlockSize = BlockSize; Instance->Media.BlockSize = BlockSize;
Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1; Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;
CopyGuid (&Instance->DevicePath.Vendor.Guid,NorFlashGuid); CopyGuid (&Instance->DevicePath.Vendor.Guid, NorFlashGuid);
if (SupportFvb) { if (SupportFvb) {
Instance->SupportFvb = TRUE; Instance->SupportFvb = TRUE;
Instance->Initialize = NorFlashFvbInitialize; Instance->Initialize = NorFlashFvbInitialize;
Instance->FvbBuffer = AllocateRuntimePool (BlockSize);;
if (Instance->FvbBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = gBS->InstallMultipleProtocolInterfaces ( Status = gBS->InstallMultipleProtocolInterfaces (
&Instance->Handle, &Instance->Handle,
@ -137,7 +141,7 @@ NorFlashCreateInstance (
NULL NULL
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
FreePool(Instance); FreePool (Instance);
return Status; return Status;
} }
} else { } else {
@ -150,7 +154,7 @@ NorFlashCreateInstance (
NULL NULL
); );
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
FreePool(Instance); FreePool (Instance);
return Status; return Status;
} }
} }
@ -340,8 +344,14 @@ NorFlashUnlockAndEraseSingleBlock (
UINTN Index; UINTN Index;
EFI_TPL OriginalTPL; EFI_TPL OriginalTPL;
// Raise TPL to TPL_HIGH to stop anyone from interrupting us. if (!EfiAtRuntime ()) {
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
} else {
// This initialization is only to prevent the compiler to complain about the
// use of uninitialized variables
OriginalTPL = TPL_HIGH_LEVEL;
}
Index = 0; Index = 0;
// The block erase might fail a first time (SW bug ?). Retry it ... // The block erase might fail a first time (SW bug ?). Retry it ...
@ -358,8 +368,10 @@ NorFlashUnlockAndEraseSingleBlock (
DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index)); DEBUG((EFI_D_ERROR,"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress,Index));
} }
// Interruptions can resume. if (!EfiAtRuntime ()) {
gBS->RestoreTPL (OriginalTPL); // Interruptions can resume.
gBS->RestoreTPL (OriginalTPL);
}
return Status; return Status;
} }
@ -581,8 +593,14 @@ NorFlashWriteSingleBlock (
// Start writing from the first address at the start of the block // Start writing from the first address at the start of the block
WordAddress = BlockAddress; WordAddress = BlockAddress;
// Raise TPL to TPL_HIGH to stop anyone from interrupting us. if (!EfiAtRuntime ()) {
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL); // Raise TPL to TPL_HIGH to stop anyone from interrupting us.
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
} else {
// This initialization is only to prevent the compiler to complain about the
// use of uninitialized variables
OriginalTPL = TPL_HIGH_LEVEL;
}
Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress); Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
@ -632,8 +650,10 @@ NorFlashWriteSingleBlock (
} }
EXIT: EXIT:
// Interruptions can resume. if (!EfiAtRuntime ()) {
gBS->RestoreTPL (OriginalTPL); // Interruptions can resume.
gBS->RestoreTPL (OriginalTPL);
}
if (EFI_ERROR(Status)) { if (EFI_ERROR(Status)) {
DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status)); DEBUG((EFI_D_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
@ -797,7 +817,7 @@ NorFlashInitialise (
return Status; return Status;
} }
mNorFlashInstances = AllocatePool (sizeof(NOR_FLASH_INSTANCE*) * NorFlashDeviceCount); mNorFlashInstances = AllocateRuntimePool (sizeof(NOR_FLASH_INSTANCE*) * NorFlashDeviceCount);
for (Index = 0; Index < NorFlashDeviceCount; Index++) { for (Index = 0; Index < NorFlashDeviceCount; Index++) {
// Check if this NOR Flash device contain the variable storage region // Check if this NOR Flash device contain the variable storage region

View File

@ -1,6 +1,6 @@
/** @file NorFlashDxe.h /** @file NorFlashDxe.h
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR> Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -26,6 +26,7 @@
#include <Library/IoLib.h> #include <Library/IoLib.h>
#include <Library/NorFlashPlatformLib.h> #include <Library/NorFlashPlatformLib.h>
#include <Library/UefiLib.h> #include <Library/UefiLib.h>
#include <Library/UefiRuntimeLib.h>
#define NOR_FLASH_ERASE_RETRY 10 #define NOR_FLASH_ERASE_RETRY 10
@ -141,6 +142,7 @@ struct _NOR_FLASH_INSTANCE {
BOOLEAN SupportFvb; BOOLEAN SupportFvb;
EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol; EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL FvbProtocol;
VOID* FvbBuffer;
NOR_FLASH_DEVICE_PATH DevicePath; NOR_FLASH_DEVICE_PATH DevicePath;
}; };

View File

@ -41,6 +41,7 @@
UefiLib UefiLib
UefiDriverEntryPoint UefiDriverEntryPoint
UefiBootServicesTableLib UefiBootServicesTableLib
UefiRuntimeLib
[Guids] [Guids]
gEfiSystemNvDataFvGuid gEfiSystemNvDataFvGuid

View File

@ -1,6 +1,6 @@
/*++ @file NorFlashFvbDxe.c /*++ @file NorFlashFvbDxe.c
Copyright (c) 2011-201333, ARM Ltd. All rights reserved.<BR> Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License are licensed and made available under the terms and conditions of the BSD License
@ -417,7 +417,6 @@ FvbRead (
EFI_STATUS Status; EFI_STATUS Status;
EFI_STATUS TempStatus; EFI_STATUS TempStatus;
UINTN BlockSize; UINTN BlockSize;
UINT8 *BlockBuffer;
NOR_FLASH_INSTANCE *Instance; NOR_FLASH_INSTANCE *Instance;
Instance = INSTANCE_FROM_FVB_THIS(This); Instance = INSTANCE_FROM_FVB_THIS(This);
@ -450,32 +449,24 @@ FvbRead (
return EFI_BAD_BUFFER_SIZE; return EFI_BAD_BUFFER_SIZE;
} }
// FixMe: Allow an arbitrary number of bytes to be read out, not just a multiple of block size. // Check we did get some memory
if (Instance->FvbBuffer == NULL) {
// Allocate runtime memory to read in the NOR Flash data. Variable Services are runtime. DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - Buffer not ready\n"));
BlockBuffer = AllocateRuntimePool (BlockSize);
// Check if the memory allocation was successful
if (BlockBuffer == NULL) {
DEBUG ((EFI_D_ERROR, "FvbRead: ERROR - Could not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer));
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
// Read NOR Flash data into shadow buffer // Read NOR Flash data into shadow buffer
TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer); TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer);
if (EFI_ERROR (TempStatus)) { if (EFI_ERROR (TempStatus)) {
// Return one of the pre-approved error statuses // Return one of the pre-approved error statuses
Status = EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
goto FREE_MEMORY;
} }
// Put the data at the appropriate location inside the buffer area // 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, BlockBuffer + Offset, *NumBytes)); DEBUG ((DEBUG_BLKIO, "FvbRead: CopyMem( Dst=0x%08x, Src=0x%08x, Size=0x%x ).\n", Buffer, (UINTN)Instance->FvbBuffer + Offset, *NumBytes));
CopyMem(Buffer, BlockBuffer + Offset, *NumBytes); CopyMem (Buffer, (VOID*)((UINTN)Instance->FvbBuffer + Offset), *NumBytes);
FREE_MEMORY:
FreePool(BlockBuffer);
return Status; return Status;
} }
@ -546,7 +537,6 @@ FvbWrite (
EFI_STATUS Status; EFI_STATUS Status;
EFI_STATUS TempStatus; EFI_STATUS TempStatus;
UINTN BlockSize; UINTN BlockSize;
UINT8 *BlockBuffer;
NOR_FLASH_INSTANCE *Instance; NOR_FLASH_INSTANCE *Instance;
Instance = INSTANCE_FROM_FVB_THIS(This); Instance = INSTANCE_FROM_FVB_THIS(This);
@ -585,38 +575,29 @@ FvbWrite (
return EFI_BAD_BUFFER_SIZE; return EFI_BAD_BUFFER_SIZE;
} }
// Allocate runtime memory to read in the NOR Flash data.
// Since the intention is to use this with Variable Services and since these are runtime,
// allocate the memory from the runtime pool.
BlockBuffer = AllocateRuntimePool (BlockSize);
// Check we did get some memory // Check we did get some memory
if( BlockBuffer == NULL ) { if (Instance->FvbBuffer == NULL) {
DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not allocate BlockBuffer @ 0x%08x.\n", BlockBuffer)); DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Buffer not ready\n"));
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
// Read NOR Flash data into shadow buffer // Read NOR Flash data into shadow buffer
TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer); TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer);
if (EFI_ERROR (TempStatus)) { if (EFI_ERROR (TempStatus)) {
// Return one of the pre-approved error statuses // Return one of the pre-approved error statuses
Status = EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
goto FREE_MEMORY;
} }
// Put the data at the appropriate location inside the buffer area // Put the data at the appropriate location inside the buffer area
CopyMem((BlockBuffer + Offset), Buffer, *NumBytes); CopyMem ((VOID*)((UINTN)Instance->FvbBuffer + Offset), Buffer, *NumBytes);
// Write the modified buffer back to the NorFlash // Write the modified buffer back to the NorFlash
TempStatus = NorFlashWriteBlocks (Instance, Instance->StartLba + Lba, BlockSize, BlockBuffer); TempStatus = NorFlashWriteBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->FvbBuffer);
if (EFI_ERROR (TempStatus)) { if (EFI_ERROR (TempStatus)) {
// Return one of the pre-approved error statuses // Return one of the pre-approved error statuses
Status = EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
goto FREE_MEMORY;
} }
FREE_MEMORY:
FreePool(BlockBuffer);
return Status; return Status;
} }