1 /** @file NorFlashDxe.c
3 Copyright (c) 2011, ARM Ltd. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include <Library/UefiLib.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/MemoryAllocationLib.h>
17 #include <Library/UefiBootServicesTableLib.h>
18 #include <Library/PcdLib.h>
20 #include "NorFlashDxe.h"
24 // Global variable declarations
26 NOR_FLASH_INSTANCE
**mNorFlashInstances
;
28 NOR_FLASH_INSTANCE mNorFlashInstanceTemplate
= {
29 NOR_FLASH_SIGNATURE
, // Signature
30 NULL
, // Handle ... NEED TO BE FILLED
35 0, // BaseAddress ... NEED TO BE FILLED
36 0, // Size ... NEED TO BE FILLED
40 EFI_BLOCK_IO_PROTOCOL_REVISION2
, // Revision
41 NULL
, // Media ... NEED TO BE FILLED
42 NorFlashBlockIoReset
, // Reset;
43 NorFlashBlockIoReadBlocks
, // ReadBlocks
44 NorFlashBlockIoWriteBlocks
, // WriteBlocks
45 NorFlashBlockIoFlushBlocks
// FlushBlocks
49 0, // MediaId ... NEED TO BE FILLED
50 FALSE
, // RemovableMedia
52 FALSE
, // LogicalPartition
54 FALSE
, // WriteCaching;
55 0, // BlockSize ... NEED TO BE FILLED
57 0, // LastBlock ... NEED TO BE FILLED
58 0, // LowestAlignedLba
59 1, // LogicalBlocksPerPhysicalBlock
62 FALSE
, // SupportFvb ... NEED TO BE FILLED
64 FvbGetAttributes
, // GetAttributes
65 FvbSetAttributes
, // SetAttributes
66 FvbGetPhysicalAddress
, // GetPhysicalAddress
67 FvbGetBlockSize
, // GetBlockSize
70 FvbEraseBlocks
, // EraseBlocks
79 (UINT8
)( sizeof(VENDOR_DEVICE_PATH
) ),
80 (UINT8
)((sizeof(VENDOR_DEVICE_PATH
)) >> 8),
82 { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, // GUID ... NEED TO BE FILLED
86 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
87 sizeof (EFI_DEVICE_PATH_PROTOCOL
),
94 NorFlashCreateInstance (
95 IN UINTN NorFlashBase
,
96 IN UINTN NorFlashSize
,
99 IN BOOLEAN SupportFvb
,
100 IN CONST GUID
*NorFlashGuid
,
101 OUT NOR_FLASH_INSTANCE
** NorFlashInstance
105 NOR_FLASH_INSTANCE
* Instance
;
107 ASSERT(NorFlashInstance
!= NULL
);
109 Instance
= AllocateCopyPool (sizeof(NOR_FLASH_INSTANCE
),&mNorFlashInstanceTemplate
);
110 if (Instance
== NULL
) {
111 return EFI_OUT_OF_RESOURCES
;
114 Instance
->BaseAddress
= NorFlashBase
;
115 Instance
->Size
= NorFlashSize
;
117 Instance
->BlockIoProtocol
.Media
= &Instance
->Media
;
118 Instance
->Media
.MediaId
= MediaId
;
119 Instance
->Media
.BlockSize
= BlockSize
;
120 Instance
->Media
.LastBlock
= (NorFlashSize
/ BlockSize
)-1;
122 CopyGuid (&Instance
->DevicePath
.Vendor
.Guid
,NorFlashGuid
);
125 Instance
->SupportFvb
= TRUE
;
126 Instance
->Initialize
= NorFlashFvbInitialize
;
128 Status
= gBS
->InstallMultipleProtocolInterfaces (
130 &gEfiDevicePathProtocolGuid
, &Instance
->DevicePath
,
131 &gEfiBlockIoProtocolGuid
, &Instance
->BlockIoProtocol
,
132 &gEfiFirmwareVolumeBlockProtocolGuid
, &Instance
->FvbProtocol
,
135 if (EFI_ERROR(Status
)) {
140 Instance
->Initialize
= NorFlashBlkIoInitialize
;
142 Status
= gBS
->InstallMultipleProtocolInterfaces (
144 &gEfiDevicePathProtocolGuid
, &Instance
->DevicePath
,
145 &gEfiBlockIoProtocolGuid
, &Instance
->BlockIoProtocol
,
148 if (EFI_ERROR(Status
)) {
154 *NorFlashInstance
= Instance
;
159 NorFlashReadCfiData (
160 IN UINTN BaseAddress
,
162 IN UINT32 NumberOfBytes
,
171 UINT32 CombinedData
= 0;
172 EFI_STATUS Status
= EFI_SUCCESS
;
175 if (NumberOfBytes
> 4) {
176 // Using 32 bit variable so can only read 4 bytes
177 return EFI_INVALID_PARAMETER
;
180 // First combine the base address with the offset address to create an absolute read address.
181 // However, because we are in little endian, read from the last address down to the first
182 ReadAddress
= CREATE_NOR_ADDRESS (BaseAddress
, CfiOffset
) + (NumberOfBytes
- 1) * sizeof(UINT32
);
184 // Although each read returns 32 bits, because of the NOR Flash structure,
185 // each 16 bits (16 MSB and 16 LSB) come from two different chips.
186 // When in CFI mode, each chip read returns valid data in only the 8 LSBits;
187 // the 8 MSBits are invalid and can be ignored.
188 // Therefore, each read address returns one byte from each chip.
190 // Also note: As we are in little endian notation and we are reading
191 // bytes from incremental addresses, we should assemble them in little endian order.
192 for (CurrentByte
=0; CurrentByte
<NumberOfBytes
; CurrentByte
++) {
193 // Read the bytes from the two chips
194 ReadData
= MmioRead32(ReadAddress
);
196 // Check the data validity:
197 // The 'Dual Data' function means that
198 // each chip should return identical data.
199 // If that is not the case then we have a problem.
200 Byte1
= GET_LOW_BYTE (ReadData
);
201 Byte2
= GET_HIGH_BYTE(ReadData
);
204 // The two bytes should have been identical
205 return EFI_DEVICE_ERROR
;
207 // Each successive iteration of the 'for' loop reads a lower address.
208 // As we read lower addresses and as we use little endian,
209 // we read lower significance bytes. So combine them in the correct order.
210 CombinedData
= (CombinedData
<< 8) | Byte1
;
212 // Decrement down to the next address
213 ReadAddress
-= sizeof(UINT32
);
217 *Data
= CombinedData
;
223 NorFlashReadStatusRegister (
227 volatile UINT32
*pStatusRegister
;
228 UINT32 StatusRegister
;
230 EFI_STATUS Status
= EFI_SUCCESS
;
232 // Prepare the read address
233 pStatusRegister
= (UINT32
*) SR_Address
;
236 // Prepare to read the status register
237 SEND_NOR_COMMAND (SR_Address
, 0, P30_CMD_READ_STATUS_REGISTER
);
238 // Snapshot the status register
239 StatusRegister
= *pStatusRegister
;
241 // The chip is busy while the WRITE bit is not asserted
242 while ((StatusRegister
& P30_SR_BIT_WRITE
) != P30_SR_BIT_WRITE
);
245 // Perform a full status check:
246 // Mask the relevant bits of Status Register.
247 // Everything should be zero, if not, we have a problem
249 // Prepare the Error Mask by setting bits 5, 4, 3, 1
250 ErrorMask
= P30_SR_BIT_ERASE
| P30_SR_BIT_PROGRAM
| P30_SR_BIT_VPP
| P30_SR_BIT_BLOCK_LOCKED
;
252 if ( (StatusRegister
& ErrorMask
) != 0 ) {
253 if ( (StatusRegister
& P30_SR_BIT_VPP
) != 0 ) {
254 DEBUG((EFI_D_ERROR
,"NorFlashReadStatusRegister: VPP Range Error\n"));
255 } else if ( (StatusRegister
& (P30_SR_BIT_ERASE
| P30_SR_BIT_PROGRAM
) ) != 0 ) {
256 DEBUG((EFI_D_ERROR
,"NorFlashReadStatusRegister: Command Sequence Error\n"));
257 } else if ( (StatusRegister
& P30_SR_BIT_PROGRAM
) != 0 ) {
258 DEBUG((EFI_D_ERROR
,"NorFlashReadStatusRegister: Program Error\n"));
259 } else if ( (StatusRegister
& P30_SR_BIT_BLOCK_LOCKED
) != 0 ) {
260 DEBUG((EFI_D_ERROR
,"NorFlashReadStatusRegister: Device Protect Error\n"));
262 DEBUG((EFI_D_ERROR
,"NorFlashReadStatusRegister: Error (0x%X)\n",Status
));
265 // If an error is detected we must clear the Status Register
266 SEND_NOR_COMMAND(SR_Address
, 0, P30_CMD_CLEAR_STATUS_REGISTER
);
267 Status
= EFI_DEVICE_ERROR
;
270 SEND_NOR_COMMAND(SR_Address
, 0, P30_CMD_READ_ARRAY
);
277 NorFlashBlockIsLocked (
278 IN UINTN BlockAddress
282 BOOLEAN BlockIsLocked
= TRUE
;
284 // Send command for reading device id
285 SEND_NOR_COMMAND (BlockAddress
, 2, P30_CMD_READ_DEVICE_ID
);
287 // Read block lock status
288 LockStatus
= MmioRead32 (CREATE_NOR_ADDRESS( BlockAddress
, 2 ));
290 // Decode block lock status
291 LockStatus
= FOLD_32BIT_INTO_16BIT(LockStatus
);
293 if((LockStatus
& 0x2) != 0) {
294 DEBUG((EFI_D_ERROR
, "UnlockSingleBlock: WARNING: Block LOCKED DOWN\n"));
297 if((LockStatus
& 0x1) == 0) {
298 // This means the block is unlocked
299 DEBUG((DEBUG_BLKIO
, "UnlockSingleBlock: Block 0x%08x unlocked\n", BlockAddress
));
300 BlockIsLocked
= FALSE
;
303 return BlockIsLocked
;
308 NorFlashUnlockSingleBlock (
309 IN UINTN BlockAddress
312 EFI_STATUS Status
= EFI_SUCCESS
;
314 // Raise the Task Priority Level to TPL_NOTIFY to serialise all its operations
315 // and to protect shared data structures.
317 // Request a lock setup
318 SEND_NOR_COMMAND(BlockAddress
, 0, P30_CMD_LOCK_BLOCK_SETUP
);
321 SEND_NOR_COMMAND(BlockAddress
, 0, P30_CMD_UNLOCK_BLOCK
);
323 // Put device back into Read Array mode
324 SEND_NOR_COMMAND(BlockAddress
, 0, P30_CMD_READ_ARRAY
);
326 DEBUG((DEBUG_BLKIO
, "UnlockSingleBlock: BlockAddress=0x%08x, Exit Status = \"%r\".\n", BlockAddress
, Status
));
333 NorFlashUnlockSingleBlockIfNecessary (
334 IN UINTN BlockAddress
337 EFI_STATUS Status
= EFI_SUCCESS
;
339 if ( NorFlashBlockIsLocked(BlockAddress
) == TRUE
) {
340 Status
= NorFlashUnlockSingleBlock(BlockAddress
);
348 * The following function presumes that the block has already been unlocked.
351 NorFlashEraseSingleBlock (
352 IN UINTN BlockAddress
355 EFI_STATUS Status
= EFI_SUCCESS
;
357 // Request a block erase and then confirm it
358 SEND_NOR_COMMAND (BlockAddress
, 0, P30_CMD_BLOCK_ERASE_SETUP
);
359 SEND_NOR_COMMAND (BlockAddress
, 0, P30_CMD_BLOCK_ERASE_CONFIRM
);
360 // Wait until the status register gives us the all clear
361 Status
= NorFlashReadStatusRegister( BlockAddress
);
363 if (EFI_ERROR(Status
)) {
364 DEBUG((DEBUG_BLKIO
, "EraseSingleBlock(BlockAddress=0x%08x) = '%r'\n", BlockAddress
, Status
));
370 * The following function presumes that the block has already been unlocked.
373 NorFlashUnlockAndEraseSingleBlock (
374 IN UINTN BlockAddress
379 // Unlock the block if we have to
380 Status
= NorFlashUnlockSingleBlockIfNecessary (BlockAddress
);
381 if (!EFI_ERROR(Status
)) {
382 Status
= NorFlashEraseSingleBlock(BlockAddress
);
390 NorFlashWriteSingleWord (
391 IN UINTN WordAddress
,
396 volatile UINT32
*Data
;
398 // Prepare the read address
399 Data
= (UINT32
*)WordAddress
;
401 // Request a write single word command
402 SEND_NOR_COMMAND( WordAddress
, 0, P30_CMD_WORD_PROGRAM_SETUP
);
404 // Store the word into NOR Flash;
407 // Wait for the write to complete and then check for any errors; i.e. check the Status Register
408 Status
= NorFlashReadStatusRegister( WordAddress
);
414 * Writes data to the NOR Flash using the Buffered Programming method.
416 * The maximum size of the on-chip buffer is 32-words, because of hardware restrictions.
417 * Therefore this function will only handle buffers up to 32 words or 128 bytes.
418 * To deal with larger buffers, call this function again.
420 * This function presumes that both the TargetAddress and the TargetAddress+BufferSize
421 * exist entirely within the NOR Flash. Therefore these conditions will not be checked here.
423 * In buffered programming, if the target address not at the beginning of a 32-bit word boundary,
424 * then programming time is doubled and power consumption is increased.
425 * Therefore, it is a requirement to align buffer writes to 32-bit word boundaries.
426 * i.e. the last 4 bits of the target start address must be zero: 0x......00
429 NorFlashWriteBuffer (
430 IN UINTN TargetAddress
,
431 IN UINTN BufferSizeInBytes
,
436 UINTN BufferSizeInWords
;
438 volatile UINT32
*Data
;
439 UINTN WaitForBuffer
= MAX_BUFFERED_PROG_ITERATIONS
;
440 BOOLEAN BufferAvailable
= FALSE
;
443 // Check that the target address does not cross a 32-word boundary.
444 if ( (TargetAddress
& BOUNDARY_OF_32_WORDS
) != 0 ) {
445 return EFI_INVALID_PARAMETER
;
448 // Check there are some data to program
449 if ( BufferSizeInBytes
== 0 ) {
450 return EFI_BUFFER_TOO_SMALL
;
453 // Check that the buffer size does not exceed the maximum hardware buffer size on chip.
454 if ( BufferSizeInBytes
> P30_MAX_BUFFER_SIZE_IN_BYTES
) {
455 return EFI_BAD_BUFFER_SIZE
;
458 // Check that the buffer size is a multiple of 32-bit words
459 if ( (BufferSizeInBytes
% 4) != 0 ) {
460 return EFI_BAD_BUFFER_SIZE
;
463 // Pre-programming conditions checked, now start the algorithm.
465 // Prepare the data destination address
466 Data
= (UINT32
*)TargetAddress
;
468 // Check the availability of the buffer
470 // Issue the Buffered Program Setup command
471 SEND_NOR_COMMAND( TargetAddress
, 0, P30_CMD_BUFFERED_PROGRAM_SETUP
);
473 // Read back the status register bit#7 from the same address
474 if ( ((*Data
) & P30_SR_BIT_WRITE
) == P30_SR_BIT_WRITE
) {
475 BufferAvailable
= TRUE
;
478 // Update the loop counter
481 } while (( WaitForBuffer
> 0 ) && ( BufferAvailable
== FALSE
));
483 // The buffer was not available for writing
484 if ( WaitForBuffer
== 0 ) {
485 return EFI_DEVICE_ERROR
;
488 // From now on we work in 32-bit words
489 BufferSizeInWords
= BufferSizeInBytes
/ (UINTN
)4;
491 // Write the word count, which is (buffer_size_in_words - 1),
492 // because word count 0 means one word.
493 SEND_NOR_COMMAND( TargetAddress
, 0, (BufferSizeInWords
- 1) );
495 // Write the data to the NOR Flash, advancing each address by 4 bytes
496 for( Count
=0; Count
<BufferSizeInWords
; Count
++, Data
++, Buffer
++ ) {
500 // Issue the Buffered Program Confirm command, to start the programming operation
501 SEND_NOR_COMMAND( TargetAddress
, 0, P30_CMD_BUFFERED_PROGRAM_CONFIRM
);
503 // Wait for the write to complete and then check for any errors; i.e. check the Status Register
504 Status
= NorFlashReadStatusRegister( TargetAddress
);
510 NorFlashWriteSingleBlock (
511 IN UINTN DeviceBaseAddress
,
513 IN UINT32
*DataBuffer
,
514 IN UINT32 BlockSizeInWords
517 EFI_STATUS Status
= EFI_SUCCESS
;
522 UINTN BuffersInBlock
;
523 UINTN RemainingWords
;
525 // Get the physical address of the block
526 BlockAddress
= GET_NOR_BLOCK_ADDRESS(DeviceBaseAddress
, Lba
, BlockSizeInWords
* 4);
528 Status
= NorFlashUnlockAndEraseSingleBlock( BlockAddress
);
529 if (EFI_ERROR(Status
)) {
530 DEBUG((EFI_D_ERROR
, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress
));
534 // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.
536 // Start writing from the first address at the start of the block
537 WordAddress
= BlockAddress
;
539 // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero
540 if ((WordAddress
& BOUNDARY_OF_32_WORDS
) == 0x00) {
542 // First, break the entire block into buffer-sized chunks.
543 BuffersInBlock
= (UINTN
)BlockSizeInWords
/ P30_MAX_BUFFER_SIZE_IN_BYTES
;
545 // Then feed each buffer chunk to the NOR Flash
547 BufferIndex
< BuffersInBlock
;
548 BufferIndex
++, WordAddress
+= P30_MAX_BUFFER_SIZE_IN_BYTES
, DataBuffer
+= P30_MAX_BUFFER_SIZE_IN_WORDS
550 Status
= NorFlashWriteBuffer ( WordAddress
, P30_MAX_BUFFER_SIZE_IN_BYTES
, DataBuffer
);
551 if (EFI_ERROR(Status
)) {
556 // Finally, finish off any remaining words that are less than the maximum size of the buffer
557 RemainingWords
= BlockSizeInWords
% P30_MAX_BUFFER_SIZE_IN_WORDS
;
559 if( RemainingWords
!= 0) {
560 Status
= NorFlashWriteBuffer ( WordAddress
, (RemainingWords
* 4), DataBuffer
);
561 if (EFI_ERROR(Status
)) {
567 // For now, use the single word programming algorithm
568 // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,
569 // i.e. which ends in the range 0x......01 - 0x......7F.
570 for( WordIndex
=0; WordIndex
<BlockSizeInWords
; WordIndex
++, DataBuffer
++, WordAddress
= WordAddress
+ 4 ) {
571 Status
= NorFlashWriteSingleWord( WordAddress
, *DataBuffer
);
572 if (EFI_ERROR(Status
)) {
579 if (EFI_ERROR(Status
)) {
580 DEBUG((EFI_D_ERROR
, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress
, Status
));
587 NorFlashWriteBlocks (
588 IN NOR_FLASH_INSTANCE
*Instance
,
590 IN UINTN BufferSizeInBytes
,
594 UINT32
*pWriteBuffer
;
595 EFI_STATUS Status
= EFI_SUCCESS
;
596 EFI_LBA CurrentBlock
;
597 UINT32 BlockSizeInWords
;
601 // The buffer must be valid
602 if (Buffer
== NULL
) {
603 return EFI_INVALID_PARAMETER
;
606 if( Instance
->Media
.ReadOnly
== TRUE
) {
607 return EFI_WRITE_PROTECTED
;
610 // We must have some bytes to read
611 DEBUG((DEBUG_BLKIO
, "NorFlashWriteBlocks: BufferSizeInBytes=0x%x\n", BufferSizeInBytes
));
612 if( BufferSizeInBytes
== 0 ) {
613 return EFI_BAD_BUFFER_SIZE
;
616 // The size of the buffer must be a multiple of the block size
617 DEBUG((DEBUG_BLKIO
, "NorFlashWriteBlocks: BlockSize in bytes =0x%x\n", Instance
->Media
.BlockSize
));
618 if ((BufferSizeInBytes
% Instance
->Media
.BlockSize
) != 0) {
619 return EFI_BAD_BUFFER_SIZE
;
622 // All blocks must be within the device
623 NumBlocks
= ((UINT32
)BufferSizeInBytes
) / Instance
->Media
.BlockSize
;
625 DEBUG((DEBUG_BLKIO
, "NorFlashWriteBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld.\n", NumBlocks
, Instance
->Media
.LastBlock
, Lba
));
627 if ( ( Lba
+ NumBlocks
) > ( Instance
->Media
.LastBlock
+ 1 ) ) {
628 DEBUG((EFI_D_ERROR
, "NorFlashWriteBlocks: ERROR - Write will exceed last block.\n"));
629 return EFI_INVALID_PARAMETER
;
632 BlockSizeInWords
= Instance
->Media
.BlockSize
/ 4;
634 // Because the target *Buffer is a pointer to VOID, we must put all the data into a pointer
635 // to a proper data type, so use *ReadBuffer
636 pWriteBuffer
= (UINT32
*)Buffer
;
639 for( BlockCount
=0; BlockCount
<NumBlocks
; BlockCount
++, CurrentBlock
++, pWriteBuffer
= pWriteBuffer
+ BlockSizeInWords
) {
641 DEBUG((DEBUG_BLKIO
, "NorFlashWriteBlocks: Writing block #%d\n", (UINTN
)CurrentBlock
));
643 Status
= NorFlashWriteSingleBlock( Instance
->BaseAddress
, CurrentBlock
, pWriteBuffer
, BlockSizeInWords
);
645 if (EFI_ERROR(Status
)) {
651 DEBUG((DEBUG_BLKIO
, "NorFlashWriteBlocks: Exit Status = \"%r\".\n", Status
));
658 IN NOR_FLASH_INSTANCE
*Instance
,
660 IN UINTN BufferSizeInBytes
,
667 // The buffer must be valid
668 if (Buffer
== NULL
) {
669 return EFI_INVALID_PARAMETER
;
672 // We must have some bytes to read
673 DEBUG((DEBUG_BLKIO
, "NorFlashReadBlocks: BufferSize=0x%x bytes.\n", BufferSizeInBytes
));
674 if( BufferSizeInBytes
== 0 ) {
675 return EFI_BAD_BUFFER_SIZE
;
678 // The size of the buffer must be a multiple of the block size
679 DEBUG((DEBUG_BLKIO
, "NorFlashReadBlocks: BlockSize=0x%x bytes.\n", Instance
->Media
.BlockSize
));
680 if ((BufferSizeInBytes
% Instance
->Media
.BlockSize
) != 0) {
681 return EFI_BAD_BUFFER_SIZE
;
684 // All blocks must be within the device
685 NumBlocks
= ((UINT32
)BufferSizeInBytes
) / Instance
->Media
.BlockSize
;
687 DEBUG((DEBUG_BLKIO
, "NorFlashReadBlocks: NumBlocks=%d, LastBlock=%ld, Lba=%ld\n", NumBlocks
, Instance
->Media
.LastBlock
, Lba
));
689 if ( ( Lba
+ NumBlocks
) > (Instance
->Media
.LastBlock
+ 1) ) {
690 DEBUG((EFI_D_ERROR
, "NorFlashReadBlocks: ERROR - Read will exceed last block\n"));
691 return EFI_INVALID_PARAMETER
;
694 // Get the address to start reading from
695 StartAddress
= GET_NOR_BLOCK_ADDRESS (Instance
->BaseAddress
,
697 Instance
->Media
.BlockSize
700 // Put the device into Read Array mode
701 SEND_NOR_COMMAND (Instance
->BaseAddress
, 0, P30_CMD_READ_ARRAY
);
704 CopyMem(Buffer
, (UINTN
*)StartAddress
, BufferSizeInBytes
);
712 IN NOR_FLASH_INSTANCE
*Instance
715 // As there is no specific RESET to perform, ensure that the devices is in the default Read Array mode
716 SEND_NOR_COMMAND( Instance
->BaseAddress
, 0, P30_CMD_READ_ARRAY
);
725 IN EFI_HANDLE ImageHandle
,
726 IN EFI_SYSTEM_TABLE
*SystemTable
731 NOR_FLASH_DESCRIPTION
* NorFlashDevices
;
732 UINT32 NorFlashDeviceCount
;
733 BOOLEAN ContainVariableStorage
;
735 Status
= NorFlashPlatformInitialization ();
736 if (EFI_ERROR(Status
)) {
737 DEBUG((EFI_D_ERROR
,"NorFlashInitialise: Fail to initialize Nor Flash devices\n"));
741 Status
= NorFlashPlatformGetDevices (&NorFlashDevices
,&NorFlashDeviceCount
);
742 if (EFI_ERROR(Status
)) {
743 DEBUG((EFI_D_ERROR
,"NorFlashInitialise: Fail to get Nor Flash devices\n"));
747 mNorFlashInstances
= AllocatePool(sizeof(NOR_FLASH_INSTANCE
*) * NorFlashDeviceCount
);
749 for (Index
= 0; Index
< NorFlashDeviceCount
; Index
++) {
750 // Check if this NOR Flash device contain the variable storage region
751 ContainVariableStorage
=
752 (NorFlashDevices
[Index
].BaseAddress
<= PcdGet32 (PcdFlashNvStorageVariableBase
)) &&
753 (PcdGet32 (PcdFlashNvStorageVariableBase
) + PcdGet32 (PcdFlashNvStorageVariableSize
) <= NorFlashDevices
[Index
].BaseAddress
+ NorFlashDevices
[Index
].Size
);
755 Status
= NorFlashCreateInstance (
756 NorFlashDevices
[Index
].BaseAddress
,
757 NorFlashDevices
[Index
].Size
,
759 NorFlashDevices
[Index
].BlockSize
,
760 ContainVariableStorage
,
761 &NorFlashDevices
[Index
].Guid
,
762 &mNorFlashInstances
[Index
]
764 if (EFI_ERROR(Status
)) {
765 DEBUG((EFI_D_ERROR
,"NorFlashInitialise: Fail to create instance for NorFlash[%d]\n",Index
));