TianoCore EDK2 master
Loading...
Searching...
No Matches
VirtNorFlashFvb.c
1/*++ @file NorFlashFvbDxe.c
2
3 Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
4
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 --*/
8
9#include <PiDxe.h>
10
11#include <Library/BaseLib.h>
14#include <Library/PcdLib.h>
15#include <Library/SafeIntLib.h>
16#include <Library/UefiLib.h>
17
20#include <Guid/VariableFormat.h>
21
22#include "VirtNorFlash.h"
23
24extern UINTN mFlashNvStorageVariableBase;
34
44 IN NOR_FLASH_INSTANCE *Instance
45 )
46{
47 EFI_STATUS Status;
48 VOID *Headers;
49 UINTN HeadersLength;
50 EFI_FIRMWARE_VOLUME_HEADER *FirmwareVolumeHeader;
51 VARIABLE_STORE_HEADER *VariableStoreHeader;
52 UINT32 NvStorageFtwSpareSize;
53 UINT32 NvStorageFtwWorkingSize;
54 UINT32 NvStorageVariableSize;
55 UINT64 NvStorageFtwSpareBase;
56 UINT64 NvStorageFtwWorkingBase;
57 UINT64 NvStorageVariableBase;
58
59 HeadersLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY) + sizeof (VARIABLE_STORE_HEADER);
60 Headers = AllocateZeroPool (HeadersLength);
61
62 NvStorageFtwWorkingSize = PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
63 NvStorageFtwSpareSize = PcdGet32 (PcdFlashNvStorageFtwSpareSize);
64 NvStorageVariableSize = PcdGet32 (PcdFlashNvStorageVariableSize);
65
66 NvStorageFtwSpareBase = (PcdGet64 (PcdFlashNvStorageFtwSpareBase64) != 0) ?
67 PcdGet64 (PcdFlashNvStorageFtwSpareBase64) : PcdGet32 (PcdFlashNvStorageFtwSpareBase);
68 NvStorageFtwWorkingBase = (PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) != 0) ?
69 PcdGet64 (PcdFlashNvStorageFtwWorkingBase64) : PcdGet32 (PcdFlashNvStorageFtwWorkingBase);
70 NvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?
71 PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);
72
73 // FirmwareVolumeHeader->FvLength is declared to have the Variable area AND the FTW working area AND the FTW Spare contiguous.
74 if ((NvStorageVariableBase + NvStorageVariableSize) != NvStorageFtwWorkingBase) {
75 DEBUG ((
76 DEBUG_ERROR,
77 "%a: NvStorageFtwWorkingBase is not contiguous with NvStorageVariableBase region\n",
78 __func__
79 ));
80 return EFI_INVALID_PARAMETER;
81 }
82
83 if ((NvStorageFtwWorkingBase + NvStorageFtwWorkingSize) != NvStorageFtwSpareBase) {
84 DEBUG ((
85 DEBUG_ERROR,
86 "%a: NvStorageFtwSpareBase is not contiguous with NvStorageFtwWorkingBase region\n",
87 __func__
88 ));
89 return EFI_INVALID_PARAMETER;
90 }
91
92 // Check if the size of the area is at least one block size
93 if ((NvStorageVariableSize <= 0) || (NvStorageVariableSize / Instance->BlockSize <= 0)) {
94 DEBUG ((
95 DEBUG_ERROR,
96 "%a: NvStorageVariableSize is 0x%x, should be atleast one block size\n",
97 __func__,
98 NvStorageVariableSize
99 ));
100 return EFI_INVALID_PARAMETER;
101 }
102
103 if ((NvStorageFtwWorkingSize <= 0) || (NvStorageFtwWorkingSize / Instance->BlockSize <= 0)) {
104 DEBUG ((
105 DEBUG_ERROR,
106 "%a: NvStorageFtwWorkingSize is 0x%x, should be atleast one block size\n",
107 __func__,
108 NvStorageFtwWorkingSize
109 ));
110 return EFI_INVALID_PARAMETER;
111 }
112
113 if ((NvStorageFtwSpareSize <= 0) || (NvStorageFtwSpareSize / Instance->BlockSize <= 0)) {
114 DEBUG ((
115 DEBUG_ERROR,
116 "%a: NvStorageFtwSpareSize is 0x%x, should be atleast one block size\n",
117 __func__,
118 NvStorageFtwSpareSize
119 ));
120 return EFI_INVALID_PARAMETER;
121 }
122
123 // Ensure the Variable area Base Addresses are aligned on a block size boundaries
124 if ((NvStorageVariableBase % Instance->BlockSize != 0) ||
125 (NvStorageFtwWorkingBase % Instance->BlockSize != 0) ||
126 (NvStorageFtwSpareBase % Instance->BlockSize != 0))
127 {
128 DEBUG ((DEBUG_ERROR, "%a: NvStorage Base addresses must be aligned to block size boundaries", __func__));
129 return EFI_INVALID_PARAMETER;
130 }
131
132 //
133 // EFI_FIRMWARE_VOLUME_HEADER
134 //
135 FirmwareVolumeHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Headers;
136 CopyGuid (&FirmwareVolumeHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid);
137 FirmwareVolumeHeader->FvLength =
138 PcdGet32 (PcdFlashNvStorageVariableSize) +
139 PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
140 PcdGet32 (PcdFlashNvStorageFtwSpareSize);
141 FirmwareVolumeHeader->Signature = EFI_FVH_SIGNATURE;
142 FirmwareVolumeHeader->Attributes = (EFI_FVB_ATTRIBUTES_2)(
143 EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
144 EFI_FVB2_READ_STATUS | // Reads are currently enabled
145 EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
146 EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
147 EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
148 EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
149 EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
150 );
151 FirmwareVolumeHeader->HeaderLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY);
152 FirmwareVolumeHeader->Revision = EFI_FVH_REVISION;
153 FirmwareVolumeHeader->BlockMap[0].NumBlocks = Instance->LastBlock + 1;
154 FirmwareVolumeHeader->BlockMap[0].Length = Instance->BlockSize;
155 FirmwareVolumeHeader->BlockMap[1].NumBlocks = 0;
156 FirmwareVolumeHeader->BlockMap[1].Length = 0;
157 FirmwareVolumeHeader->Checksum = CalculateCheckSum16 ((UINT16 *)FirmwareVolumeHeader, FirmwareVolumeHeader->HeaderLength);
158
159 //
160 // VARIABLE_STORE_HEADER
161 //
162 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)Headers + FirmwareVolumeHeader->HeaderLength);
163 CopyGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid);
164 VariableStoreHeader->Size = PcdGet32 (PcdFlashNvStorageVariableSize) - FirmwareVolumeHeader->HeaderLength;
165 VariableStoreHeader->Format = VARIABLE_STORE_FORMATTED;
166 VariableStoreHeader->State = VARIABLE_STORE_HEALTHY;
167
168 // Install the combined super-header in the NorFlash
169 Status = FvbWrite (&Instance->FvbProtocol, 0, 0, &HeadersLength, Headers);
170
171 FreePool (Headers);
172 return Status;
173}
174
185ValidateFvHeader (
186 IN NOR_FLASH_INSTANCE *Instance
187 )
188{
189 UINT16 Checksum;
191 CONST VARIABLE_STORE_HEADER *VariableStoreHeader;
192 UINTN VarOffset;
193 UINTN VariableStoreLength;
194 UINTN FvLength;
195
196 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)Instance->RegionBaseAddress;
197
198 FvLength = PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
199 PcdGet32 (PcdFlashNvStorageFtwSpareSize);
200
201 //
202 // Verify the header revision, header signature, length
203 // Length of FvBlock cannot be 2**64-1
204 // HeaderLength cannot be an odd number
205 //
206 if ( (FwVolHeader->Revision != EFI_FVH_REVISION)
207 || (FwVolHeader->Signature != EFI_FVH_SIGNATURE)
208 || (FwVolHeader->FvLength != FvLength)
209 )
210 {
211 DEBUG ((
212 DEBUG_INFO,
213 "%a: No Firmware Volume header present\n",
214 __func__
215 ));
216 return EFI_NOT_FOUND;
217 }
218
219 // Check the Firmware Volume Guid
220 if ( CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiSystemNvDataFvGuid) == FALSE ) {
221 DEBUG ((
222 DEBUG_INFO,
223 "%a: Firmware Volume Guid non-compatible\n",
224 __func__
225 ));
226 return EFI_NOT_FOUND;
227 }
228
229 // Verify the header checksum
230 Checksum = CalculateSum16 ((UINT16 *)FwVolHeader, FwVolHeader->HeaderLength);
231 if (Checksum != 0) {
232 DEBUG ((
233 DEBUG_INFO,
234 "%a: FV checksum is invalid (Checksum:0x%X)\n",
235 __func__,
236 Checksum
237 ));
238 return EFI_NOT_FOUND;
239 }
240
241 VariableStoreHeader = (VARIABLE_STORE_HEADER *)((UINTN)FwVolHeader + FwVolHeader->HeaderLength);
242
243 // Check the Variable Store Guid
244 if (!CompareGuid (&VariableStoreHeader->Signature, &gEfiAuthenticatedVariableGuid)) {
245 DEBUG ((
246 DEBUG_INFO,
247 "%a: Variable Store Guid non-compatible\n",
248 __func__
249 ));
250 return EFI_NOT_FOUND;
251 }
252
253 VariableStoreLength = PcdGet32 (PcdFlashNvStorageVariableSize) - FwVolHeader->HeaderLength;
254 if (VariableStoreHeader->Size != VariableStoreLength) {
255 DEBUG ((
256 DEBUG_INFO,
257 "%a: Variable Store Length does not match\n",
258 __func__
259 ));
260 return EFI_NOT_FOUND;
261 }
262
263 //
264 // check variables
265 //
266 DEBUG ((DEBUG_INFO, "%a: checking variables\n", __func__));
267 VarOffset = sizeof (*VariableStoreHeader);
268 for ( ; ;) {
269 UINTN VarHeaderEnd;
270 UINTN VarNameEnd;
271 UINTN VarEnd;
272 UINTN VarPadding;
274 CONST CHAR16 *VarName;
275 CONST CHAR8 *VarState;
276 RETURN_STATUS Status;
277
278 Status = SafeUintnAdd (VarOffset, sizeof (*VarHeader), &VarHeaderEnd);
279 if (RETURN_ERROR (Status)) {
280 DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
281 return EFI_NOT_FOUND;
282 }
283
284 if (VarHeaderEnd >= VariableStoreHeader->Size) {
285 if (VarOffset <= VariableStoreHeader->Size - sizeof (UINT16)) {
286 CONST UINT16 *StartId;
287
288 StartId = (VOID *)((UINTN)VariableStoreHeader + VarOffset);
289 if (*StartId == 0x55aa) {
290 DEBUG ((DEBUG_ERROR, "%a: startid at invalid location\n", __func__));
291 return EFI_NOT_FOUND;
292 }
293 }
294
295 DEBUG ((DEBUG_INFO, "%a: end of var list (no space left)\n", __func__));
296 break;
297 }
298
299 VarHeader = (VOID *)((UINTN)VariableStoreHeader + VarOffset);
300 if (VarHeader->StartId != 0x55aa) {
301 DEBUG ((DEBUG_INFO, "%a: end of var list (no startid)\n", __func__));
302 break;
303 }
304
305 if (VarHeader->State == 0xff) {
306 DEBUG ((DEBUG_INFO, "%a: end of var list (unwritten state)\n", __func__));
307 break;
308 }
309
310 VarName = NULL;
311 switch (VarHeader->State) {
312 // usage: State = VAR_HEADER_VALID_ONLY
314 VarState = "header-ok";
315 VarName = L"<unknown>";
316 break;
317
318 // usage: State = VAR_ADDED
319 case VAR_ADDED:
320 VarState = "ok";
321 break;
322
323 // usage: State &= VAR_IN_DELETED_TRANSITION
325 VarState = "del-in-transition";
326 break;
327
328 // usage: State &= VAR_DELETED
331 VarState = "deleted";
332 break;
333
334 default:
335 DEBUG ((
336 DEBUG_ERROR,
337 "%a: invalid variable state: 0x%x\n",
338 __func__,
339 VarHeader->State
340 ));
341 return EFI_NOT_FOUND;
342 }
343
344 Status = SafeUintnAdd (VarHeaderEnd, VarHeader->NameSize, &VarNameEnd);
345 if (RETURN_ERROR (Status)) {
346 DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
347 return EFI_NOT_FOUND;
348 }
349
350 Status = SafeUintnAdd (VarNameEnd, VarHeader->DataSize, &VarEnd);
351 if (RETURN_ERROR (Status)) {
352 DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
353 return EFI_NOT_FOUND;
354 }
355
356 if (VarEnd > VariableStoreHeader->Size) {
357 DEBUG ((
358 DEBUG_ERROR,
359 "%a: invalid variable size: 0x%Lx + 0x%Lx + 0x%x + 0x%x > 0x%x\n",
360 __func__,
361 (UINT64)VarOffset,
362 (UINT64)(sizeof (*VarHeader)),
363 VarHeader->NameSize,
364 VarHeader->DataSize,
365 VariableStoreHeader->Size
366 ));
367 return EFI_NOT_FOUND;
368 }
369
370 if (((VarHeader->NameSize & 1) != 0) ||
371 (VarHeader->NameSize < 4))
372 {
373 DEBUG ((DEBUG_ERROR, "%a: invalid name size\n", __func__));
374 return EFI_NOT_FOUND;
375 }
376
377 if (VarName == NULL) {
378 VarName = (VOID *)((UINTN)VariableStoreHeader + VarHeaderEnd);
379 if (VarName[VarHeader->NameSize / 2 - 1] != L'\0') {
380 DEBUG ((DEBUG_ERROR, "%a: name is not null terminated\n", __func__));
381 return EFI_NOT_FOUND;
382 }
383 }
384
385 DEBUG ((
386 DEBUG_VERBOSE,
387 "%a: +0x%04Lx: name=0x%x data=0x%x guid=%g '%s' (%a)\n",
388 __func__,
389 (UINT64)VarOffset,
390 VarHeader->NameSize,
391 VarHeader->DataSize,
392 &VarHeader->VendorGuid,
393 VarName,
394 VarState
395 ));
396
397 VarPadding = (4 - (VarEnd & 3)) & 3;
398 Status = SafeUintnAdd (VarEnd, VarPadding, &VarOffset);
399 if (RETURN_ERROR (Status)) {
400 DEBUG ((DEBUG_ERROR, "%a: integer overflow\n", __func__));
401 return EFI_NOT_FOUND;
402 }
403 }
404
405 return EFI_SUCCESS;
406}
407
422EFIAPI
423FvbGetAttributes (
425 OUT EFI_FVB_ATTRIBUTES_2 *Attributes
426 )
427{
428 EFI_FVB_ATTRIBUTES_2 FlashFvbAttributes;
429
430 FlashFvbAttributes = (EFI_FVB_ATTRIBUTES_2)(
431
432 EFI_FVB2_READ_ENABLED_CAP | // Reads may be enabled
433 EFI_FVB2_READ_STATUS | // Reads are currently enabled
434 EFI_FVB2_STICKY_WRITE | // A block erase is required to flip bits into EFI_FVB2_ERASE_POLARITY
435 EFI_FVB2_MEMORY_MAPPED | // It is memory mapped
436 EFI_FVB2_ERASE_POLARITY | // After erasure all bits take this value (i.e. '1')
437 EFI_FVB2_WRITE_STATUS | // Writes are currently enabled
438 EFI_FVB2_WRITE_ENABLED_CAP // Writes may be enabled
439
440 );
441
442 *Attributes = FlashFvbAttributes;
443
444 DEBUG ((DEBUG_BLKIO, "FvbGetAttributes(0x%X)\n", *Attributes));
445
446 return EFI_SUCCESS;
447}
448
469EFIAPI
470FvbSetAttributes (
472 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
473 )
474{
475 DEBUG ((DEBUG_BLKIO, "FvbSetAttributes(0x%X) is not supported\n", *Attributes));
476 return EFI_UNSUPPORTED;
477}
478
497EFIAPI
498FvbGetPhysicalAddress (
501 )
502{
503 NOR_FLASH_INSTANCE *Instance;
504
505 Instance = INSTANCE_FROM_FVB_THIS (This);
506
507 DEBUG ((DEBUG_BLKIO, "FvbGetPhysicalAddress(BaseAddress=0x%08x)\n", Instance->RegionBaseAddress));
508
509 ASSERT (Address != NULL);
510
511 *Address = mFlashNvStorageVariableBase;
512 return EFI_SUCCESS;
513}
514
542EFIAPI
543FvbGetBlockSize (
545 IN EFI_LBA Lba,
546 OUT UINTN *BlockSize,
547 OUT UINTN *NumberOfBlocks
548 )
549{
550 EFI_STATUS Status;
551 NOR_FLASH_INSTANCE *Instance;
552
553 Instance = INSTANCE_FROM_FVB_THIS (This);
554
555 DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize(Lba=%ld, BlockSize=0x%x, LastBlock=%ld)\n", Lba, Instance->BlockSize, Instance->LastBlock));
556
557 if (Lba > Instance->LastBlock) {
558 DEBUG ((DEBUG_ERROR, "FvbGetBlockSize: ERROR - Parameter LBA %ld is beyond the last Lba (%ld).\n", Lba, Instance->LastBlock));
559 Status = EFI_INVALID_PARAMETER;
560 } else {
561 // This is easy because in this platform each NorFlash device has equal sized blocks.
562 *BlockSize = (UINTN)Instance->BlockSize;
563 *NumberOfBlocks = (UINTN)(Instance->LastBlock - Lba + 1);
564
565 DEBUG ((DEBUG_BLKIO, "FvbGetBlockSize: *BlockSize=0x%x, *NumberOfBlocks=0x%x.\n", *BlockSize, *NumberOfBlocks));
566
567 Status = EFI_SUCCESS;
568 }
569
570 return Status;
571}
572
615EFIAPI
616FvbRead (
618 IN EFI_LBA Lba,
619 IN UINTN Offset,
620 IN OUT UINTN *NumBytes,
621 IN OUT UINT8 *Buffer
622 )
623{
624 EFI_STATUS TempStatus;
625 UINTN BlockSize;
626 NOR_FLASH_INSTANCE *Instance;
627
628 Instance = INSTANCE_FROM_FVB_THIS (This);
629
630 DEBUG ((DEBUG_BLKIO, "FvbRead(Parameters: Lba=%ld, Offset=0x%x, *NumBytes=0x%x, Buffer @ 0x%08x)\n", Instance->StartLba + Lba, Offset, *NumBytes, Buffer));
631
632 TempStatus = EFI_SUCCESS;
633
634 // Cache the block size to avoid de-referencing pointers all the time
635 BlockSize = Instance->BlockSize;
636
637 DEBUG ((DEBUG_BLKIO, "FvbRead: Check if (Offset=0x%x + NumBytes=0x%x) <= BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
638
639 // The read must not span block boundaries.
640 // We need to check each variable individually because adding two large values together overflows.
641 if ((Offset >= BlockSize) ||
642 (*NumBytes > BlockSize) ||
643 ((Offset + *NumBytes) > BlockSize))
644 {
645 DEBUG ((DEBUG_ERROR, "FvbRead: ERROR - EFI_BAD_BUFFER_SIZE: (Offset=0x%x + NumBytes=0x%x) > BlockSize=0x%x\n", Offset, *NumBytes, BlockSize));
646 return EFI_BAD_BUFFER_SIZE;
647 }
648
649 // We must have some bytes to read
650 if (*NumBytes == 0) {
651 return EFI_BAD_BUFFER_SIZE;
652 }
653
654 // Decide if we are doing full block reads or not.
655 if (*NumBytes % BlockSize != 0) {
656 TempStatus = NorFlashRead (Instance, Instance->StartLba + Lba, Offset, *NumBytes, Buffer);
657 if (EFI_ERROR (TempStatus)) {
658 return EFI_DEVICE_ERROR;
659 }
660 } else {
661 // Read NOR Flash data into shadow buffer
662 TempStatus = NorFlashReadBlocks (Instance, Instance->StartLba + Lba, BlockSize, Buffer);
663 if (EFI_ERROR (TempStatus)) {
664 // Return one of the pre-approved error statuses
665 return EFI_DEVICE_ERROR;
666 }
667 }
668
669 return EFI_SUCCESS;
670}
671
727EFIAPI
728FvbWrite (
730 IN EFI_LBA Lba,
731 IN UINTN Offset,
732 IN OUT UINTN *NumBytes,
733 IN UINT8 *Buffer
734 )
735{
736 NOR_FLASH_INSTANCE *Instance;
737
738 Instance = INSTANCE_FROM_FVB_THIS (This);
739
740 return NorFlashWriteSingleBlock (Instance, Instance->StartLba + Lba, Offset, NumBytes, Buffer);
741}
742
787EFIAPI
788FvbEraseBlocks (
790 ...
791 )
792{
793 EFI_STATUS Status;
794 VA_LIST Args;
795 UINTN BlockAddress; // Physical address of Lba to erase
796 EFI_LBA StartingLba; // Lba from which we start erasing
797 UINTN NumOfLba; // Number of Lba blocks to erase
798 NOR_FLASH_INSTANCE *Instance;
799
800 Instance = INSTANCE_FROM_FVB_THIS (This);
801
802 DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks()\n"));
803
804 Status = EFI_SUCCESS;
805
806 // Before erasing, check the entire list of parameters to ensure all specified blocks are valid
807
808 VA_START (Args, This);
809 do {
810 // Get the Lba from which we start erasing
811 StartingLba = VA_ARG (Args, EFI_LBA);
812
813 // Have we reached the end of the list?
814 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
815 // Exit the while loop
816 break;
817 }
818
819 // How many Lba blocks are we requested to erase?
820 NumOfLba = VA_ARG (Args, UINTN);
821
822 // All blocks must be within range
823 DEBUG ((
824 DEBUG_BLKIO,
825 "FvbEraseBlocks: Check if: ( StartingLba=%ld + NumOfLba=%Lu - 1 ) > LastBlock=%ld.\n",
826 Instance->StartLba + StartingLba,
827 (UINT64)NumOfLba,
828 Instance->LastBlock
829 ));
830 if ((NumOfLba == 0) || ((Instance->StartLba + StartingLba + NumOfLba - 1) > Instance->LastBlock)) {
831 VA_END (Args);
832 DEBUG ((DEBUG_ERROR, "FvbEraseBlocks: ERROR - Lba range goes past the last Lba.\n"));
833 Status = EFI_INVALID_PARAMETER;
834 goto EXIT;
835 }
836 } while (TRUE);
837
838 VA_END (Args);
839
840 //
841 // To get here, all must be ok, so start erasing
842 //
843 VA_START (Args, This);
844 do {
845 // Get the Lba from which we start erasing
846 StartingLba = VA_ARG (Args, EFI_LBA);
847
848 // Have we reached the end of the list?
849 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
850 // Exit the while loop
851 break;
852 }
853
854 // How many Lba blocks are we requested to erase?
855 NumOfLba = VA_ARG (Args, UINTN);
856
857 // Go through each one and erase it
858 while (NumOfLba > 0) {
859 // Get the physical address of Lba to erase
860 BlockAddress = GET_NOR_BLOCK_ADDRESS (
861 Instance->RegionBaseAddress,
862 Instance->StartLba + StartingLba,
863 Instance->BlockSize
864 );
865
866 // Erase it
867 DEBUG ((DEBUG_BLKIO, "FvbEraseBlocks: Erasing Lba=%ld @ 0x%08x.\n", Instance->StartLba + StartingLba, BlockAddress));
868 Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);
869 if (EFI_ERROR (Status)) {
870 VA_END (Args);
871 Status = EFI_DEVICE_ERROR;
872 goto EXIT;
873 }
874
875 // Move to the next Lba
876 StartingLba++;
877 NumOfLba--;
878 }
879 } while (TRUE);
880
881 VA_END (Args);
882
883EXIT:
884 return Status;
885}
886
895VOID
896EFIAPI
897FvbVirtualNotifyEvent (
898 IN EFI_EVENT Event,
899 IN VOID *Context
900 )
901{
902 EfiConvertPointer (0x0, (VOID **)&mFlashNvStorageVariableBase);
903 return;
904}
UINT64 UINTN
UINT16 EFIAPI CalculateSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
Definition: CheckSum.c:107
UINT16 EFIAPI CalculateCheckSum16(IN CONST UINT16 *Buffer, IN UINTN Length)
Definition: CheckSum.c:151
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define EFI_LBA_LIST_TERMINATOR
VOID InitializeFvAndVariableStoreHeaders(IN VOID *Ptr)
Definition: Fvb.c:606
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define VA_ARG(Marker, TYPE)
Definition: Base.h:679
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define VA_END(Marker)
Definition: Base.h:691
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
UINT32 EFI_FVB_ATTRIBUTES_2
#define EFI_FVH_REVISION
RETURN_STATUS EFIAPI SafeUintnAdd(IN UINTN Augend, IN UINTN Addend, OUT UINTN *Result)
Definition: SafeIntLib32.c:338
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
UINT64 EFI_LBA
Definition: UefiBaseType.h:45
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI EfiConvertPointer(IN UINTN DebugDisposition, IN OUT VOID **Address)
Definition: RuntimeLib.c:561
#define VAR_DELETED
Variable is obsolete.
#define VAR_HEADER_VALID_ONLY
Variable header has been valid.
#define VAR_IN_DELETED_TRANSITION
Variable is in obsolete transition.
#define VARIABLE_STORE_FORMATTED
#define VAR_ADDED
Variable has been completely added.
EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]
EFI_FVB_ATTRIBUTES_2 Attributes