12#include "VirtNorFlash.h"
18extern UINT32 mNorFlashDeviceCount;
21NorFlashReadStatusRegister (
27 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_STATUS_REGISTER);
28 return MmioRead32 (Instance->DeviceBaseAddress);
33NorFlashBlockIsLocked (
41 SEND_NOR_COMMAND (BlockAddress, 2, P30_CMD_READ_DEVICE_ID);
44 LockStatus =
MmioRead32 (CREATE_NOR_ADDRESS (BlockAddress, 2));
47 LockStatus = FOLD_32BIT_INTO_16BIT (LockStatus);
49 if ((LockStatus & 0x2) != 0) {
50 DEBUG ((DEBUG_ERROR,
"NorFlashBlockIsLocked: WARNING: Block LOCKED DOWN\n"));
53 return ((LockStatus & 0x1) != 0);
58NorFlashUnlockSingleBlock (
69 SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_LOCK_BLOCK_SETUP);
72 SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_UNLOCK_BLOCK);
76 LockStatus = NorFlashReadStatusRegister (Instance, BlockAddress);
77 }
while ((LockStatus & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
80 SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_READ_ARRAY);
82 DEBUG ((DEBUG_BLKIO,
"UnlockSingleBlock: BlockAddress=0x%08x\n", BlockAddress));
88NorFlashUnlockSingleBlockIfNecessary (
97 if (NorFlashBlockIsLocked (Instance, BlockAddress)) {
98 Status = NorFlashUnlockSingleBlock (Instance, BlockAddress);
108NorFlashEraseSingleBlock (
114 UINT32 StatusRegister;
119 SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_SETUP);
120 SEND_NOR_COMMAND (BlockAddress, 0, P30_CMD_BLOCK_ERASE_CONFIRM);
124 StatusRegister = NorFlashReadStatusRegister (Instance, BlockAddress);
125 }
while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
127 if (StatusRegister & P30_SR_BIT_VPP) {
128 DEBUG ((DEBUG_ERROR,
"EraseSingleBlock(BlockAddress=0x%08x: VPP Range Error\n", BlockAddress));
129 Status = EFI_DEVICE_ERROR;
132 if ((StatusRegister & (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) == (P30_SR_BIT_ERASE | P30_SR_BIT_PROGRAM)) {
133 DEBUG ((DEBUG_ERROR,
"EraseSingleBlock(BlockAddress=0x%08x: Command Sequence Error\n", BlockAddress));
134 Status = EFI_DEVICE_ERROR;
137 if (StatusRegister & P30_SR_BIT_ERASE) {
138 DEBUG ((DEBUG_ERROR,
"EraseSingleBlock(BlockAddress=0x%08x: Block Erase Error StatusRegister:0x%X\n", BlockAddress, StatusRegister));
139 Status = EFI_DEVICE_ERROR;
142 if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
144 DEBUG ((DEBUG_INFO,
"EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error\n", BlockAddress));
145 Status = EFI_WRITE_PROTECTED;
148 if (EFI_ERROR (Status)) {
150 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
154 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
160NorFlashWriteSingleWord (
167 UINT32 StatusRegister;
172 SEND_NOR_COMMAND (WordAddress, 0, P30_CMD_WORD_PROGRAM_SETUP);
180 StatusRegister = NorFlashReadStatusRegister (Instance, WordAddress);
182 }
while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
188 if (StatusRegister & P30_SR_BIT_VPP) {
189 DEBUG ((DEBUG_ERROR,
"NorFlashWriteSingleWord(WordAddress:0x%X): VPP Range Error\n", WordAddress));
190 Status = EFI_DEVICE_ERROR;
193 if (StatusRegister & P30_SR_BIT_PROGRAM) {
194 DEBUG ((DEBUG_ERROR,
"NorFlashWriteSingleWord(WordAddress:0x%X): Program Error\n", WordAddress));
195 Status = EFI_DEVICE_ERROR;
198 if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
199 DEBUG ((DEBUG_ERROR,
"NorFlashWriteSingleWord(WordAddress:0x%X): Device Protect Error\n", WordAddress));
200 Status = EFI_DEVICE_ERROR;
203 if (!EFI_ERROR (Status)) {
205 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
235 UINTN BufferSizeInWords;
237 volatile UINT32 *Data;
239 BOOLEAN BufferAvailable;
240 UINT32 StatusRegister;
242 WaitForBuffer = MAX_BUFFERED_PROG_ITERATIONS;
243 BufferAvailable =
FALSE;
246 if ((TargetAddress & BOUNDARY_OF_32_WORDS) != 0) {
247 return EFI_INVALID_PARAMETER;
251 if (BufferSizeInBytes == 0) {
252 return EFI_BUFFER_TOO_SMALL;
256 if (BufferSizeInBytes > P30_MAX_BUFFER_SIZE_IN_BYTES) {
257 return EFI_BAD_BUFFER_SIZE;
261 if ((BufferSizeInBytes % 4) != 0) {
262 return EFI_BAD_BUFFER_SIZE;
268 Data = (UINT32 *)TargetAddress;
273 SEND_NOR_COMMAND (TargetAddress, 0, P30_CMD_BUFFERED_PROGRAM_SETUP);
276 if (((*Data) & P30_SR_BIT_WRITE) == P30_SR_BIT_WRITE) {
277 BufferAvailable =
TRUE;
282 }
while ((WaitForBuffer > 0) && (BufferAvailable ==
FALSE));
285 if (WaitForBuffer == 0) {
286 return EFI_DEVICE_ERROR;
290 BufferSizeInWords = BufferSizeInBytes / (
UINTN)4;
294 SEND_NOR_COMMAND (TargetAddress, 0, (BufferSizeInWords - 1));
297 for (Count = 0; Count < BufferSizeInWords; Count++, Data++, Buffer++) {
302 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM);
306 StatusRegister = NorFlashReadStatusRegister (Instance, TargetAddress);
308 }
while ((StatusRegister & P30_SR_BIT_WRITE) != P30_SR_BIT_WRITE);
316 if (StatusRegister & P30_SR_BIT_VPP) {
317 DEBUG ((DEBUG_ERROR,
"NorFlashWriteBuffer(TargetAddress:0x%X): VPP Range Error\n", TargetAddress));
318 Status = EFI_DEVICE_ERROR;
321 if (StatusRegister & P30_SR_BIT_PROGRAM) {
322 DEBUG ((DEBUG_ERROR,
"NorFlashWriteBuffer(TargetAddress:0x%X): Program Error\n", TargetAddress));
323 Status = EFI_DEVICE_ERROR;
326 if (StatusRegister & P30_SR_BIT_BLOCK_LOCKED) {
327 DEBUG ((DEBUG_ERROR,
"NorFlashWriteBuffer(TargetAddress:0x%X): Device Protect Error\n", TargetAddress));
328 Status = EFI_DEVICE_ERROR;
331 if (!EFI_ERROR (Status)) {
333 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_CLEAR_STATUS_REGISTER);
347 UINT32 *pWriteBuffer;
350 UINT32 BlockSizeInWords;
357 if (Buffer ==
NULL) {
358 return EFI_INVALID_PARAMETER;
362 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes));
363 if (BufferSizeInBytes == 0) {
364 return EFI_BAD_BUFFER_SIZE;
368 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance->BlockSize));
369 if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
370 return EFI_BAD_BUFFER_SIZE;
374 NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
376 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks, Instance->LastBlock, Lba));
378 if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
379 DEBUG ((DEBUG_ERROR,
"NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
380 return EFI_INVALID_PARAMETER;
383 BlockSizeInWords = Instance->BlockSize / 4;
387 pWriteBuffer = (UINT32 *)Buffer;
390 for (BlockCount = 0; BlockCount < NumBlocks; BlockCount++, CurrentBlock++, pWriteBuffer = pWriteBuffer + BlockSizeInWords) {
391 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteBlocks: Writing block #%d\n", (
UINTN)CurrentBlock));
393 Status = NorFlashWriteFullBlock (Instance, CurrentBlock, pWriteBuffer, BlockSizeInWords);
395 if (EFI_ERROR (Status)) {
400 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status));
417 "NorFlashReadBlocks: BufferSize=0x%xB BlockSize=0x%xB LastBlock=%ld, Lba=%ld.\n",
425 if (Buffer ==
NULL) {
426 return EFI_INVALID_PARAMETER;
430 if (BufferSizeInBytes == 0) {
435 if ((BufferSizeInBytes % Instance->BlockSize) != 0) {
436 return EFI_BAD_BUFFER_SIZE;
440 NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->BlockSize;
442 if ((Lba + NumBlocks) > (Instance->LastBlock + 1)) {
443 DEBUG ((DEBUG_ERROR,
"NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
444 return EFI_INVALID_PARAMETER;
448 StartAddress = GET_NOR_BLOCK_ADDRESS (
449 Instance->RegionBaseAddress,
455 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
458 CopyMem (Buffer, (VOID *)StartAddress, BufferSizeInBytes);
475 if (Buffer ==
NULL) {
476 return EFI_INVALID_PARAMETER;
480 if (BufferSizeInBytes == 0) {
484 if (((Lba * Instance->BlockSize) + Offset + BufferSizeInBytes) > Instance->Size) {
485 DEBUG ((DEBUG_ERROR,
"NorFlashRead: ERROR - Read will exceed device size.\n"));
486 return EFI_INVALID_PARAMETER;
490 StartAddress = GET_NOR_BLOCK_ADDRESS (
491 Instance->RegionBaseAddress,
497 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
500 CopyMem (Buffer, (VOID *)(StartAddress + Offset), BufferSizeInBytes);
507NorFlashWriteSingleBlockWithErase (
518 Status = NorFlashReadBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
519 if (EFI_ERROR (Status)) {
521 return EFI_DEVICE_ERROR;
525 CopyMem ((VOID *)((
UINTN)Instance->ShadowBuffer + Offset), Buffer, *NumBytes);
528 Status = NorFlashWriteBlocks (Instance, Lba, Instance->BlockSize, Instance->ShadowBuffer);
529 if (EFI_ERROR (Status)) {
531 return EFI_DEVICE_ERROR;
542NorFlashWriteSingleBlock (
558 DEBUG ((DEBUG_BLKIO,
"NorFlashWriteSingleBlock(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Lba, Offset, *NumBytes, Buffer));
561 if (Instance->ShadowBuffer ==
NULL) {
562 DEBUG ((DEBUG_ERROR,
"FvbWrite: ERROR - Buffer not ready\n"));
563 return EFI_DEVICE_ERROR;
567 BlockSize = Instance->BlockSize;
571 if ((Offset >= BlockSize) ||
572 (*NumBytes > BlockSize) ||
573 ((Offset + *NumBytes) > BlockSize))
575 DEBUG ((DEBUG_ERROR,
"NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
576 return EFI_BAD_BUFFER_SIZE;
580 if (*NumBytes == 0) {
581 DEBUG ((DEBUG_ERROR,
"NorFlashWriteSingleBlock: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
582 return EFI_BAD_BUFFER_SIZE;
612 Start = Offset & ~BOUNDARY_OF_32_WORDS;
613 End =
ALIGN_VALUE (Offset + *NumBytes, P30_MAX_BUFFER_SIZE_IN_BYTES);
615 if ((End - Start) <= (4 * P30_MAX_BUFFER_SIZE_IN_BYTES)) {
622 Status = NorFlashRead (
627 Instance->ShadowBuffer
629 if (EFI_ERROR (Status)) {
630 return EFI_DEVICE_ERROR;
635 OrigData = Instance->ShadowBuffer + (Offset & BOUNDARY_OF_32_WORDS);
640 for (CurOffset = 0; CurOffset < *NumBytes; CurOffset++) {
641 if (~(UINT32)OrigData[CurOffset] & (UINT32)Buffer[CurOffset]) {
642 Status = NorFlashWriteSingleBlockWithErase (
652 OrigData[CurOffset] = Buffer[CurOffset];
658 BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
661 Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
662 if (EFI_ERROR (Status)) {
666 Count = (End - Start) / P30_MAX_BUFFER_SIZE_IN_BYTES;
667 for (Index = 0; Index < Count; Index++) {
668 Status = NorFlashWriteBuffer (
670 BlockAddress + Start + Index * P30_MAX_BUFFER_SIZE_IN_BYTES,
671 P30_MAX_BUFFER_SIZE_IN_BYTES,
672 Instance->ShadowBuffer + Index * P30_MAX_BUFFER_SIZE_IN_BYTES
674 if (EFI_ERROR (Status)) {
679 Status = NorFlashWriteSingleBlockWithErase (
691 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
702 SEND_NOR_COMMAND (Instance->DeviceBaseAddress, 0, P30_CMD_READ_ARRAY);
716NorFlashVirtualNotifyEvent (
723 for (Index = 0; Index < mNorFlashDeviceCount; Index++) {
728 EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.EraseBlocks);
729 EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetAttributes);
730 EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetBlockSize);
731 EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.GetPhysicalAddress);
733 EfiConvertPointer (0x0, (VOID **)&mNorFlashInstances[Index]->FvbProtocol.SetAttributes);
736 if (mNorFlashInstances[Index]->ShadowBuffer !=
NULL) {
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
UINT32 EFIAPI MmioRead32(IN UINTN Address)
UINT32 EFIAPI MmioWrite32(IN UINTN Address, IN UINT32 Value)
#define ALIGN_VALUE(Value, Alignment)
#define DEBUG(Expression)
VOID EFIAPI Exit(IN EFI_STATUS Status)
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)