NOR_FLASH_SIGNATURE, // Signature\r
NULL, // Handle ... NEED TO BE FILLED\r
\r
- FALSE, // Initialized\r
- NULL, // Initialize\r
-\r
0, // DeviceBaseAddress ... NEED TO BE FILLED\r
0, // RegionBaseAddress ... NEED TO BE FILLED\r
0, // Size ... NEED TO BE FILLED\r
NorFlashDiskIoWriteDisk // WriteDisk\r
},\r
\r
- FALSE, // SupportFvb ... NEED TO BE FILLED\r
{\r
FvbGetAttributes, // GetAttributes\r
FvbSetAttributes, // SetAttributes\r
{\r
HARDWARE_DEVICE_PATH,\r
HW_VENDOR_DP,\r
- (UINT8)( sizeof(VENDOR_DEVICE_PATH) ),\r
- (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8),\r
+ {\r
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),\r
+ (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)\r
+ }\r
},\r
- { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, // GUID ... NEED TO BE FILLED\r
+ { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }, // GUID ... NEED TO BE FILLED\r
},\r
{\r
END_DEVICE_PATH_TYPE,\r
END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
- sizeof (EFI_DEVICE_PATH_PROTOCOL),\r
- 0\r
+ { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }\r
}\r
} // DevicePath\r
};\r
IN UINTN NorFlashDeviceBase,\r
IN UINTN NorFlashRegionBase,\r
IN UINTN NorFlashSize,\r
- IN UINT32 MediaId,\r
+ IN UINT32 Index,\r
IN UINT32 BlockSize,\r
IN BOOLEAN SupportFvb,\r
IN CONST GUID *NorFlashGuid,\r
Instance->Size = NorFlashSize;\r
\r
Instance->BlockIoProtocol.Media = &Instance->Media;\r
- Instance->Media.MediaId = MediaId;\r
+ Instance->Media.MediaId = Index;\r
Instance->Media.BlockSize = BlockSize;\r
Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;\r
\r
}\r
\r
if (SupportFvb) {\r
- Instance->SupportFvb = TRUE;\r
- Instance->Initialize = NorFlashFvbInitialize;\r
+ NorFlashFvbInitialize (Instance);\r
\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Instance->Handle,\r
return Status;\r
}\r
} else {\r
- Instance->Initialized = TRUE;\r
-\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
&Instance->Handle,\r
&gEfiDevicePathProtocolGuid, &Instance->DevicePath,\r
return MmioRead32 (Instance->DeviceBaseAddress);\r
}\r
\r
-\r
+STATIC\r
BOOLEAN\r
NorFlashBlockIsLocked (\r
IN NOR_FLASH_INSTANCE *Instance,\r
)\r
{\r
UINT32 LockStatus;\r
- BOOLEAN BlockIsLocked;\r
-\r
- BlockIsLocked = TRUE;\r
\r
// Send command for reading device id\r
SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);\r
DEBUG((EFI_D_ERROR, "NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));\r
}\r
\r
- if ((LockStatus & 0x1) == 0) {\r
- // This means the block is unlocked\r
- DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: Block 0x%08x unlocked\n", BlockAddress));\r
- BlockIsLocked = FALSE;\r
- }\r
-\r
- return BlockIsLocked;\r
+ return ((LockStatus & 0x1) != 0);\r
}\r
\r
-\r
+STATIC\r
EFI_STATUS\r
NorFlashUnlockSingleBlock (\r
IN NOR_FLASH_INSTANCE *Instance,\r
IN UINTN BlockAddress\r
)\r
{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
UINT32 LockStatus;\r
\r
// Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations\r
// Put device back into Read Array mode\r
SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);\r
\r
- DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x, Exit Status = \"%r\".\n", BlockAddress, Status));\r
+ DEBUG((DEBUG_BLKIO, "UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));\r
\r
- return Status;\r
+ return EFI_SUCCESS;\r
}\r
\r
-\r
+STATIC\r
EFI_STATUS\r
NorFlashUnlockSingleBlockIfNecessary (\r
IN NOR_FLASH_INSTANCE *Instance,\r
IN UINTN BlockAddress\r
)\r
{\r
- EFI_STATUS Status = EFI_SUCCESS;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
\r
if (NorFlashBlockIsLocked (Instance, BlockAddress) == TRUE) {\r
Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);\r
/**\r
* The following function presumes that the block has already been unlocked.\r
**/\r
+STATIC\r
EFI_STATUS\r
NorFlashEraseSingleBlock (\r
IN NOR_FLASH_INSTANCE *Instance,\r
}\r
\r
/**\r
- * The following function presumes that the block has already been unlocked.\r
+ * This function unlock and erase an entire NOR Flash block.\r
**/\r
EFI_STATUS\r
NorFlashUnlockAndEraseSingleBlock (\r
do {\r
// Unlock the block if we have to\r
Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);\r
- if (!EFI_ERROR(Status)) {\r
- Status = NorFlashEraseSingleBlock (Instance, BlockAddress);\r
+ if (EFI_ERROR (Status)) {\r
+ break;\r
}\r
+ Status = NorFlashEraseSingleBlock (Instance, BlockAddress);\r
Index++;\r
} while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));\r
\r
\r
// Write the data to the NOR Flash, advancing each address by 4 bytes\r
for(Count=0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {\r
- *Data = *Buffer;\r
+ MmioWrite32 ((UINTN)Data, *Buffer);\r
}\r
\r
// Issue the Buffered Program Confirm command, to start the programming operation\r
return Status;\r
}\r
\r
+#define BOTH_ALIGNED(a, b, align) ((((UINTN)(a) | (UINTN)(b)) & ((align) - 1)) == 0)\r
+\r
+/**\r
+ Copy Length bytes from Source to Destination, using aligned accesses only.\r
+ Note that this implementation uses memcpy() semantics rather then memmove()\r
+ semantics, i.e., SourceBuffer and DestinationBuffer should not overlap.\r
+\r
+ @param DestinationBuffer The target of the copy request.\r
+ @param SourceBuffer The place to copy from.\r
+ @param Length The number of bytes to copy.\r
+\r
+ @return Destination\r
+\r
+**/\r
+STATIC\r
+VOID *\r
+AlignedCopyMem (\r
+ OUT VOID *DestinationBuffer,\r
+ IN CONST VOID *SourceBuffer,\r
+ IN UINTN Length\r
+ )\r
+{\r
+ UINT8 *Destination8;\r
+ CONST UINT8 *Source8;\r
+ UINT32 *Destination32;\r
+ CONST UINT32 *Source32;\r
+ UINT64 *Destination64;\r
+ CONST UINT64 *Source64;\r
+\r
+ if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 8) && Length >= 8) {\r
+ Destination64 = DestinationBuffer;\r
+ Source64 = SourceBuffer;\r
+ while (Length >= 8) {\r
+ *Destination64++ = *Source64++;\r
+ Length -= 8;\r
+ }\r
+\r
+ Destination8 = (UINT8 *)Destination64;\r
+ Source8 = (CONST UINT8 *)Source64;\r
+ } else if (BOTH_ALIGNED(DestinationBuffer, SourceBuffer, 4) && Length >= 4) {\r
+ Destination32 = DestinationBuffer;\r
+ Source32 = SourceBuffer;\r
+ while (Length >= 4) {\r
+ *Destination32++ = *Source32++;\r
+ Length -= 4;\r
+ }\r
+\r
+ Destination8 = (UINT8 *)Destination32;\r
+ Source8 = (CONST UINT8 *)Source32;\r
+ } else {\r
+ Destination8 = DestinationBuffer;\r
+ Source8 = SourceBuffer;\r
+ }\r
+ while (Length-- != 0) {\r
+ *Destination8++ = *Source8++;\r
+ }\r
+ return DestinationBuffer;\r
+}\r
+\r
EFI_STATUS\r
NorFlashReadBlocks (\r
IN NOR_FLASH_INSTANCE *Instance,\r
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);\r
\r
// Readout the data\r
- CopyMem(Buffer, (UINTN *)StartAddress, BufferSizeInBytes);\r
+ AlignedCopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);\r
\r
return EFI_SUCCESS;\r
}\r
OUT VOID *Buffer\r
)\r
{\r
- UINT32 NumBlocks;\r
- UINTN StartAddress;\r
+ UINTN StartAddress;\r
\r
// The buffer must be valid\r
if (Buffer == NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
- // All blocks must be within the device\r
- NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;\r
-\r
- if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1)) {\r
- DEBUG ((EFI_D_ERROR, "NorFlashRead: ERROR - Read will exceed last block\n"));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (Offset + BufferSizeInBytes >= Instance->Size) {\r
+ if (((Lba * Instance->Media.BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {\r
DEBUG ((EFI_D_ERROR, "NorFlashRead: ERROR - Read will exceed device size.\n"));\r
return EFI_INVALID_PARAMETER;\r
}\r
SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);\r
\r
// Readout the data\r
- CopyMem (Buffer, (UINTN *)(StartAddress + Offset), BufferSizeInBytes);\r
+ AlignedCopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);\r
\r
return EFI_SUCCESS;\r
}\r
\r
PrevBlockAddress = 0;\r
\r
- if (!Instance->Initialized && Instance->Initialize) {\r
- Instance->Initialize(Instance);\r
- }\r
-\r
- DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));\r
+ DEBUG ((DEBUG_BLKIO, "NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));\r
\r
// Detect WriteDisabled state\r
if (Instance->Media.ReadOnly == TRUE) {\r
while (BytesToWrite > 0) {\r
// Read full word from NOR, splice as required. A word is the smallest\r
// unit we can write.\r
- TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba,\r
- CurOffset & ~(0x3), sizeof(Tmp), &Tmp);\r
+ TempStatus = NorFlashRead (Instance, Lba, CurOffset & ~(0x3), sizeof(Tmp), &Tmp);\r
if (EFI_ERROR (TempStatus)) {\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
\r
// Read NOR Flash data into shadow buffer\r
- TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->ShadowBuffer);\r
+ TempStatus = NorFlashReadBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);\r
if (EFI_ERROR (TempStatus)) {\r
// Return one of the pre-approved error statuses\r
return EFI_DEVICE_ERROR;\r
CopyMem ((VOID*)((UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);\r
\r
// Write the modified buffer back to the NorFlash\r
- TempStatus = NorFlashWriteBlocks (Instance, Instance->StartLba + Lba, BlockSize, Instance->ShadowBuffer);\r
+ TempStatus = NorFlashWriteBlocks (Instance, Lba, BlockSize, Instance->ShadowBuffer);\r
if (EFI_ERROR (TempStatus)) {\r
// Return one of the pre-approved error statuses\r
return EFI_DEVICE_ERROR;\r