]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Drivers/NorFlashDxe/NorFlashDxe.c
ArmPlatformPkg: Apply uncrustify changes
[mirror_edk2.git] / ArmPlatformPkg / Drivers / NorFlashDxe / NorFlashDxe.c
CommitLineData
1e57a462 1/** @file NorFlashDxe.c\r
2\r
8015f3f6 3 Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>\r
1e57a462 4\r
f4dfad05 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1e57a462 6\r
7**/\r
8\r
9#include <Library/UefiLib.h>\r
10#include <Library/BaseMemoryLib.h>\r
11#include <Library/MemoryAllocationLib.h>\r
12#include <Library/UefiBootServicesTableLib.h>\r
13#include <Library/PcdLib.h>\r
c2d1cf1b
MK
14#include <Library/HobLib.h>\r
15#include <Library/DxeServicesTableLib.h>\r
1e57a462 16\r
c2d1cf1b 17#include "NorFlash.h"\r
1e57a462 18\r
40b0b23e 19STATIC EFI_EVENT mNorFlashVirtualAddrChangeEvent;\r
1e57a462 20\r
21//\r
22// Global variable declarations\r
23//\r
40b0b23e
MK
24NOR_FLASH_INSTANCE **mNorFlashInstances;\r
25UINT32 mNorFlashDeviceCount;\r
26UINTN mFlashNvStorageVariableBase;\r
27EFI_EVENT mFvbVirtualAddrChangeEvent;\r
1e57a462 28\r
29NOR_FLASH_INSTANCE mNorFlashInstanceTemplate = {\r
30 NOR_FLASH_SIGNATURE, // Signature\r
40b0b23e 31 NULL, // Handle ... NEED TO BE FILLED\r
1e57a462 32\r
1e57a462 33 0, // DeviceBaseAddress ... NEED TO BE FILLED\r
34 0, // RegionBaseAddress ... NEED TO BE FILLED\r
35 0, // Size ... NEED TO BE FILLED\r
36 0, // StartLba\r
37\r
1d5d0ae9 38 {\r
39 EFI_BLOCK_IO_PROTOCOL_REVISION2, // Revision\r
40b0b23e
MK
40 NULL, // Media ... NEED TO BE FILLED\r
41 NorFlashBlockIoReset, // Reset;\r
42 NorFlashBlockIoReadBlocks, // ReadBlocks\r
43 NorFlashBlockIoWriteBlocks, // WriteBlocks\r
44 NorFlashBlockIoFlushBlocks // FlushBlocks\r
1e57a462 45 }, // BlockIoProtocol\r
46\r
1d5d0ae9 47 {\r
40b0b23e 48 0, // MediaId ... NEED TO BE FILLED\r
1d5d0ae9 49 FALSE, // RemovableMedia\r
40b0b23e 50 TRUE, // MediaPresent\r
1d5d0ae9 51 FALSE, // LogicalPartition\r
52 FALSE, // ReadOnly\r
53 FALSE, // WriteCaching;\r
40b0b23e
MK
54 0, // BlockSize ... NEED TO BE FILLED\r
55 4, // IoAlign\r
56 0, // LastBlock ... NEED TO BE FILLED\r
57 0, // LowestAlignedLba\r
58 1, // LogicalBlocksPerPhysicalBlock\r
59 }, // Media;\r
1e57a462 60\r
452a9ee1
BJ
61 {\r
62 EFI_DISK_IO_PROTOCOL_REVISION, // Revision\r
63 NorFlashDiskIoReadDisk, // ReadDisk\r
64 NorFlashDiskIoWriteDisk // WriteDisk\r
65 },\r
66\r
1d5d0ae9 67 {\r
40b0b23e
MK
68 FvbGetAttributes, // GetAttributes\r
69 FvbSetAttributes, // SetAttributes\r
70 FvbGetPhysicalAddress, // GetPhysicalAddress\r
71 FvbGetBlockSize, // GetBlockSize\r
72 FvbRead, // Read\r
73 FvbWrite, // Write\r
74 FvbEraseBlocks, // EraseBlocks\r
75 NULL, // ParentHandle\r
76 }, // FvbProtoccol;\r
452a9ee1 77 NULL, // ShadowBuffer\r
1e57a462 78 {\r
79 {\r
80 {\r
81 HARDWARE_DEVICE_PATH,\r
82 HW_VENDOR_DP,\r
4ef11358
AB
83 {\r
84 (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End)),\r
85 (UINT8)(OFFSET_OF (NOR_FLASH_DEVICE_PATH, End) >> 8)\r
86 }\r
1e57a462 87 },\r
40b0b23e
MK
88 { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }\r
89 }, // GUID ... NEED TO BE FILLED\r
1e57a462 90 },\r
8b902534 91 0, // Index\r
1e57a462 92 {\r
93 END_DEVICE_PATH_TYPE,\r
94 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
b0fdce95 95 { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }\r
1e57a462 96 }\r
40b0b23e 97 } // DevicePath\r
1e57a462 98};\r
99\r
100EFI_STATUS\r
101NorFlashCreateInstance (\r
40b0b23e
MK
102 IN UINTN NorFlashDeviceBase,\r
103 IN UINTN NorFlashRegionBase,\r
104 IN UINTN NorFlashSize,\r
105 IN UINT32 Index,\r
106 IN UINT32 BlockSize,\r
107 IN BOOLEAN SupportFvb,\r
108 OUT NOR_FLASH_INSTANCE **NorFlashInstance\r
1e57a462 109 )\r
110{\r
40b0b23e
MK
111 EFI_STATUS Status;\r
112 NOR_FLASH_INSTANCE *Instance;\r
1e57a462 113\r
40b0b23e 114 ASSERT (NorFlashInstance != NULL);\r
1e57a462 115\r
40b0b23e 116 Instance = AllocateRuntimeCopyPool (sizeof (NOR_FLASH_INSTANCE), &mNorFlashInstanceTemplate);\r
1e57a462 117 if (Instance == NULL) {\r
118 return EFI_OUT_OF_RESOURCES;\r
119 }\r
120\r
121 Instance->DeviceBaseAddress = NorFlashDeviceBase;\r
122 Instance->RegionBaseAddress = NorFlashRegionBase;\r
40b0b23e 123 Instance->Size = NorFlashSize;\r
1e57a462 124\r
125 Instance->BlockIoProtocol.Media = &Instance->Media;\r
40b0b23e
MK
126 Instance->Media.MediaId = Index;\r
127 Instance->Media.BlockSize = BlockSize;\r
128 Instance->Media.LastBlock = (NorFlashSize / BlockSize)-1;\r
1d5d0ae9 129\r
8b902534
AB
130 CopyGuid (&Instance->DevicePath.Vendor.Guid, &gEfiCallerIdGuid);\r
131 Instance->DevicePath.Index = (UINT8)Index;\r
1e57a462 132\r
40b0b23e 133 Instance->ShadowBuffer = AllocateRuntimePool (BlockSize);\r
452a9ee1
BJ
134 if (Instance->ShadowBuffer == NULL) {\r
135 return EFI_OUT_OF_RESOURCES;\r
136 }\r
137\r
1e57a462 138 if (SupportFvb) {\r
0f87c53d 139 NorFlashFvbInitialize (Instance);\r
1e57a462 140\r
141 Status = gBS->InstallMultipleProtocolInterfaces (\r
40b0b23e
MK
142 &Instance->Handle,\r
143 &gEfiDevicePathProtocolGuid,\r
144 &Instance->DevicePath,\r
145 &gEfiBlockIoProtocolGuid,\r
146 &Instance->BlockIoProtocol,\r
147 &gEfiFirmwareVolumeBlockProtocolGuid,\r
148 &Instance->FvbProtocol,\r
149 NULL\r
150 );\r
151 if (EFI_ERROR (Status)) {\r
2dff0c1a 152 FreePool (Instance);\r
1e57a462 153 return Status;\r
154 }\r
155 } else {\r
1e57a462 156 Status = gBS->InstallMultipleProtocolInterfaces (\r
157 &Instance->Handle,\r
40b0b23e
MK
158 &gEfiDevicePathProtocolGuid,\r
159 &Instance->DevicePath,\r
160 &gEfiBlockIoProtocolGuid,\r
161 &Instance->BlockIoProtocol,\r
162 &gEfiDiskIoProtocolGuid,\r
163 &Instance->DiskIoProtocol,\r
1e57a462 164 NULL\r
165 );\r
40b0b23e 166 if (EFI_ERROR (Status)) {\r
2dff0c1a 167 FreePool (Instance);\r
1e57a462 168 return Status;\r
169 }\r
170 }\r
1d5d0ae9 171\r
172 *NorFlashInstance = Instance;\r
1e57a462 173 return Status;\r
174}\r
175\r
1e57a462 176/**\r
22044caa 177 * This function unlock and erase an entire NOR Flash block.\r
1e57a462 178 **/\r
179EFI_STATUS\r
180NorFlashUnlockAndEraseSingleBlock (\r
40b0b23e
MK
181 IN NOR_FLASH_INSTANCE *Instance,\r
182 IN UINTN BlockAddress\r
1e57a462 183 )\r
184{\r
40b0b23e
MK
185 EFI_STATUS Status;\r
186 UINTN Index;\r
187 EFI_TPL OriginalTPL;\r
1e57a462 188\r
2dff0c1a
OM
189 if (!EfiAtRuntime ()) {\r
190 // Raise TPL to TPL_HIGH to stop anyone from interrupting us.\r
191 OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
192 } else {\r
193 // This initialization is only to prevent the compiler to complain about the\r
194 // use of uninitialized variables\r
195 OriginalTPL = TPL_HIGH_LEVEL;\r
196 }\r
1e57a462 197\r
198 Index = 0;\r
199 // The block erase might fail a first time (SW bug ?). Retry it ...\r
200 do {\r
201 // Unlock the block if we have to\r
202 Status = NorFlashUnlockSingleBlockIfNecessary (Instance, BlockAddress);\r
22044caa
OM
203 if (EFI_ERROR (Status)) {\r
204 break;\r
1e57a462 205 }\r
40b0b23e 206\r
22044caa 207 Status = NorFlashEraseSingleBlock (Instance, BlockAddress);\r
1e57a462 208 Index++;\r
209 } while ((Index < NOR_FLASH_ERASE_RETRY) && (Status == EFI_WRITE_PROTECTED));\r
210\r
211 if (Index == NOR_FLASH_ERASE_RETRY) {\r
40b0b23e 212 DEBUG ((DEBUG_ERROR, "EraseSingleBlock(BlockAddress=0x%08x: Block Locked Error (try to erase %d times)\n", BlockAddress, Index));\r
1e57a462 213 }\r
214\r
2dff0c1a
OM
215 if (!EfiAtRuntime ()) {\r
216 // Interruptions can resume.\r
217 gBS->RestoreTPL (OriginalTPL);\r
218 }\r
1e57a462 219\r
220 return Status;\r
221}\r
222\r
1e57a462 223EFI_STATUS\r
452a9ee1 224NorFlashWriteFullBlock (\r
40b0b23e
MK
225 IN NOR_FLASH_INSTANCE *Instance,\r
226 IN EFI_LBA Lba,\r
227 IN UINT32 *DataBuffer,\r
228 IN UINT32 BlockSizeInWords\r
1e57a462 229 )\r
230{\r
40b0b23e
MK
231 EFI_STATUS Status;\r
232 UINTN WordAddress;\r
233 UINT32 WordIndex;\r
234 UINTN BufferIndex;\r
235 UINTN BlockAddress;\r
236 UINTN BuffersInBlock;\r
237 UINTN RemainingWords;\r
238 EFI_TPL OriginalTPL;\r
239 UINTN Cnt;\r
1e57a462 240\r
241 Status = EFI_SUCCESS;\r
242\r
243 // Get the physical address of the block\r
244 BlockAddress = GET_NOR_BLOCK_ADDRESS (Instance->RegionBaseAddress, Lba, BlockSizeInWords * 4);\r
245\r
246 // Start writing from the first address at the start of the block\r
247 WordAddress = BlockAddress;\r
248\r
2dff0c1a
OM
249 if (!EfiAtRuntime ()) {\r
250 // Raise TPL to TPL_HIGH to stop anyone from interrupting us.\r
251 OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
252 } else {\r
253 // This initialization is only to prevent the compiler to complain about the\r
254 // use of uninitialized variables\r
255 OriginalTPL = TPL_HIGH_LEVEL;\r
256 }\r
1e57a462 257\r
258 Status = NorFlashUnlockAndEraseSingleBlock (Instance, BlockAddress);\r
40b0b23e
MK
259 if (EFI_ERROR (Status)) {\r
260 DEBUG ((DEBUG_ERROR, "WriteSingleBlock: ERROR - Failed to Unlock and Erase the single block at 0x%X\n", BlockAddress));\r
1e57a462 261 goto EXIT;\r
262 }\r
263\r
264 // To speed up the programming operation, NOR Flash is programmed using the Buffered Programming method.\r
265\r
266 // Check that the address starts at a 32-word boundary, i.e. last 7 bits must be zero\r
267 if ((WordAddress & BOUNDARY_OF_32_WORDS) == 0x00) {\r
1e57a462 268 // First, break the entire block into buffer-sized chunks.\r
82745213 269 BuffersInBlock = (UINTN)(BlockSizeInWords * 4) / P30_MAX_BUFFER_SIZE_IN_BYTES;\r
1e57a462 270\r
271 // Then feed each buffer chunk to the NOR Flash\r
518c243d 272 // If a buffer does not contain any data, don't write it.\r
40b0b23e 273 for (BufferIndex = 0;\r
1e57a462 274 BufferIndex < BuffersInBlock;\r
275 BufferIndex++, WordAddress += P30_MAX_BUFFER_SIZE_IN_BYTES, DataBuffer += P30_MAX_BUFFER_SIZE_IN_WORDS\r
40b0b23e
MK
276 )\r
277 {\r
518c243d
HL
278 // Check the buffer to see if it contains any data (not set all 1s).\r
279 for (Cnt = 0; Cnt < P30_MAX_BUFFER_SIZE_IN_WORDS; Cnt++) {\r
280 if (~DataBuffer[Cnt] != 0 ) {\r
281 // Some data found, write the buffer.\r
40b0b23e
MK
282 Status = NorFlashWriteBuffer (\r
283 Instance,\r
284 WordAddress,\r
285 P30_MAX_BUFFER_SIZE_IN_BYTES,\r
286 DataBuffer\r
287 );\r
288 if (EFI_ERROR (Status)) {\r
518c243d
HL
289 goto EXIT;\r
290 }\r
40b0b23e 291\r
518c243d
HL
292 break;\r
293 }\r
1e57a462 294 }\r
295 }\r
296\r
297 // Finally, finish off any remaining words that are less than the maximum size of the buffer\r
298 RemainingWords = BlockSizeInWords % P30_MAX_BUFFER_SIZE_IN_WORDS;\r
299\r
40b0b23e 300 if (RemainingWords != 0) {\r
1e57a462 301 Status = NorFlashWriteBuffer (Instance, WordAddress, (RemainingWords * 4), DataBuffer);\r
40b0b23e 302 if (EFI_ERROR (Status)) {\r
1e57a462 303 goto EXIT;\r
304 }\r
305 }\r
1e57a462 306 } else {\r
307 // For now, use the single word programming algorithm\r
308 // It is unlikely that the NOR Flash will exist in an address which falls within a 32 word boundary range,\r
309 // i.e. which ends in the range 0x......01 - 0x......7F.\r
40b0b23e 310 for (WordIndex = 0; WordIndex < BlockSizeInWords; WordIndex++, DataBuffer++, WordAddress = WordAddress + 4) {\r
1e57a462 311 Status = NorFlashWriteSingleWord (Instance, WordAddress, *DataBuffer);\r
40b0b23e 312 if (EFI_ERROR (Status)) {\r
1e57a462 313 goto EXIT;\r
314 }\r
315 }\r
316 }\r
317\r
318EXIT:\r
2dff0c1a
OM
319 if (!EfiAtRuntime ()) {\r
320 // Interruptions can resume.\r
321 gBS->RestoreTPL (OriginalTPL);\r
322 }\r
1e57a462 323\r
40b0b23e
MK
324 if (EFI_ERROR (Status)) {\r
325 DEBUG ((DEBUG_ERROR, "NOR FLASH Programming [WriteSingleBlock] failed at address 0x%08x. Exit Status = \"%r\".\n", WordAddress, Status));\r
1e57a462 326 }\r
40b0b23e 327\r
1e57a462 328 return Status;\r
329}\r
330\r
1e57a462 331EFI_STATUS\r
332EFIAPI\r
333NorFlashInitialise (\r
40b0b23e
MK
334 IN EFI_HANDLE ImageHandle,\r
335 IN EFI_SYSTEM_TABLE *SystemTable\r
1e57a462 336 )\r
337{\r
40b0b23e
MK
338 EFI_STATUS Status;\r
339 UINT32 Index;\r
340 NOR_FLASH_DESCRIPTION *NorFlashDevices;\r
341 BOOLEAN ContainVariableStorage;\r
1e57a462 342\r
343 Status = NorFlashPlatformInitialization ();\r
40b0b23e
MK
344 if (EFI_ERROR (Status)) {\r
345 DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to initialize Nor Flash devices\n"));\r
1e57a462 346 return Status;\r
347 }\r
348\r
1dbbfc17 349 Status = NorFlashPlatformGetDevices (&NorFlashDevices, &mNorFlashDeviceCount);\r
40b0b23e
MK
350 if (EFI_ERROR (Status)) {\r
351 DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to get Nor Flash devices\n"));\r
1e57a462 352 return Status;\r
353 }\r
354\r
40b0b23e 355 mNorFlashInstances = AllocateRuntimePool (sizeof (NOR_FLASH_INSTANCE *) * mNorFlashDeviceCount);\r
1e57a462 356\r
1dbbfc17 357 for (Index = 0; Index < mNorFlashDeviceCount; Index++) {\r
1e57a462 358 // Check if this NOR Flash device contain the variable storage region\r
8015f3f6 359\r
40b0b23e
MK
360 if (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) {\r
361 ContainVariableStorage =\r
362 (NorFlashDevices[Index].RegionBaseAddress <= PcdGet64 (PcdFlashNvStorageVariableBase64)) &&\r
363 (PcdGet64 (PcdFlashNvStorageVariableBase64) + PcdGet32 (PcdFlashNvStorageVariableSize) <=\r
364 NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);\r
365 } else {\r
366 ContainVariableStorage =\r
367 (NorFlashDevices[Index].RegionBaseAddress <= PcdGet32 (PcdFlashNvStorageVariableBase)) &&\r
368 (PcdGet32 (PcdFlashNvStorageVariableBase) + PcdGet32 (PcdFlashNvStorageVariableSize) <=\r
369 NorFlashDevices[Index].RegionBaseAddress + NorFlashDevices[Index].Size);\r
370 }\r
1e57a462 371\r
372 Status = NorFlashCreateInstance (\r
40b0b23e
MK
373 NorFlashDevices[Index].DeviceBaseAddress,\r
374 NorFlashDevices[Index].RegionBaseAddress,\r
375 NorFlashDevices[Index].Size,\r
376 Index,\r
377 NorFlashDevices[Index].BlockSize,\r
378 ContainVariableStorage,\r
379 &mNorFlashInstances[Index]\r
380 );\r
381 if (EFI_ERROR (Status)) {\r
382 DEBUG ((DEBUG_ERROR, "NorFlashInitialise: Fail to create instance for NorFlash[%d]\n", Index));\r
1e57a462 383 }\r
384 }\r
385\r
1dbbfc17
OM
386 //\r
387 // Register for the virtual address change event\r
388 //\r
389 Status = gBS->CreateEventEx (\r
390 EVT_NOTIFY_SIGNAL,\r
391 TPL_NOTIFY,\r
392 NorFlashVirtualNotifyEvent,\r
393 NULL,\r
394 &gEfiEventVirtualAddressChangeGuid,\r
395 &mNorFlashVirtualAddrChangeEvent\r
396 );\r
397 ASSERT_EFI_ERROR (Status);\r
398\r
1e57a462 399 return Status;\r
400}\r
c2d1cf1b
MK
401\r
402EFI_STATUS\r
403EFIAPI\r
404NorFlashFvbInitialize (\r
40b0b23e 405 IN NOR_FLASH_INSTANCE *Instance\r
c2d1cf1b
MK
406 )\r
407{\r
40b0b23e
MK
408 EFI_STATUS Status;\r
409 UINT32 FvbNumLba;\r
410 EFI_BOOT_MODE BootMode;\r
411 UINTN RuntimeMmioRegionSize;\r
c2d1cf1b 412\r
40b0b23e
MK
413 DEBUG ((DEBUG_BLKIO, "NorFlashFvbInitialize\n"));\r
414 ASSERT ((Instance != NULL));\r
c2d1cf1b
MK
415\r
416 //\r
417 // Declare the Non-Volatile storage as EFI_MEMORY_RUNTIME\r
418 //\r
419\r
420 // Note: all the NOR Flash region needs to be reserved into the UEFI Runtime memory;\r
421 // even if we only use the small block region at the top of the NOR Flash.\r
422 // The reason is when the NOR Flash memory is set into program mode, the command\r
423 // is written as the base of the flash region (ie: Instance->DeviceBaseAddress)\r
424 RuntimeMmioRegionSize = (Instance->RegionBaseAddress - Instance->DeviceBaseAddress) + Instance->Size;\r
425\r
426 Status = gDS->AddMemorySpace (\r
40b0b23e
MK
427 EfiGcdMemoryTypeMemoryMappedIo,\r
428 Instance->DeviceBaseAddress,\r
429 RuntimeMmioRegionSize,\r
430 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
431 );\r
c2d1cf1b
MK
432 ASSERT_EFI_ERROR (Status);\r
433\r
434 Status = gDS->SetMemorySpaceAttributes (\r
40b0b23e
MK
435 Instance->DeviceBaseAddress,\r
436 RuntimeMmioRegionSize,\r
437 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
438 );\r
c2d1cf1b
MK
439 ASSERT_EFI_ERROR (Status);\r
440\r
4f214830 441 mFlashNvStorageVariableBase = (PcdGet64 (PcdFlashNvStorageVariableBase64) != 0) ?\r
40b0b23e 442 PcdGet64 (PcdFlashNvStorageVariableBase64) : PcdGet32 (PcdFlashNvStorageVariableBase);\r
c2d1cf1b
MK
443\r
444 // Set the index of the first LBA for the FVB\r
8015f3f6 445 Instance->StartLba = (mFlashNvStorageVariableBase - Instance->RegionBaseAddress) / Instance->Media.BlockSize;\r
c2d1cf1b
MK
446\r
447 BootMode = GetBootModeHob ();\r
448 if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {\r
449 Status = EFI_INVALID_PARAMETER;\r
450 } else {\r
451 // Determine if there is a valid header at the beginning of the NorFlash\r
452 Status = ValidateFvHeader (Instance);\r
453 }\r
454\r
455 // Install the Default FVB header if required\r
40b0b23e 456 if (EFI_ERROR (Status)) {\r
c2d1cf1b
MK
457 // There is no valid header, so time to install one.\r
458 DEBUG ((DEBUG_INFO, "%a: The FVB Header is not valid.\n", __FUNCTION__));\r
40b0b23e
MK
459 DEBUG ((\r
460 DEBUG_INFO,\r
461 "%a: Installing a correct one for this volume.\n",\r
462 __FUNCTION__\r
463 ));\r
c2d1cf1b
MK
464\r
465 // Erase all the NorFlash that is reserved for variable storage\r
40b0b23e 466 FvbNumLba = (PcdGet32 (PcdFlashNvStorageVariableSize) + PcdGet32 (PcdFlashNvStorageFtwWorkingSize) + PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / Instance->Media.BlockSize;\r
c2d1cf1b
MK
467\r
468 Status = FvbEraseBlocks (&Instance->FvbProtocol, (EFI_LBA)0, FvbNumLba, EFI_LBA_LIST_TERMINATOR);\r
40b0b23e 469 if (EFI_ERROR (Status)) {\r
c2d1cf1b
MK
470 return Status;\r
471 }\r
472\r
473 // Install all appropriate headers\r
474 Status = InitializeFvAndVariableStoreHeaders (Instance);\r
40b0b23e 475 if (EFI_ERROR (Status)) {\r
c2d1cf1b
MK
476 return Status;\r
477 }\r
478 }\r
479\r
480 //\r
481 // The driver implementing the variable read service can now be dispatched;\r
482 // the varstore headers are in place.\r
483 //\r
484 Status = gBS->InstallProtocolInterface (\r
485 &gImageHandle,\r
486 &gEdkiiNvVarStoreFormattedGuid,\r
487 EFI_NATIVE_INTERFACE,\r
488 NULL\r
489 );\r
490 ASSERT_EFI_ERROR (Status);\r
491\r
492 //\r
493 // Register for the virtual address change event\r
494 //\r
495 Status = gBS->CreateEventEx (\r
496 EVT_NOTIFY_SIGNAL,\r
497 TPL_NOTIFY,\r
498 FvbVirtualNotifyEvent,\r
499 NULL,\r
500 &gEfiEventVirtualAddressChangeGuid,\r
501 &mFvbVirtualAddrChangeEvent\r
502 );\r
503 ASSERT_EFI_ERROR (Status);\r
504\r
505 return Status;\r
506}\r