17#include "VirtNorFlash.h"
25UINT32 mNorFlashDeviceCount;
26UINTN mFlashNvStorageVariableBase;
43 FvbGetPhysicalAddress,
61 { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }
67 END_ENTIRE_DEVICE_PATH_SUBTYPE,
74NorFlashCreateInstance (
80 IN BOOLEAN SupportFvb,
87 ASSERT (NorFlashInstance !=
NULL);
90 if (Instance ==
NULL) {
91 return EFI_OUT_OF_RESOURCES;
94 Instance->DeviceBaseAddress = NorFlashDeviceBase;
95 Instance->RegionBaseAddress = NorFlashRegionBase;
96 Instance->Size = NorFlashSize;
97 Instance->BlockSize = BlockSize;
98 Instance->LastBlock = (NorFlashSize / BlockSize) - 1;
100 CopyGuid (&Instance->DevicePath.Vendor.
Guid, &gEfiCallerIdGuid);
101 Instance->DevicePath.Index = (UINT8)Index;
104 if (Instance->ShadowBuffer ==
NULL) {
105 return EFI_OUT_OF_RESOURCES;
109 NorFlashFvbInitialize (Instance);
111 Status =
gBS->InstallMultipleProtocolInterfaces (
113 &gEfiDevicePathProtocolGuid,
114 &Instance->DevicePath,
115 &gEfiFirmwareVolumeBlockProtocolGuid,
116 &Instance->FvbProtocol,
119 if (EFI_ERROR (Status)) {
124 Status =
gBS->InstallMultipleProtocolInterfaces (
126 &gEfiDevicePathProtocolGuid,
127 &Instance->DevicePath,
130 if (EFI_ERROR (Status)) {
136 *NorFlashInstance = Instance;
144NorFlashUnlockAndEraseSingleBlock (
155 OriginalTPL =
gBS->RaiseTPL (TPL_HIGH_LEVEL);
159 OriginalTPL = TPL_HIGH_LEVEL;
166 Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
167 if (EFI_ERROR (Status)) {
171 Status = NorFlashEraseSingleBlock (Instance, BlockAddress);
173 }
while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
175 if (Index == NOR_FLASH_ERASE_RETRY) {
176 DEBUG ((DEBUG_ERROR,
"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
181 gBS->RestoreTPL (OriginalTPL);
188NorFlashWriteFullBlock (
191 IN UINT32 *DataBuffer,
192 IN UINT32 BlockSizeInWords
200 UINTN BuffersInBlock;
201 UINTN RemainingWords;
208 BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);
211 WordAddress = BlockAddress;
215 OriginalTPL =
gBS->RaiseTPL (TPL_HIGH_LEVEL);
219 OriginalTPL = TPL_HIGH_LEVEL;
222 Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
223 if (EFI_ERROR (Status)) {
224 DEBUG ((DEBUG_ERROR,
"WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));
231 if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {
233 BuffersInBlock = (
UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;
237 for (BufferIndex = 0;
238 BufferIndex < BuffersInBlock;
239 BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS
243 for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {
244 if (~DataBuffer[Cnt] != 0 ) {
246 Status = NorFlashWriteBuffer (
249 P30_MAX_BUFFER_SIZE_IN_BYTES,
252 if (EFI_ERROR (Status)) {
262 RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;
264 if (RemainingWords != 0) {
265 Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);
266 if (EFI_ERROR (Status)) {
274 for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {
275 Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);
276 if (EFI_ERROR (Status)) {
284 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
288 gBS->RestoreTPL (OriginalTPL);
291 if (EFI_ERROR (Status)) {
292 DEBUG ((DEBUG_ERROR,
"NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));
308 BOOLEAN ContainVariableStorage;
311 if (EFI_ERROR (Status)) {
312 DEBUG ((DEBUG_ERROR,
"NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
317 if (EFI_ERROR (Status)) {
318 DEBUG ((DEBUG_ERROR,
"NorFlashInitialise: Fail to get Nor Flash devices\n"));
324 for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
327 if (
PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {
328 ContainVariableStorage =
329 (NorFlashDevices[Index].RegionBaseAddress <=
PcdGet64 (PcdFlashNvStorageVariableBase64)) &&
330 (
PcdGet64 (PcdFlashNvStorageVariableBase64) +
PcdGet32 (PcdFlashNvStorageVariableSize) <=
331 NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
333 ContainVariableStorage =
334 (NorFlashDevices[Index].RegionBaseAddress <=
PcdGet32 (PcdFlashNvStorageVariableBase)) &&
335 (
PcdGet32 (PcdFlashNvStorageVariableBase) +
PcdGet32 (PcdFlashNvStorageVariableSize) <=
336 NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);
339 Status = NorFlashCreateInstance (
340 NorFlashDevices[Index].DeviceBaseAddress,
341 NorFlashDevices[Index].RegionBaseAddress,
342 NorFlashDevices[Index].Size,
344 NorFlashDevices[Index].BlockSize,
345 ContainVariableStorage,
346 &mNorFlashInstances[Index]
348 if (EFI_ERROR (Status)) {
349 DEBUG ((DEBUG_ERROR,
"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index));
356 Status =
gBS->CreateEventEx (
359 NorFlashVirtualNotifyEvent,
361 &gEfiEventVirtualAddressChangeGuid,
362 &mNorFlashVirtualAddrChangeEvent
371NorFlashFvbInitialize (
378 UINTN RuntimeMmioRegionSize;
380 DEBUG ((DEBUG_BLKIO,
"NorFlashFvbInitialize\n"));
381 ASSERT ((Instance !=
NULL));
391 RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;
393 Status =
gDS->AddMemorySpace (
395 Instance->DeviceBaseAddress,
396 RuntimeMmioRegionSize,
397 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
401 Status =
gDS->SetMemorySpaceAttributes (
402 Instance->DeviceBaseAddress,
403 RuntimeMmioRegionSize,
404 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
408 mFlashNvStorageVariableBase = (
PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
409 PcdGet64 (PcdFlashNvStorageVariableBase64) :
PcdGet32 (PcdFlashNvStorageVariableBase);
412 Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->BlockSize;
415 if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
416 Status = EFI_INVALID_PARAMETER;
419 Status = ValidateFvHeader (Instance);
423 if (EFI_ERROR (Status)) {
425 DEBUG ((DEBUG_INFO,
"%a: The FVB Header is not valid.\n", __func__));
428 "%a: Installing a correct one for this volume.\n",
433 FvbNumLba = (
PcdGet32 (PcdFlashNvStorageVariableSize) +
PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->BlockSize;
436 if (EFI_ERROR (Status)) {
442 if (EFI_ERROR (Status)) {
451 Status =
gBS->InstallProtocolInterface (
453 &gEdkiiNvVarStoreFormattedGuid,
462 Status =
gBS->CreateEventEx (
465 FvbVirtualNotifyEvent,
467 &gEfiEventVirtualAddressChangeGuid,
468 &mFvbVirtualAddrChangeEvent
EFI_BOOT_MODE EFIAPI GetBootModeHob(VOID)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
#define HARDWARE_DEVICE_PATH
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateRuntimePool(IN UINTN AllocationSize)
VOID *EFIAPI AllocateRuntimeCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define EFI_LBA_LIST_TERMINATOR
VOID InitializeFvAndVariableStoreHeaders(IN VOID *Ptr)
#define OFFSET_OF(TYPE, Field)
#define ASSERT_EFI_ERROR(StatusParameter)
#define DEBUG(Expression)
#define PcdGet64(TokenName)
#define PcdGet32(TokenName)
@ EfiGcdMemoryTypeMemoryMappedIo
BOOLEAN EFIAPI EfiAtRuntime(VOID)