• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 *
3 *  Copyright (c) 2011-2015, ARM Limited. All rights reserved.
4 *  Copyright (c) 2015, Hisilicon Limited. All rights reserved.
5 *  Copyright (c) 2015, Linaro Limited. All rights reserved.
6 *
7 *  This program and the accompanying materials
8 *  are licensed and made available under the terms and conditions of the BSD License
9 *  which accompanies this distribution.  The full text of the license may be found at
10 *  http://opensource.org/licenses/bsd-license.php
11 *
12 *  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 *
15 * Based on files under ArmPlatformPkg/Drivers/NorFlashDxe/
16 **/
17 
18 #include "FlashFvbDxe.h"
19 STATIC EFI_EVENT mFlashFvbVirtualAddrChangeEvent;
20 STATIC UINTN     mFlashNvStorageVariableBase;
21 
22 
23 //
24 // Global variable declarations
25 //
26 
27 FLASH_DESCRIPTION mFlashDevices[FLASH_DEVICE_COUNT] =
28 {
29     {
30         // UEFI Variable Services non-volatile storage
31         0xa4000000,
32         FixedPcdGet32(PcdFlashNvStorageVariableBase),
33         0x20000,
34         SIZE_64KB,
35         {0xCC2CBF29, 0x1498, 0x4CDD, {0x81, 0x71, 0xF8, 0xB6, 0xB4, 0x1D, 0x09, 0x09}}
36     }
37 
38 };
39 
40 FLASH_INSTANCE** mFlashInstances;
41 
42 FLASH_INSTANCE  mFlashInstanceTemplate =
43 {
44     FLASH_SIGNATURE, // Signature
45     NULL, // Handle ... NEED TO BE FILLED
46 
47     FALSE, // Initialized
48     NULL, // Initialize
49 
50     0, // DeviceBaseAddress ... NEED TO BE FILLED
51     0, // RegionBaseAddress ... NEED TO BE FILLED
52     0, // Size ... NEED TO BE FILLED
53     0, // StartLba
54 
55     {
56         EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision
57         NULL, // Media ... NEED TO BE FILLED
58         NULL, //NorFlashBlockIoReset
59         FlashBlockIoReadBlocks,
60         FlashBlockIoWriteBlocks,
61         FlashBlockIoFlushBlocks
62     }, // BlockIoProtocol
63 
64     {
65         0, // MediaId ... NEED TO BE FILLED
66         FALSE, // RemovableMedia
67         TRUE, // MediaPresent
68         FALSE, // LogicalPartition
69         FALSE, // ReadOnly
70         FALSE, // WriteCaching;
71         SIZE_64KB, // BlockSize ... NEED TO BE FILLED
72         4, //  IoAlign
73         0, // LastBlock ... NEED TO BE FILLED
74         0, // LowestAlignedLba
75         1, // LogicalBlocksPerPhysicalBlock
76     }, //Media;
77 
78     FALSE, // SupportFvb ... NEED TO BE FILLED
79     {
80         FvbGetAttributes,
81         FvbSetAttributes,
82         FvbGetPhysicalAddress,
83         FvbGetBlockSize,
84         FvbRead,
85         FvbWrite,
86         FvbEraseBlocks,
87         NULL, //ParentHandle
88     }, //  FvbProtoccol;
89 
90     {
91         {
92             {
93                 HARDWARE_DEVICE_PATH,
94                 HW_VENDOR_DP,
95                 {(UINT8)(sizeof(VENDOR_DEVICE_PATH)),
96                 (UINT8)((sizeof(VENDOR_DEVICE_PATH)) >> 8)},
97             },
98             { 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}, // GUID ... NEED TO BE FILLED
99         },
100         {
101             END_DEVICE_PATH_TYPE,
102             END_ENTIRE_DEVICE_PATH_SUBTYPE,
103             {sizeof (EFI_DEVICE_PATH_PROTOCOL),
104             0}
105         }
106     } // DevicePath
107 };
108 
109 HISI_SPI_FLASH_PROTOCOL* mFlash;
110 
111 ///
112 /// The Firmware Volume Block Protocol is the low-level interface
113 /// to a firmware volume. File-level access to a firmware volume
114 /// should not be done using the Firmware Volume Block Protocol.
115 /// Normal access to a firmware volume must use the Firmware
116 /// Volume Protocol. Typically, only the file system driver that
117 /// produces the Firmware Volume Protocol will bind to the
118 /// Firmware Volume Block Protocol.
119 ///
120 
121 /**
122   Initialises the FV Header and Variable Store Header
123   to support variable operations.
124 
125   @param[in]  Ptr - Location to initialise the headers
126 
127 **/
128 EFI_STATUS
InitializeFvAndVariableStoreHeaders(IN FLASH_INSTANCE * Instance)129 InitializeFvAndVariableStoreHeaders (
130     IN FLASH_INSTANCE* Instance
131 )
132 {
133     EFI_STATUS                          Status;
134     VOID*                               Headers;
135     UINTN                               HeadersLength;
136     EFI_FIRMWARE_VOLUME_HEADER*          FirmwareVolumeHeader;
137     VARIABLE_STORE_HEADER*               VariableStoreHeader;
138 
139     if (!Instance->Initialized && Instance->Initialize)
140     {
141         Instance->Initialize (Instance);
142     }
143 
144     HeadersLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY) + sizeof(VARIABLE_STORE_HEADER);
145     Headers = AllocateZeroPool(HeadersLength);
146 
147     // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
148     ASSERT(PcdGet32(PcdFlashNvStorageVariableBase) + PcdGet32(PcdFlashNvStorageVariableSize) == PcdGet32(PcdFlashNvStorageFtwWorkingBase));
149     ASSERT(PcdGet32(PcdFlashNvStorageFtwWorkingBase) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) == PcdGet32(PcdFlashNvStorageFtwSpareBase));
150 
151     // Check if the size of the area is at least one block size
152     ASSERT((PcdGet32(PcdFlashNvStorageVariableSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageVariableSize) / Instance->Media.BlockSize > 0));
153     ASSERT((PcdGet32(PcdFlashNvStorageFtwWorkingSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingSize) / Instance->Media.BlockSize > 0));
154     ASSERT((PcdGet32(PcdFlashNvStorageFtwSpareSize) > 0) && ((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize) / Instance->Media.BlockSize > 0));
155 
156     // Ensure the Variable area Base Addresses are aligned on a block size boundaries
157     ASSERT((UINT32)PcdGet32(PcdFlashNvStorageVariableBase) % Instance->Media.BlockSize == 0);
158     ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwWorkingBase) % Instance->Media.BlockSize == 0);
159     ASSERT((UINT32)PcdGet32(PcdFlashNvStorageFtwSpareBase) % Instance->Media.BlockSize == 0);
160 
161     //
162     // EFI_FIRMWARE_VOLUME_HEADER
163     //
164     FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Headers;
165     CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
166     FirmwareVolumeHeader->FvLength =
167         PcdGet32(PcdFlashNvStorageVariableSize) +
168         PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
169         PcdGet32(PcdFlashNvStorageFtwSpareSize);
170     FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
171     FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2) (
172                                            EFI_FVB2_READ_ENABLED_CAP   | // Reads may be enabled
173                                            EFI_FVB2_READ_STATUS        | // Reads are currently enabled
174                                            EFI_FVB2_STICKY_WRITE       | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
175                                            EFI_FVB2_MEMORY_MAPPED      | // It is memory mapped
176                                            EFI_FVB2_ERASE_POLARITY     | // After erasure all bits take this value (i.e. '1')
177                                            EFI_FVB2_WRITE_STATUS       | // Writes are currently enabled
178                                            EFI_FVB2_WRITE_ENABLED_CAP    // Writes may be enabled
179                                        );
180     FirmwareVolumeHeader->HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER) + sizeof(EFI_FV_BLOCK_MAP_ENTRY);
181     FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
182     FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->Media.LastBlock + 1;
183     FirmwareVolumeHeader->BlockMap[0].Length      = Instance->Media.BlockSize;
184     FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
185     FirmwareVolumeHeader->BlockMap[1].Length      = 0;
186     FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16*)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
187 
188     //
189     // VARIABLE_STORE_HEADER
190     //
191     VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)Headers + (UINTN)FirmwareVolumeHeader->HeaderLength);
192     CopyGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid);
193     VariableStoreHeader->Size = PcdGet32(PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
194     VariableStoreHeader->Format            = VARIABLE_STORE_FORMATTED;
195     VariableStoreHeader->State             = VARIABLE_STORE_HEALTHY;
196 
197     // Install the combined super-header in the NorFlash
198     Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
199 
200     FreePool (Headers);
201     return Status;
202 }
203 
204 /**
205   Check the integrity of firmware volume header.
206 
207   @param[in] FwVolHeader - A pointer to a firmware volume header
208 
209   @retval  EFI_SUCCESS   - The firmware volume is consistent
210   @retval  EFI_NOT_FOUND - The firmware volume has been corrupted.
211 
212 **/
213 EFI_STATUS
ValidateFvHeader(IN FLASH_INSTANCE * Instance)214 ValidateFvHeader (
215     IN  FLASH_INSTANCE* Instance
216 )
217 {
218     UINT16                      Checksum;
219     EFI_FIRMWARE_VOLUME_HEADER* FwVolHeader;
220     VARIABLE_STORE_HEADER*      VariableStoreHeader;
221     UINTN                       VariableStoreLength;
222     UINTN                       FvLength;
223 
224     FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Instance->RegionBaseAddress;
225 
226     FvLength = PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) +
227                PcdGet32(PcdFlashNvStorageFtwSpareSize);
228 
229     //
230     // Verify the header revision, header signature, length
231     // Length of FvBlock cannot be 2**64-1
232     // HeaderLength cannot be an odd number
233     //
234     if (   (FwVolHeader->Revision  != EFI_FVH_REVISION)
235            || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
236            || (FwVolHeader->FvLength  != FvLength)
237        )
238     {
239         DEBUG ((EFI_D_ERROR, "ValidateFvHeader: No Firmware Volume header present\n"));
240         return EFI_NOT_FOUND;
241     }
242 
243     // Check the Firmware Volume Guid
244     if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE )
245     {
246         DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Firmware Volume Guid non-compatible\n"));
247         return EFI_NOT_FOUND;
248     }
249 
250     // Verify the header checksum
251     Checksum = CalculateSum16((UINT16*)FwVolHeader, FwVolHeader->HeaderLength);
252     if (Checksum != 0)
253     {
254         DEBUG ((EFI_D_ERROR, "ValidateFvHeader: FV checksum is invalid (Checksum:0x%X)\n", Checksum));
255         return EFI_NOT_FOUND;
256     }
257 
258     VariableStoreHeader = (VARIABLE_STORE_HEADER*)((UINTN)FwVolHeader + (UINTN)FwVolHeader->HeaderLength);
259 
260     // Check the Variable Store Guid
261     if ( CompareGuid (&VariableStoreHeader->Signature, &gEfiVariableGuid) == FALSE )
262     {
263         DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Guid non-compatible\n"));
264         return EFI_NOT_FOUND;
265     }
266 
267     VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
268     if (VariableStoreHeader->Size != VariableStoreLength)
269     {
270         DEBUG ((EFI_D_ERROR, "ValidateFvHeader: Variable Store Length does not match\n"));
271         return EFI_NOT_FOUND;
272     }
273 
274     return EFI_SUCCESS;
275 }
276 
277 /**
278  The FvbGetAttributes() function retrieves the attributes and
279  current settings of the block.
280 
281  @param This         Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
282 
283  @param Attributes   Pointer to EFI_FVB_ATTRIBUTES_2 in which the attributes and
284                      current settings are returned.
285                      Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
286 
287  @retval EFI_SUCCESS The firmware volume attributes were returned.
288 
289  **/
290 EFI_STATUS
291 EFIAPI
FvbGetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,OUT EFI_FVB_ATTRIBUTES_2 * Attributes)292 FvbGetAttributes(
293     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*    This,
294     OUT       EFI_FVB_ATTRIBUTES_2*                   Attributes
295 )
296 {
297     EFI_FVB_ATTRIBUTES_2  FlashFvbAttributes;
298     FLASH_INSTANCE*                 Instance;
299 
300     Instance = INSTANCE_FROM_FVB_THIS(This);
301 
302     FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2) (
303 
304                              EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
305                              EFI_FVB2_READ_STATUS      | // Reads are currently enabled
306                              EFI_FVB2_STICKY_WRITE     | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
307                              EFI_FVB2_MEMORY_MAPPED    | // It is memory mapped
308                              EFI_FVB2_ERASE_POLARITY     // After erasure all bits take this value (i.e. '1')
309 
310                          );
311 
312     // Check if it is write protected
313     if (Instance->Media.ReadOnly != TRUE)
314     {
315 
316         FlashFvbAttributes = FlashFvbAttributes         |
317                              EFI_FVB2_WRITE_STATUS      | // Writes are currently enabled
318                              EFI_FVB2_WRITE_ENABLED_CAP;  // Writes may be enabled
319     }
320 
321     *Attributes = FlashFvbAttributes;
322 
323     return EFI_SUCCESS;
324 }
325 
326 /**
327  The FvbSetAttributes() function sets configurable firmware volume attributes
328  and returns the new settings of the firmware volume.
329 
330 
331  @param This                     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
332 
333  @param Attributes               On input, Attributes is a pointer to EFI_FVB_ATTRIBUTES_2
334                                  that contains the desired firmware volume settings.
335                                  On successful return, it contains the new settings of
336                                  the firmware volume.
337                                  Type EFI_FVB_ATTRIBUTES_2 is defined in EFI_FIRMWARE_VOLUME_HEADER.
338 
339  @retval EFI_SUCCESS             The firmware volume attributes were returned.
340 
341  @retval EFI_INVALID_PARAMETER   The attributes requested are in conflict with the capabilities
342                                  as declared in the firmware volume header.
343 
344  **/
345 EFI_STATUS
346 EFIAPI
FvbSetAttributes(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN OUT EFI_FVB_ATTRIBUTES_2 * Attributes)347 FvbSetAttributes(
348     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*  This,
349     IN OUT    EFI_FVB_ATTRIBUTES_2*                 Attributes
350 )
351 {
352     DEBUG ((EFI_D_ERROR, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
353     return EFI_UNSUPPORTED;
354 }
355 
356 /**
357  The GetPhysicalAddress() function retrieves the base address of
358  a memory-mapped firmware volume. This function should be called
359  only for memory-mapped firmware volumes.
360 
361  @param This               Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
362 
363  @param Address            Pointer to a caller-allocated
364                            EFI_PHYSICAL_ADDRESS that, on successful
365                            return from GetPhysicalAddress(), contains the
366                            base address of the firmware volume.
367 
368  @retval EFI_SUCCESS       The firmware volume base address was returned.
369 
370  @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped.
371 
372  **/
373 EFI_STATUS
374 EFIAPI
FvbGetPhysicalAddress(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,OUT EFI_PHYSICAL_ADDRESS * Address)375 FvbGetPhysicalAddress (
376     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*  This,
377     OUT       EFI_PHYSICAL_ADDRESS*                 Address
378 )
379 {
380 
381     if(NULL == Address)
382     {
383         return EFI_UNSUPPORTED;
384     };
385 
386     *Address = mFlashNvStorageVariableBase;
387     return EFI_SUCCESS;
388 }
389 
390 /**
391  The GetBlockSize() function retrieves the size of the requested
392  block. It also returns the number of additional blocks with
393  the identical size. The GetBlockSize() function is used to
394  retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER).
395 
396 
397  @param This                     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
398 
399  @param Lba                      Indicates the block for which to return the size.
400 
401  @param BlockSize                Pointer to a caller-allocated UINTN in which
402                                  the size of the block is returned.
403 
404  @param NumberOfBlocks           Pointer to a caller-allocated UINTN in
405                                  which the number of consecutive blocks,
406                                  starting with Lba, is returned. All
407                                  blocks in this range have a size of
408                                  BlockSize.
409 
410 
411  @retval EFI_SUCCESS             The firmware volume base address was returned.
412 
413  @retval EFI_INVALID_PARAMETER   The requested LBA is out of range.
414 
415  **/
416 EFI_STATUS
417 EFIAPI
FvbGetBlockSize(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,OUT UINTN * BlockSize,OUT UINTN * NumberOfBlocks)418 FvbGetBlockSize (
419     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*  This,
420     IN        EFI_LBA                              Lba,
421     OUT       UINTN*                                BlockSize,
422     OUT       UINTN*                                NumberOfBlocks
423 )
424 {
425     EFI_STATUS Status;
426     FLASH_INSTANCE* Instance;
427 
428     Instance = INSTANCE_FROM_FVB_THIS(This);
429 
430     if (Lba > Instance->Media.LastBlock)
431     {
432         Status = EFI_INVALID_PARAMETER;
433     }
434     else
435     {
436         // This is easy because in this platform each NorFlash device has equal sized blocks.
437         *BlockSize = (UINTN) Instance->Media.BlockSize;
438         *NumberOfBlocks = (UINTN) (Instance->Media.LastBlock - Lba + 1);
439 
440 
441         Status = EFI_SUCCESS;
442     }
443 
444     return Status;
445 }
446 
447 /**
448  Reads the specified number of bytes into a buffer from the specified block.
449 
450  The Read() function reads the requested number of bytes from the
451  requested block and stores them in the provided buffer.
452  Implementations should be mindful that the firmware volume
453  might be in the ReadDisabled state. If it is in this state,
454  the Read() function must return the status code
455  EFI_ACCESS_DENIED without modifying the contents of the
456  buffer. The Read() function must also prevent spanning block
457  boundaries. If a read is requested that would span a block
458  boundary, the read must read up to the boundary but not
459  beyond. The output parameter NumBytes must be set to correctly
460  indicate the number of bytes actually read. The caller must be
461  aware that a read may be partially completed.
462 
463  @param This                 Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
464 
465  @param Lba                  The starting logical block index from which to read.
466 
467  @param Offset               Offset into the block at which to begin reading.
468 
469  @param NumBytes             Pointer to a UINTN.
470                              At entry, *NumBytes contains the total size of the buffer.
471                              At exit, *NumBytes contains the total number of bytes read.
472 
473  @param Buffer               Pointer to a caller-allocated buffer that will be used
474                              to hold the data that is read.
475 
476  @retval EFI_SUCCESS         The firmware volume was read successfully,  and contents are
477                              in Buffer.
478 
479  @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary.
480                              On output, NumBytes contains the total number of bytes
481                              returned in Buffer.
482 
483  @retval EFI_ACCESS_DENIED   The firmware volume is in the ReadDisabled state.
484 
485  @retval EFI_DEVICE_ERROR    The block device is not functioning correctly and could not be read.
486 
487  **/
488 EFI_STATUS
489 EFIAPI
FvbRead(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Offset,IN OUT UINTN * NumBytes,IN OUT UINT8 * Buffer)490 FvbRead (
491     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*   This,
492     IN        EFI_LBA                               Lba,
493     IN        UINTN                                 Offset,
494     IN OUT    UINTN*                                 NumBytes,
495     IN OUT    UINT8*                                 Buffer
496 )
497 {
498     EFI_STATUS                    Status;
499     UINTN                      BlockSize;
500     FLASH_INSTANCE*             Instance;
501 
502     UINTN                   StartAddress;
503     UINTN                    ReadAddress;
504 
505     Instance = INSTANCE_FROM_FVB_THIS(This);
506 
507     if (!Instance->Initialized && Instance->Initialize)
508     {
509         if (EfiAtRuntime ()) {
510             DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__));
511             return EFI_UNSUPPORTED;
512         }
513 
514         Instance->Initialize(Instance);
515     }
516 
517     Status = EFI_SUCCESS;
518 
519     // Cache the block size to avoid de-referencing pointers all the time
520     BlockSize = Instance->Media.BlockSize;
521 
522     // The read must not span block boundaries.
523     // We need to check each variable individually because adding two large values together overflows.
524     if ((Offset               >= BlockSize) ||
525         (*NumBytes            >  BlockSize) ||
526         ((Offset + *NumBytes) >  BlockSize))
527     {
528         DEBUG ((EFI_D_ERROR, "[%a]:[%dL] ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", __FUNCTION__, __LINE__, Offset, *NumBytes, BlockSize ));
529         return EFI_BAD_BUFFER_SIZE;
530     }
531 
532     // We must have some bytes to read
533     if (*NumBytes == 0)
534     {
535         return EFI_BAD_BUFFER_SIZE;
536     }
537 
538     // Get the address to start reading from
539     StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress,
540                                       Lba,
541                                       BlockSize
542                                      );
543     ReadAddress = StartAddress - Instance->DeviceBaseAddress + Offset;
544 
545     Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, *NumBytes);
546     if (EFI_SUCCESS != Status)
547     {
548         // Return one of the pre-approved error statuses
549         Status = EFI_DEVICE_ERROR;
550         return Status;
551     }
552 
553 
554     return Status;
555 }
556 
557 /**
558  Writes the specified number of bytes from the input buffer to the block.
559 
560  The Write() function writes the specified number of bytes from
561  the provided buffer to the specified block and offset. If the
562  firmware volume is sticky write, the caller must ensure that
563  all the bits of the specified range to write are in the
564  EFI_FVB_ERASE_POLARITY state before calling the Write()
565  function, or else the result will be unpredictable. This
566  unpredictability arises because, for a sticky-write firmware
567  volume, a write may negate a bit in the EFI_FVB_ERASE_POLARITY
568  state but cannot flip it back again.  Before calling the
569  Write() function,  it is recommended for the caller to first call
570  the EraseBlocks() function to erase the specified block to
571  write. A block erase cycle will transition bits from the
572  (NOT)EFI_FVB_ERASE_POLARITY state back to the
573  EFI_FVB_ERASE_POLARITY state. Implementations should be
574  mindful that the firmware volume might be in the WriteDisabled
575  state. If it is in this state, the Write() function must
576  return the status code EFI_ACCESS_DENIED without modifying the
577  contents of the firmware volume. The Write() function must
578  also prevent spanning block boundaries. If a write is
579  requested that spans a block boundary, the write must store up
580  to the boundary but not beyond. The output parameter NumBytes
581  must be set to correctly indicate the number of bytes actually
582  written. The caller must be aware that a write may be
583  partially completed. All writes, partial or otherwise, must be
584  fully flushed to the hardware before the Write() service
585  returns.
586 
587  @param This                 Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance.
588 
589  @param Lba                  The starting logical block index to write to.
590 
591  @param Offset               Offset into the block at which to begin writing.
592 
593  @param NumBytes             The pointer to a UINTN.
594                              At entry, *NumBytes contains the total size of the buffer.
595                              At exit, *NumBytes contains the total number of bytes actually written.
596 
597  @param Buffer               The pointer to a caller-allocated buffer that contains the source for the write.
598 
599  @retval EFI_SUCCESS         The firmware volume was written successfully.
600 
601  @retval EFI_BAD_BUFFER_SIZE The write was attempted across an LBA boundary.
602                              On output, NumBytes contains the total number of bytes
603                              actually written.
604 
605  @retval EFI_ACCESS_DENIED   The firmware volume is in the WriteDisabled state.
606 
607  @retval EFI_DEVICE_ERROR    The block device is malfunctioning and could not be written.
608 
609 
610  **/
611 EFI_STATUS
612 EFIAPI
FvbWrite(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,IN EFI_LBA Lba,IN UINTN Offset,IN OUT UINTN * NumBytes,IN UINT8 * Buffer)613 FvbWrite (
614     IN CONST  EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL*   This,
615     IN        EFI_LBA                               Lba,
616     IN        UINTN                                 Offset,
617     IN OUT    UINTN*                                 NumBytes,
618     IN        UINT8*                                 Buffer
619 )
620 {
621     EFI_STATUS                     Status;
622     UINTN                       BlockSize;
623     FLASH_INSTANCE*              Instance;
624     UINTN                    BlockAddress;
625     UINTN                    WriteAddress;
626 
627     Instance = INSTANCE_FROM_FVB_THIS(This);
628     if (NULL == Instance)
629     {
630         return EFI_INVALID_PARAMETER;
631 
632     }
633 
634     if (!Instance->Initialized && Instance->Initialize)
635     {
636         if (EfiAtRuntime ()) {
637             DEBUG ((EFI_D_ERROR, "[%a]:[%dL] Initialize at runtime is not supported!\n", __FUNCTION__, __LINE__));
638             return EFI_UNSUPPORTED;
639         }
640 
641         Instance->Initialize(Instance);
642     }
643 
644     Status = EFI_SUCCESS;
645 
646     // Detect WriteDisabled state
647     if (Instance->Media.ReadOnly == TRUE)
648     {
649         DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - Can not write: Device is in WriteDisabled state.\n"));
650         // It is in WriteDisabled state, return an error right away
651         return EFI_ACCESS_DENIED;
652     }
653 
654     // Cache the block size to avoid de-referencing pointers all the time
655     BlockSize = Instance->Media.BlockSize;
656 
657     // The write must not span block boundaries.
658     // We need to check each variable individually because adding two large values together overflows.
659     if ( ( Offset               >= BlockSize ) ||
660          ( *NumBytes            >  BlockSize ) ||
661          ( (Offset + *NumBytes) >  BlockSize )    )
662     {
663         DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
664         return EFI_BAD_BUFFER_SIZE;
665     }
666 
667     // We must have some bytes to write
668     if (*NumBytes == 0)
669     {
670         DEBUG ((EFI_D_ERROR, "FvbWrite: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize ));
671         return EFI_BAD_BUFFER_SIZE;
672     }
673 
674     BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSize);
675     WriteAddress = BlockAddress - Instance->DeviceBaseAddress + Offset;
676 
677     Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, *NumBytes);
678     if (EFI_SUCCESS != Status)
679     {
680         DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
681         return Status;
682     }
683 
684     return Status;
685 
686 }
687 
688 /**
689  Erases and initialises a firmware volume block.
690 
691  The EraseBlocks() function erases one or more blocks as denoted
692  by the variable argument list. The entire parameter list of
693  blocks must be verified before erasing any blocks. If a block is
694  requested that does not exist within the associated firmware
695  volume (it has a larger index than the last block of the
696  firmware volume), the EraseBlocks() function must return the
697  status code EFI_INVALID_PARAMETER without modifying the contents
698  of the firmware volume. Implementations should be mindful that
699  the firmware volume might be in the WriteDisabled state. If it
700  is in this state, the EraseBlocks() function must return the
701  status code EFI_ACCESS_DENIED without modifying the contents of
702  the firmware volume. All calls to EraseBlocks() must be fully
703  flushed to the hardware before the EraseBlocks() service
704  returns.
705 
706  @param This                     Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL
707  instance.
708 
709  @param ...                      The variable argument list is a list of tuples.
710                                  Each tuple describes a range of LBAs to erase
711                                  and consists of the following:
712                                  - An EFI_LBA that indicates the starting LBA
713                                  - A UINTN that indicates the number of blocks to erase.
714 
715                                  The list is terminated with an EFI_LBA_LIST_TERMINATOR.
716                                  For example, the following indicates that two ranges of blocks
717                                  (5-7 and 10-11) are to be erased:
718                                  EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR);
719 
720  @retval EFI_SUCCESS             The erase request successfully completed.
721 
722  @retval EFI_ACCESS_DENIED       The firmware volume is in the WriteDisabled state.
723 
724  @retval EFI_DEVICE_ERROR        The block device is not functioning correctly and could not be written.
725                                  The firmware device may have been partially erased.
726 
727  @retval EFI_INVALID_PARAMETER   One or more of the LBAs listed in the variable argument list do
728                                  not exist in the firmware volume.
729 
730  **/
731 EFI_STATUS
732 EFIAPI
FvbEraseBlocks(IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL * This,...)733 FvbEraseBlocks (
734     IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL* This,
735     ...
736 )
737 {
738     EFI_STATUS  Status;
739     VA_LIST     Args;
740     UINTN       BlockAddress; // Physical address of Lba to erase
741     EFI_LBA     StartingLba; // Lba from which we start erasing
742     UINTN       NumOfLba; // Number of Lba blocks to erase
743     FLASH_INSTANCE* Instance;
744 
745     Instance = INSTANCE_FROM_FVB_THIS(This);
746 
747     Status = EFI_SUCCESS;
748 
749     // Detect WriteDisabled state
750     if (Instance->Media.ReadOnly == TRUE)
751     {
752         // Firmware volume is in WriteDisabled state
753         return EFI_ACCESS_DENIED;
754     }
755 
756     // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
757     VA_START (Args, This);
758     do
759     {
760         // Get the Lba from which we start erasing
761         StartingLba = VA_ARG (Args, EFI_LBA);
762 
763         // Have we reached the end of the list?
764         if (StartingLba == EFI_LBA_LIST_TERMINATOR)
765         {
766             //Exit the while loop
767             break;
768         }
769 
770         // How many Lba blocks are we requested to erase?
771         NumOfLba = VA_ARG (Args, UINT32);
772 
773         // All blocks must be within range
774         if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->Media.LastBlock))
775         {
776             VA_END (Args);
777             Status = EFI_INVALID_PARAMETER;
778             goto EXIT;
779         }
780     }
781     while (TRUE);
782     VA_END (Args);
783 
784     //
785     // To get here, all must be ok, so start erasing
786     //
787     VA_START (Args, This);
788     do
789     {
790         // Get the Lba from which we start erasing
791         StartingLba = VA_ARG (Args, EFI_LBA);
792 
793         // Have we reached the end of the list?
794         if (StartingLba == EFI_LBA_LIST_TERMINATOR)
795         {
796             // Exit the while loop
797             break;
798         }
799 
800         // How many Lba blocks are we requested to erase?
801         NumOfLba = VA_ARG (Args, UINT32);
802 
803         // Go through each one and erase it
804         while (NumOfLba > 0)
805         {
806 
807             // Get the physical address of Lba to erase
808             BlockAddress = GET_BLOCK_ADDRESS (
809                                Instance->RegionBaseAddress,
810                                Instance->StartLba + StartingLba,
811                                Instance->Media.BlockSize
812                            );
813 
814             // Erase it
815 
816             Status = FlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
817             if (EFI_ERROR(Status))
818             {
819                 VA_END (Args);
820                 Status = EFI_DEVICE_ERROR;
821                 goto EXIT;
822             }
823 
824             // Move to the next Lba
825             StartingLba++;
826             NumOfLba--;
827         }
828     }
829     while (TRUE);
830     VA_END (Args);
831 
832 EXIT:
833     return Status;
834 }
835 
836 EFI_STATUS
837 EFIAPI
FvbInitialize(IN FLASH_INSTANCE * Instance)838 FvbInitialize (
839     IN FLASH_INSTANCE* Instance
840 )
841 {
842     EFI_STATUS  Status;
843     UINT32      FvbNumLba;
844 
845     Instance->Initialized = TRUE;
846     mFlashNvStorageVariableBase = FixedPcdGet32 (PcdFlashNvStorageVariableBase);
847 
848     // Set the index of the first LBA for the FVB
849     Instance->StartLba = (PcdGet32 (PcdFlashNvStorageVariableBase) - Instance->RegionBaseAddress) / Instance->Media.BlockSize;
850 
851     // Determine if there is a valid header at the beginning of the Flash
852     Status = ValidateFvHeader (Instance);
853     if (EFI_ERROR(Status))
854     {
855         // There is no valid header, so time to install one.
856         // Erase all the Flash that is reserved for variable storage
857         FvbNumLba = (PcdGet32(PcdFlashNvStorageVariableSize) + PcdGet32(PcdFlashNvStorageFtwWorkingSize) + (UINT32)PcdGet32(PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;
858         Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);
859         if (EFI_ERROR(Status))
860         {
861             return Status;
862         }
863 
864         // Install all appropriate headers
865         Status = InitializeFvAndVariableStoreHeaders (Instance);
866         if (EFI_ERROR(Status))
867         {
868             return Status;
869         }
870     }
871     return Status;
872 }
873 
874 
875 EFI_STATUS
FlashPlatformGetDevices(OUT FLASH_DESCRIPTION ** FlashDevices,OUT UINT32 * Count)876 FlashPlatformGetDevices (
877     OUT FLASH_DESCRIPTION**   FlashDevices,
878     OUT UINT32*                  Count
879 )
880 {
881     if ((FlashDevices == NULL) || (Count == NULL))
882     {
883         return EFI_INVALID_PARAMETER;
884     }
885 
886     *FlashDevices = mFlashDevices;
887     *Count = FLASH_DEVICE_COUNT;
888 
889     return EFI_SUCCESS;
890 }
891 
892 
893 EFI_STATUS
FlashCreateInstance(IN UINTN FlashDeviceBase,IN UINTN FlashRegionBase,IN UINTN FlashSize,IN UINT32 MediaId,IN UINT32 BlockSize,IN BOOLEAN SupportFvb,IN CONST GUID * FlashGuid,OUT FLASH_INSTANCE ** FlashInstance)894 FlashCreateInstance (
895     IN UINTN                  FlashDeviceBase,
896     IN UINTN                  FlashRegionBase,
897     IN UINTN                  FlashSize,
898     IN UINT32                 MediaId,
899     IN UINT32                 BlockSize,
900     IN BOOLEAN                SupportFvb,
901     IN CONST GUID*             FlashGuid,
902     OUT FLASH_INSTANCE**  FlashInstance
903 )
904 {
905     EFI_STATUS Status;
906     FLASH_INSTANCE* Instance;
907 
908     if (FlashInstance == NULL)
909     {
910         return EFI_INVALID_PARAMETER;
911     }
912 
913     Instance = AllocateRuntimeCopyPool (sizeof(FLASH_INSTANCE), &mFlashInstanceTemplate);
914     if (Instance == NULL)
915     {
916         return EFI_INVALID_PARAMETER;
917     }
918 
919     Instance->DeviceBaseAddress = FlashDeviceBase;
920     Instance->RegionBaseAddress = FlashRegionBase;
921     Instance->Size = FlashSize;
922 
923     Instance->BlockIoProtocol.Media = &Instance->Media;
924     Instance->Media.MediaId = MediaId;
925     Instance->Media.BlockSize = BlockSize;
926     Instance->Media.LastBlock = (FlashSize / BlockSize) - 1;
927 
928     CopyGuid (&Instance->DevicePath.Vendor.Guid, FlashGuid);
929 
930     if (SupportFvb)
931     {
932         Instance->SupportFvb = TRUE;
933         Instance->Initialize = FvbInitialize;
934 
935         Status = gBS->InstallMultipleProtocolInterfaces (
936                      &Instance->Handle,
937                      &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
938                      &gEfiBlockIoProtocolGuid,  &Instance->BlockIoProtocol,
939                      &gEfiFirmwareVolumeBlockProtocolGuid, &Instance->FvbProtocol,
940                      NULL
941                  );
942 
943         if (EFI_ERROR(Status))
944         {
945             FreePool(Instance);
946             return Status;
947         }
948     }
949     else
950     {
951         Instance->Initialized = TRUE;
952 
953         Status = gBS->InstallMultipleProtocolInterfaces (
954                      &Instance->Handle,
955                      &gEfiDevicePathProtocolGuid, &Instance->DevicePath,
956                      &gEfiBlockIoProtocolGuid,  &Instance->BlockIoProtocol,
957                      NULL
958                  );
959         if (EFI_ERROR(Status))
960         {
961             FreePool(Instance);
962             return Status;
963         }
964     }
965 
966     *FlashInstance = Instance;
967     return Status;
968 }
969 
970 EFI_STATUS
FlashUnlockSingleBlockIfNecessary(IN FLASH_INSTANCE * Instance,IN UINTN BlockAddress)971 FlashUnlockSingleBlockIfNecessary (
972     IN FLASH_INSTANCE*           Instance,
973     IN UINTN                  BlockAddress
974 )
975 {
976     return EFI_SUCCESS;
977 }
978 
979 
980 EFI_STATUS
FlashEraseSingleBlock(IN FLASH_INSTANCE * Instance,IN UINTN BlockAddress)981 FlashEraseSingleBlock (
982     IN FLASH_INSTANCE*           Instance,
983     IN UINTN                  BlockAddress
984 )
985 {
986     EFI_STATUS            Status;
987     UINTN                 EraseAddress;
988 
989     Status = EFI_SUCCESS;
990     EraseAddress = BlockAddress - Instance->DeviceBaseAddress;
991 
992     Status = mFlash->Erase(mFlash, (UINT32)EraseAddress, Instance->Media.BlockSize);
993     if (EFI_SUCCESS != Status)
994     {
995         DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
996         return Status;
997     }
998 
999     return EFI_SUCCESS;
1000 }
1001 
1002 /**
1003  * The following function presumes that the block has already been unlocked.
1004  **/
1005 EFI_STATUS
FlashUnlockAndEraseSingleBlock(IN FLASH_INSTANCE * Instance,IN UINTN BlockAddress)1006 FlashUnlockAndEraseSingleBlock (
1007     IN FLASH_INSTANCE*     Instance,
1008     IN UINTN                  BlockAddress
1009 )
1010 {
1011     EFI_STATUS      Status;
1012     UINTN           Index;
1013 
1014     Index = 0;
1015     // The block erase might fail a first time (SW bug ?). Retry it ...
1016     do
1017     {
1018         // Unlock the block if we have to
1019         Status = FlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);
1020         if (!EFI_ERROR(Status))
1021         {
1022             Status = FlashEraseSingleBlock (Instance, BlockAddress);
1023         }
1024         Index++;
1025     }
1026     while ((Index < FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));
1027 
1028     if (Index == FLASH_ERASE_RETRY)
1029     {
1030         DEBUG((EFI_D_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));
1031     }
1032 
1033     return Status;
1034 }
1035 
1036 EFI_STATUS
FlashWriteBlocks(IN FLASH_INSTANCE * Instance,IN EFI_LBA Lba,IN UINTN BufferSizeInBytes,IN VOID * Buffer)1037 FlashWriteBlocks (
1038     IN FLASH_INSTANCE*        Instance,
1039     IN EFI_LBA                Lba,
1040     IN UINTN                  BufferSizeInBytes,
1041     IN VOID*                   Buffer
1042 )
1043 {
1044     EFI_STATUS      Status = EFI_SUCCESS;
1045     UINTN                   BlockAddress;
1046     UINT32                     NumBlocks;
1047     UINTN                   WriteAddress;
1048 
1049     // The buffer must be valid
1050     if (Buffer == NULL)
1051     {
1052         return EFI_INVALID_PARAMETER;
1053     }
1054 
1055     if (Instance->Media.ReadOnly == TRUE)
1056     {
1057         return EFI_WRITE_PROTECTED;
1058     }
1059 
1060     // We must have some bytes to read
1061     if (BufferSizeInBytes == 0)
1062     {
1063         return EFI_BAD_BUFFER_SIZE;
1064     }
1065 
1066     // The size of the buffer must be a multiple of the block size
1067     if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0)
1068     {
1069         return EFI_BAD_BUFFER_SIZE;
1070     }
1071 
1072     // All blocks must be within the device
1073     NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
1074     if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1))
1075     {
1076         DEBUG((EFI_D_ERROR, "[%a]:[%dL]ERROR - Write will exceed last block.\n", __FUNCTION__, __LINE__ ));
1077         return EFI_INVALID_PARAMETER;
1078     }
1079 
1080     BlockAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, Instance->Media.BlockSize);
1081 
1082     WriteAddress = BlockAddress - Instance->DeviceBaseAddress;
1083 
1084     Status = mFlash->Write(mFlash, (UINT32)WriteAddress, (UINT8*)Buffer, BufferSizeInBytes);
1085     if (EFI_SUCCESS != Status)
1086     {
1087         DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
1088         return Status;
1089     }
1090 
1091     return Status;
1092 }
1093 
1094 EFI_STATUS
FlashReadBlocks(IN FLASH_INSTANCE * Instance,IN EFI_LBA Lba,IN UINTN BufferSizeInBytes,OUT VOID * Buffer)1095 FlashReadBlocks (
1096     IN FLASH_INSTANCE*   Instance,
1097     IN EFI_LBA              Lba,
1098     IN UINTN                BufferSizeInBytes,
1099     OUT VOID*                Buffer
1100 )
1101 {
1102     UINT32                     NumBlocks;
1103     UINTN                   StartAddress;
1104     UINTN                    ReadAddress;
1105     EFI_STATUS                    Status;
1106 
1107     // The buffer must be valid
1108     if (Buffer == NULL)
1109     {
1110         return EFI_INVALID_PARAMETER;
1111     }
1112 
1113     // We must have some bytes to read
1114     if (BufferSizeInBytes == 0)
1115     {
1116         return EFI_BAD_BUFFER_SIZE;
1117     }
1118 
1119     // The size of the buffer must be a multiple of the block size
1120     if ((BufferSizeInBytes % Instance->Media.BlockSize) != 0)
1121     {
1122         return EFI_BAD_BUFFER_SIZE;
1123     }
1124 
1125     // All blocks must be within the device
1126     NumBlocks = ((UINT32)BufferSizeInBytes) / Instance->Media.BlockSize ;
1127     if ((Lba + NumBlocks) > (Instance->Media.LastBlock + 1))
1128     {
1129         DEBUG((EFI_D_ERROR, "FlashReadBlocks: ERROR - Read will exceed last block\n"));
1130         return EFI_INVALID_PARAMETER;
1131     }
1132 
1133     // Get the address to start reading from
1134     StartAddress = GET_BLOCK_ADDRESS (Instance->RegionBaseAddress,
1135                                       Lba,
1136                                       Instance->Media.BlockSize
1137                                      );
1138 
1139 
1140     ReadAddress = StartAddress - Instance->DeviceBaseAddress;
1141 
1142     Status = mFlash->Read(mFlash, (UINT32)ReadAddress, Buffer, BufferSizeInBytes);
1143     if (EFI_SUCCESS != Status)
1144     {
1145         DEBUG((EFI_D_ERROR, "%s - %d Status=%r\n", __FILE__, __LINE__, Status));
1146         return Status;
1147     }
1148 
1149     return EFI_SUCCESS;
1150 }
1151 
1152 VOID
1153 EFIAPI
FlashFvbVirtualNotifyEvent(IN EFI_EVENT Event,IN VOID * Context)1154 FlashFvbVirtualNotifyEvent (
1155   IN EFI_EVENT        Event,
1156   IN VOID             *Context
1157   )
1158 {
1159   EfiConvertPointer (0x0, (VOID**)&mFlash);
1160   EfiConvertPointer (0x0, (VOID**)&mFlashNvStorageVariableBase);
1161   return;
1162 }
1163 
1164 EFI_STATUS
1165 EFIAPI
FlashFvbInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1166 FlashFvbInitialize (
1167     IN EFI_HANDLE         ImageHandle,
1168     IN EFI_SYSTEM_TABLE*   SystemTable
1169 )
1170 {
1171     EFI_STATUS              Status;
1172     UINT32                  Index;
1173     FLASH_DESCRIPTION*      FlashDevices;
1174     UINT32                  FlashDeviceCount;
1175     BOOLEAN                 ContainVariableStorage;
1176 
1177 
1178     Status = FlashPlatformGetDevices (&FlashDevices, &FlashDeviceCount);
1179     if (EFI_ERROR(Status))
1180     {
1181         DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to get Flash devices\n", __FUNCTION__, __LINE__));
1182         return Status;
1183     }
1184 
1185     mFlashInstances = AllocatePool ((UINT32)(sizeof(FLASH_INSTANCE*) * FlashDeviceCount));
1186 
1187     Status = gBS->LocateProtocol (&gHisiSpiFlashProtocolGuid, NULL, (VOID*) &mFlash);
1188     if (EFI_ERROR(Status))
1189     {
1190         DEBUG((EFI_D_ERROR, "[%a]:[%dL] Status=%r\n", __FUNCTION__, __LINE__, Status));
1191         return Status;
1192     }
1193 
1194     for (Index = 0; Index < FlashDeviceCount; Index++)
1195     {
1196         // Check if this Flash device contain the variable storage region
1197         ContainVariableStorage =
1198             (FlashDevices[Index].RegionBaseAddress <= (UINT32)PcdGet32 (PcdFlashNvStorageVariableBase)) &&
1199             ((UINT32)(PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize)) <= FlashDevices[Index].RegionBaseAddress + FlashDevices[Index].Size);
1200 
1201         Status = FlashCreateInstance (
1202                      FlashDevices[Index].DeviceBaseAddress,
1203                      FlashDevices[Index].RegionBaseAddress,
1204                      FlashDevices[Index].Size,
1205                      Index,
1206                      FlashDevices[Index].BlockSize,
1207                      ContainVariableStorage,
1208                      &FlashDevices[Index].Guid,
1209                      &mFlashInstances[Index]
1210                  );
1211         if (EFI_ERROR(Status))
1212         {
1213             DEBUG((EFI_D_ERROR, "[%a]:[%dL] Fail to create instance for Flash[%d]\n", __FUNCTION__, __LINE__, Index));
1214         }
1215     }
1216     //
1217     // Register for the virtual address change event
1218     //
1219     Status = gBS->CreateEventEx (
1220                   EVT_NOTIFY_SIGNAL,
1221                   TPL_NOTIFY,
1222                   FlashFvbVirtualNotifyEvent,
1223                   NULL,
1224                   &gEfiEventVirtualAddressChangeGuid,
1225                   &mFlashFvbVirtualAddrChangeEvent
1226                   );
1227     ASSERT_EFI_ERROR (Status);
1228 
1229     return Status;
1230 }
1231