]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockService.c
MdeModulePkg/PiSmmCore: Initialize missing LoadedImage protocol fields for SMM driver.
[mirror_edk2.git] / OvmfPkg / QemuFlashFvbServicesRuntimeDxe / FwBlockService.c
CommitLineData
a4ce9ffd
JJ
1/**@file\r
2\r
3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 FWBlockService.c\r
15\r
16Abstract:\r
17\r
18Revision History\r
19\r
20**/\r
21\r
22//\r
23// The package level header files this module uses\r
24//\r
25#include <PiDxe.h>\r
26\r
27//\r
28// The protocols, PPI and GUID defintions for this module\r
29//\r
30#include <Guid/EventGroup.h>\r
31#include <Protocol/FirmwareVolumeBlock.h>\r
32#include <Protocol/DevicePath.h>\r
33\r
34//\r
35// The Library classes this module consumes\r
36//\r
37#include <Library/UefiLib.h>\r
38#include <Library/UefiDriverEntryPoint.h>\r
39#include <Library/BaseLib.h>\r
40#include <Library/DxeServicesTableLib.h>\r
41#include <Library/UefiRuntimeLib.h>\r
42#include <Library/DebugLib.h>\r
43#include <Library/BaseMemoryLib.h>\r
44#include <Library/MemoryAllocationLib.h>\r
45#include <Library/UefiBootServicesTableLib.h>\r
46#include <Library/DevicePathLib.h>\r
47\r
48#include "FwBlockService.h"\r
49#include "QemuFlash.h"\r
50\r
51#define EFI_FVB2_STATUS (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)\r
52\r
53ESAL_FWB_GLOBAL *mFvbModuleGlobal;\r
54\r
55FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {\r
56 {\r
57 {\r
58 HARDWARE_DEVICE_PATH,\r
59 HW_MEMMAP_DP,\r
60 {\r
61 (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),\r
62 (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)\r
63 }\r
64 },\r
65 EfiMemoryMappedIO,\r
66 (EFI_PHYSICAL_ADDRESS) 0,\r
67 (EFI_PHYSICAL_ADDRESS) 0,\r
68 },\r
69 {\r
70 END_DEVICE_PATH_TYPE,\r
71 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
72 {\r
73 END_DEVICE_PATH_LENGTH,\r
74 0\r
75 }\r
76 }\r
77};\r
78\r
79FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {\r
80 {\r
81 {\r
82 MEDIA_DEVICE_PATH,\r
83 MEDIA_PIWG_FW_VOL_DP,\r
84 {\r
85 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),\r
86 (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)\r
87 }\r
88 },\r
89 { 0 }\r
90 },\r
91 {\r
92 END_DEVICE_PATH_TYPE,\r
93 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
94 {\r
95 END_DEVICE_PATH_LENGTH,\r
96 0\r
97 }\r
98 }\r
99};\r
100\r
101EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {\r
102 FVB_DEVICE_SIGNATURE,\r
103 NULL,\r
104 0,\r
105 {\r
106 FvbProtocolGetAttributes,\r
107 FvbProtocolSetAttributes,\r
108 FvbProtocolGetPhysicalAddress,\r
109 FvbProtocolGetBlockSize,\r
110 FvbProtocolRead,\r
111 FvbProtocolWrite,\r
112 FvbProtocolEraseBlocks,\r
113 NULL\r
114 }\r
115};\r
116\r
117\r
118\r
119VOID\r
120EFIAPI\r
121FvbVirtualddressChangeEvent (\r
122 IN EFI_EVENT Event,\r
123 IN VOID *Context\r
124 )\r
125/*++\r
126\r
127Routine Description:\r
128\r
129 Fixup internal data so that EFI and SAL can be call in virtual mode.\r
130 Call the passed in Child Notify event and convert the mFvbModuleGlobal\r
131 date items to there virtual address.\r
132\r
133 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data\r
134 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common\r
135 instance data.\r
136\r
137Arguments:\r
138\r
139 (Standard EFI notify event - EFI_EVENT_NOTIFY)\r
140\r
141Returns:\r
142\r
143 None\r
144\r
145--*/\r
146{\r
147 EFI_FW_VOL_INSTANCE *FwhInstance;\r
148 UINTN Index;\r
149\r
150 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);\r
151\r
152 //\r
153 // Convert the base address of all the instances\r
154 //\r
155 Index = 0;\r
156 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];\r
157 while (Index < mFvbModuleGlobal->NumFv) {\r
158 EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);\r
159 FwhInstance = (EFI_FW_VOL_INSTANCE *)\r
160 (\r
161 (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength +\r
162 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
163 );\r
164 Index++;\r
165 }\r
166\r
167 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);\r
168 EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal);\r
169 QemuFlashConvertPointers ();\r
170}\r
171\r
172EFI_STATUS\r
173GetFvbInstance (\r
174 IN UINTN Instance,\r
175 IN ESAL_FWB_GLOBAL *Global,\r
176 OUT EFI_FW_VOL_INSTANCE **FwhInstance,\r
177 IN BOOLEAN Virtual\r
178 )\r
179/*++\r
180\r
181Routine Description:\r
182 Retrieves the physical address of a memory mapped FV\r
183\r
184Arguments:\r
185 Instance - The FV instance whose base address is going to be\r
186 returned\r
187 Global - Pointer to ESAL_FWB_GLOBAL that contains all\r
188 instance data\r
189 FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure\r
190 Virtual - Whether CPU is in virtual or physical mode\r
191\r
192Returns:\r
193 EFI_SUCCESS - Successfully returns\r
194 EFI_INVALID_PARAMETER - Instance not found\r
195\r
196--*/\r
197{\r
198 EFI_FW_VOL_INSTANCE *FwhRecord;\r
199\r
200 if (Instance >= Global->NumFv) {\r
201 return EFI_INVALID_PARAMETER;\r
202 }\r
203 //\r
204 // Find the right instance of the FVB private data\r
205 //\r
206 FwhRecord = Global->FvInstance[Virtual];\r
207 while (Instance > 0) {\r
208 FwhRecord = (EFI_FW_VOL_INSTANCE *)\r
209 (\r
210 (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +\r
211 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
212 );\r
213 Instance--;\r
214 }\r
215\r
216 *FwhInstance = FwhRecord;\r
217\r
218 return EFI_SUCCESS;\r
219}\r
220\r
221EFI_STATUS\r
222FvbGetPhysicalAddress (\r
223 IN UINTN Instance,\r
224 OUT EFI_PHYSICAL_ADDRESS *Address,\r
225 IN ESAL_FWB_GLOBAL *Global,\r
226 IN BOOLEAN Virtual\r
227 )\r
228/*++\r
229\r
230Routine Description:\r
231 Retrieves the physical address of a memory mapped FV\r
232\r
233Arguments:\r
234 Instance - The FV instance whose base address is going to be\r
235 returned\r
236 Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS\r
237 that on successful return, contains the base address\r
238 of the firmware volume.\r
239 Global - Pointer to ESAL_FWB_GLOBAL that contains all\r
240 instance data\r
241 Virtual - Whether CPU is in virtual or physical mode\r
242\r
243Returns:\r
244 EFI_SUCCESS - Successfully returns\r
245 EFI_INVALID_PARAMETER - Instance not found\r
246\r
247--*/\r
248{\r
249 EFI_FW_VOL_INSTANCE *FwhInstance;\r
250 EFI_STATUS Status;\r
251\r
252 //\r
253 // Find the right instance of the FVB private data\r
254 //\r
255 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
256 ASSERT_EFI_ERROR (Status);\r
257 *Address = FwhInstance->FvBase[Virtual];\r
258\r
259 return EFI_SUCCESS;\r
260}\r
261\r
262EFI_STATUS\r
263FvbGetVolumeAttributes (\r
264 IN UINTN Instance,\r
265 OUT EFI_FVB_ATTRIBUTES_2 *Attributes,\r
266 IN ESAL_FWB_GLOBAL *Global,\r
267 IN BOOLEAN Virtual\r
268 )\r
269/*++\r
270\r
271Routine Description:\r
272 Retrieves attributes, insures positive polarity of attribute bits, returns\r
273 resulting attributes in output parameter\r
274\r
275Arguments:\r
276 Instance - The FV instance whose attributes is going to be\r
277 returned\r
278 Attributes - Output buffer which contains attributes\r
279 Global - Pointer to ESAL_FWB_GLOBAL that contains all\r
280 instance data\r
281 Virtual - Whether CPU is in virtual or physical mode\r
282\r
283Returns:\r
284 EFI_SUCCESS - Successfully returns\r
285 EFI_INVALID_PARAMETER - Instance not found\r
286\r
287--*/\r
288{\r
289 EFI_FW_VOL_INSTANCE *FwhInstance;\r
290 EFI_STATUS Status;\r
291\r
292 //\r
293 // Find the right instance of the FVB private data\r
294 //\r
295 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
296 ASSERT_EFI_ERROR (Status);\r
297 *Attributes = FwhInstance->VolumeHeader.Attributes;\r
298\r
299 return EFI_SUCCESS;\r
300}\r
301\r
302EFI_STATUS\r
303FvbGetLbaAddress (\r
304 IN UINTN Instance,\r
305 IN EFI_LBA Lba,\r
306 OUT UINTN *LbaAddress,\r
307 OUT UINTN *LbaLength,\r
308 OUT UINTN *NumOfBlocks,\r
309 IN ESAL_FWB_GLOBAL *Global,\r
310 IN BOOLEAN Virtual\r
311 )\r
312/*++\r
313\r
314Routine Description:\r
315 Retrieves the starting address of an LBA in an FV\r
316\r
317Arguments:\r
318 Instance - The FV instance which the Lba belongs to\r
319 Lba - The logical block address\r
320 LbaAddress - On output, contains the physical starting address\r
321 of the Lba\r
322 LbaLength - On output, contains the length of the block\r
323 NumOfBlocks - A pointer to a caller allocated UINTN in which the\r
324 number of consecutive blocks starting with Lba is\r
325 returned. All blocks in this range have a size of\r
326 BlockSize\r
327 Global - Pointer to ESAL_FWB_GLOBAL that contains all\r
328 instance data\r
329 Virtual - Whether CPU is in virtual or physical mode\r
330\r
331Returns:\r
332 EFI_SUCCESS - Successfully returns\r
333 EFI_INVALID_PARAMETER - Instance not found\r
334\r
335--*/\r
336{\r
337 UINT32 NumBlocks;\r
338 UINT32 BlockLength;\r
339 UINTN Offset;\r
340 EFI_LBA StartLba;\r
341 EFI_LBA NextLba;\r
342 EFI_FW_VOL_INSTANCE *FwhInstance;\r
343 EFI_FV_BLOCK_MAP_ENTRY *BlockMap;\r
344 EFI_STATUS Status;\r
345\r
346 //\r
347 // Find the right instance of the FVB private data\r
348 //\r
349 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
350 ASSERT_EFI_ERROR (Status);\r
351\r
352 StartLba = 0;\r
353 Offset = 0;\r
354 BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);\r
355\r
356 //\r
357 // Parse the blockmap of the FV to find which map entry the Lba belongs to\r
358 //\r
359 while (TRUE) {\r
360 NumBlocks = BlockMap->NumBlocks;\r
361 BlockLength = BlockMap->Length;\r
362\r
363 if (NumBlocks == 0 || BlockLength == 0) {\r
364 return EFI_INVALID_PARAMETER;\r
365 }\r
366\r
367 NextLba = StartLba + NumBlocks;\r
368\r
369 //\r
370 // The map entry found\r
371 //\r
372 if (Lba >= StartLba && Lba < NextLba) {\r
373 Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);\r
374 if (LbaAddress != NULL) {\r
375 *LbaAddress = FwhInstance->FvBase[Virtual] + Offset;\r
376 }\r
377\r
378 if (LbaLength != NULL) {\r
379 *LbaLength = BlockLength;\r
380 }\r
381\r
382 if (NumOfBlocks != NULL) {\r
383 *NumOfBlocks = (UINTN) (NextLba - Lba);\r
384 }\r
385\r
386 return EFI_SUCCESS;\r
387 }\r
388\r
389 StartLba = NextLba;\r
390 Offset = Offset + NumBlocks * BlockLength;\r
391 BlockMap++;\r
392 }\r
393}\r
394\r
395EFI_STATUS\r
396FvbSetVolumeAttributes (\r
397 IN UINTN Instance,\r
398 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,\r
399 IN ESAL_FWB_GLOBAL *Global,\r
400 IN BOOLEAN Virtual\r
401 )\r
402/*++\r
403\r
404Routine Description:\r
405 Modifies the current settings of the firmware volume according to the\r
406 input parameter, and returns the new setting of the volume\r
407\r
408Arguments:\r
409 Instance - The FV instance whose attributes is going to be\r
410 modified\r
411 Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2\r
412 containing the desired firmware volume settings.\r
413 On successful return, it contains the new settings\r
414 of the firmware volume\r
415 Global - Pointer to ESAL_FWB_GLOBAL that contains all\r
416 instance data\r
417 Virtual - Whether CPU is in virtual or physical mode\r
418\r
419Returns:\r
420 EFI_SUCCESS - Successfully returns\r
421 EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified\r
422 EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are\r
423 in conflict with the capabilities as declared in the\r
424 firmware volume header\r
425\r
426--*/\r
427{\r
428 EFI_FW_VOL_INSTANCE *FwhInstance;\r
429 EFI_FVB_ATTRIBUTES_2 OldAttributes;\r
430 EFI_FVB_ATTRIBUTES_2 *AttribPtr;\r
431 UINT32 Capabilities;\r
432 UINT32 OldStatus;\r
433 UINT32 NewStatus;\r
434 EFI_STATUS Status;\r
435 EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;\r
436\r
437 //\r
438 // Find the right instance of the FVB private data\r
439 //\r
440 Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);\r
441 ASSERT_EFI_ERROR (Status);\r
442\r
443 AttribPtr = (EFI_FVB_ATTRIBUTES_2 *) &(FwhInstance->VolumeHeader.Attributes);\r
444 OldAttributes = *AttribPtr;\r
445 Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \\r
446 EFI_FVB2_READ_ENABLED_CAP | \\r
447 EFI_FVB2_WRITE_DISABLED_CAP | \\r
448 EFI_FVB2_WRITE_ENABLED_CAP | \\r
449 EFI_FVB2_LOCK_CAP \\r
450 );\r
451 OldStatus = OldAttributes & EFI_FVB2_STATUS;\r
452 NewStatus = *Attributes & EFI_FVB2_STATUS;\r
453\r
454 UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \\r
455 EFI_FVB2_READ_ENABLED_CAP | \\r
456 EFI_FVB2_WRITE_DISABLED_CAP | \\r
457 EFI_FVB2_WRITE_ENABLED_CAP | \\r
458 EFI_FVB2_LOCK_CAP | \\r
459 EFI_FVB2_STICKY_WRITE | \\r
460 EFI_FVB2_MEMORY_MAPPED | \\r
461 EFI_FVB2_ERASE_POLARITY | \\r
462 EFI_FVB2_READ_LOCK_CAP | \\r
463 EFI_FVB2_WRITE_LOCK_CAP | \\r
464 EFI_FVB2_ALIGNMENT;\r
465\r
466 //\r
467 // Some attributes of FV is read only can *not* be set\r
468 //\r
469 if ((OldAttributes & UnchangedAttributes) ^ (*Attributes & UnchangedAttributes)) {\r
470 return EFI_INVALID_PARAMETER;\r
471 }\r
472 //\r
473 // If firmware volume is locked, no status bit can be updated\r
474 //\r
475 if (OldAttributes & EFI_FVB2_LOCK_STATUS) {\r
476 if (OldStatus ^ NewStatus) {\r
477 return EFI_ACCESS_DENIED;\r
478 }\r
479 }\r
480 //\r
481 // Test read disable\r
482 //\r
483 if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {\r
484 if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {\r
485 return EFI_INVALID_PARAMETER;\r
486 }\r
487 }\r
488 //\r
489 // Test read enable\r
490 //\r
491 if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {\r
492 if (NewStatus & EFI_FVB2_READ_STATUS) {\r
493 return EFI_INVALID_PARAMETER;\r
494 }\r
495 }\r
496 //\r
497 // Test write disable\r
498 //\r
499 if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {\r
500 if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {\r
501 return EFI_INVALID_PARAMETER;\r
502 }\r
503 }\r
504 //\r
505 // Test write enable\r
506 //\r
507 if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {\r
508 if (NewStatus & EFI_FVB2_WRITE_STATUS) {\r
509 return EFI_INVALID_PARAMETER;\r
510 }\r
511 }\r
512 //\r
513 // Test lock\r
514 //\r
515 if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {\r
516 if (NewStatus & EFI_FVB2_LOCK_STATUS) {\r
517 return EFI_INVALID_PARAMETER;\r
518 }\r
519 }\r
520\r
521 *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));\r
522 *AttribPtr = (*AttribPtr) | NewStatus;\r
523 *Attributes = *AttribPtr;\r
524\r
525 return EFI_SUCCESS;\r
526}\r
527\r
528//\r
529// FVB protocol APIs\r
530//\r
531EFI_STATUS\r
532EFIAPI\r
533FvbProtocolGetPhysicalAddress (\r
534 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
535 OUT EFI_PHYSICAL_ADDRESS *Address\r
536 )\r
537/*++\r
538\r
539Routine Description:\r
540\r
541 Retrieves the physical address of the device.\r
542\r
543Arguments:\r
544\r
545 This - Calling context\r
546 Address - Output buffer containing the address.\r
547\r
548Returns:\r
549\r
550Returns:\r
551 EFI_SUCCESS - Successfully returns\r
552\r
553--*/\r
554{\r
555 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
556\r
557 FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
558\r
559 return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ());\r
560}\r
561\r
562EFI_STATUS\r
563EFIAPI\r
564FvbProtocolGetBlockSize (\r
565 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
566 IN CONST EFI_LBA Lba,\r
567 OUT UINTN *BlockSize,\r
568 OUT UINTN *NumOfBlocks\r
569 )\r
570/*++\r
571\r
572Routine Description:\r
573 Retrieve the size of a logical block\r
574\r
575Arguments:\r
576 This - Calling context\r
577 Lba - Indicates which block to return the size for.\r
578 BlockSize - A pointer to a caller allocated UINTN in which\r
579 the size of the block is returned\r
580 NumOfBlocks - a pointer to a caller allocated UINTN in which the\r
581 number of consecutive blocks starting with Lba is\r
582 returned. All blocks in this range have a size of\r
583 BlockSize\r
584\r
585Returns:\r
586 EFI_SUCCESS - The firmware volume was read successfully and\r
587 contents are in Buffer\r
588\r
589--*/\r
590{\r
591 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
592\r
593 FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
594\r
595 return FvbGetLbaAddress (\r
596 FvbDevice->Instance,\r
597 Lba,\r
598 NULL,\r
599 BlockSize,\r
600 NumOfBlocks,\r
601 mFvbModuleGlobal,\r
602 EfiGoneVirtual ()\r
603 );\r
604}\r
605\r
606EFI_STATUS\r
607EFIAPI\r
608FvbProtocolGetAttributes (\r
609 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
610 OUT EFI_FVB_ATTRIBUTES_2 *Attributes\r
611 )\r
612/*++\r
613\r
614Routine Description:\r
615 Retrieves Volume attributes. No polarity translations are done.\r
616\r
617Arguments:\r
618 This - Calling context\r
619 Attributes - output buffer which contains attributes\r
620\r
621Returns:\r
622 EFI_SUCCESS - Successfully returns\r
623\r
624--*/\r
625{\r
626 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
627\r
628 FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
629\r
630 return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());\r
631}\r
632\r
633EFI_STATUS\r
634EFIAPI\r
635FvbProtocolSetAttributes (\r
636 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
637 IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes\r
638 )\r
639/*++\r
640\r
641Routine Description:\r
642 Sets Volume attributes. No polarity translations are done.\r
643\r
644Arguments:\r
645 This - Calling context\r
646 Attributes - output buffer which contains attributes\r
647\r
648Returns:\r
649 EFI_SUCCESS - Successfully returns\r
650\r
651--*/\r
652{\r
653 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
654\r
655 FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
656\r
657 return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ());\r
658}\r
659\r
660EFI_STATUS\r
661EFIAPI\r
662FvbProtocolEraseBlocks (\r
663 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
664 ...\r
665 )\r
666/*++\r
667\r
668Routine Description:\r
669\r
670 The EraseBlock() function erases one or more blocks as denoted by the\r
671 variable argument list. The entire parameter list of blocks must be verified\r
672 prior to erasing any blocks. If a block is requested that does not exist\r
673 within the associated firmware volume (it has a larger index than the last\r
674 block of the firmware volume), the EraseBlock() function must return\r
675 EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.\r
676\r
677Arguments:\r
678 This - Calling context\r
679 ... - Starting LBA followed by Number of Lba to erase.\r
680 a -1 to terminate the list.\r
681\r
682Returns:\r
683 EFI_SUCCESS - The erase request was successfully completed\r
684 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state\r
685 EFI_DEVICE_ERROR - The block device is not functioning correctly and\r
686 could not be written. Firmware device may have been\r
687 partially erased\r
688\r
689--*/\r
690{\r
691 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
692 EFI_FW_VOL_INSTANCE *FwhInstance;\r
693 UINTN NumOfBlocks;\r
694 VA_LIST args;\r
695 EFI_LBA StartingLba;\r
696 UINTN NumOfLba;\r
697 EFI_STATUS Status;\r
698\r
699 FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
700\r
701 Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ());\r
702 ASSERT_EFI_ERROR (Status);\r
703\r
704 NumOfBlocks = FwhInstance->NumOfBlocks;\r
705\r
706 VA_START (args, This);\r
707\r
708 do {\r
709 StartingLba = VA_ARG (args, EFI_LBA);\r
710 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {\r
711 break;\r
712 }\r
713\r
714 NumOfLba = VA_ARG (args, UINT32);\r
715\r
716 //\r
717 // Check input parameters\r
718 //\r
719 if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {\r
720 VA_END (args);\r
721 return EFI_INVALID_PARAMETER;\r
722 }\r
723 } while (1);\r
724\r
725 VA_END (args);\r
726\r
727 VA_START (args, This);\r
728 do {\r
729 StartingLba = VA_ARG (args, EFI_LBA);\r
730 if (StartingLba == EFI_LBA_LIST_TERMINATOR) {\r
731 break;\r
732 }\r
733\r
734 NumOfLba = VA_ARG (args, UINT32);\r
735\r
736 while (NumOfLba > 0) {\r
737 Status = QemuFlashEraseBlock (StartingLba);\r
738 if (EFI_ERROR (Status)) {\r
739 VA_END (args);\r
740 return Status;\r
741 }\r
742\r
743 StartingLba++;\r
744 NumOfLba--;\r
745 }\r
746\r
747 } while (1);\r
748\r
749 VA_END (args);\r
750\r
751 return EFI_SUCCESS;\r
752}\r
753\r
754EFI_STATUS\r
755EFIAPI\r
756FvbProtocolWrite (\r
757 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
758 IN EFI_LBA Lba,\r
759 IN UINTN Offset,\r
760 IN OUT UINTN *NumBytes,\r
761 IN UINT8 *Buffer\r
762 )\r
763/*++\r
764\r
765Routine Description:\r
766\r
767 Writes data beginning at Lba:Offset from FV. The write terminates either\r
768 when *NumBytes of data have been written, or when a block boundary is\r
769 reached. *NumBytes is updated to reflect the actual number of bytes\r
770 written. The write opertion does not include erase. This routine will\r
771 attempt to write only the specified bytes. If the writes do not stick,\r
772 it will return an error.\r
773\r
774Arguments:\r
775 This - Calling context\r
776 Lba - Block in which to begin write\r
777 Offset - Offset in the block at which to begin write\r
778 NumBytes - On input, indicates the requested write size. On\r
779 output, indicates the actual number of bytes written\r
780 Buffer - Buffer containing source data for the write.\r
781\r
782Returns:\r
783 EFI_SUCCESS - The firmware volume was written successfully\r
784 EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,\r
785 NumBytes contains the total number of bytes\r
786 actually written\r
787 EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state\r
788 EFI_DEVICE_ERROR - The block device is not functioning correctly and\r
789 could not be written\r
790 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL\r
791\r
792--*/\r
793{\r
794 return QemuFlashWrite ((EFI_LBA)Lba, (UINTN)Offset, NumBytes, (UINT8 *)Buffer);\r
795}\r
796\r
797EFI_STATUS\r
798EFIAPI\r
799FvbProtocolRead (\r
800 IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,\r
801 IN CONST EFI_LBA Lba,\r
802 IN CONST UINTN Offset,\r
803 IN OUT UINTN *NumBytes,\r
804 IN UINT8 *Buffer\r
805 )\r
806/*++\r
807\r
808Routine Description:\r
809\r
810 Reads data beginning at Lba:Offset from FV. The Read terminates either\r
811 when *NumBytes of data have been read, or when a block boundary is\r
812 reached. *NumBytes is updated to reflect the actual number of bytes\r
813 written. The write opertion does not include erase. This routine will\r
814 attempt to write only the specified bytes. If the writes do not stick,\r
815 it will return an error.\r
816\r
817Arguments:\r
818 This - Calling context\r
819 Lba - Block in which to begin Read\r
820 Offset - Offset in the block at which to begin Read\r
821 NumBytes - On input, indicates the requested write size. On\r
822 output, indicates the actual number of bytes Read\r
823 Buffer - Buffer containing source data for the Read.\r
824\r
825Returns:\r
826 EFI_SUCCESS - The firmware volume was read successfully and\r
827 contents are in Buffer\r
828 EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,\r
829 NumBytes contains the total number of bytes returned\r
830 in Buffer\r
831 EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state\r
832 EFI_DEVICE_ERROR - The block device is not functioning correctly and\r
833 could not be read\r
834 EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL\r
835\r
836--*/\r
837{\r
838 return QemuFlashRead ((EFI_LBA)Lba, (UINTN)Offset, NumBytes, (UINT8 *)Buffer);\r
839}\r
840\r
841EFI_STATUS\r
842ValidateFvHeader (\r
843 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader\r
844 )\r
845/*++\r
846\r
847Routine Description:\r
848 Check the integrity of firmware volume header\r
849\r
850Arguments:\r
851 FwVolHeader - A pointer to a firmware volume header\r
852\r
853Returns:\r
854 EFI_SUCCESS - The firmware volume is consistent\r
855 EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV\r
856\r
857--*/\r
858{\r
859 UINT16 Checksum;\r
860\r
861 //\r
862 // Verify the header revision, header signature, length\r
863 // Length of FvBlock cannot be 2**64-1\r
864 // HeaderLength cannot be an odd number\r
865 //\r
866 if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||\r
867 (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||\r
868 (FwVolHeader->FvLength == ((UINTN) -1)) ||\r
869 ((FwVolHeader->HeaderLength & 0x01) != 0)\r
870 ) {\r
871 return EFI_NOT_FOUND;\r
872 }\r
873 \r
874 //\r
875 // Verify the header checksum\r
876 //\r
877\r
878 Checksum = CalculateSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);\r
879 if (Checksum != 0) {\r
880 UINT16 Expected;\r
881\r
882 Expected = ((UINTN) FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff;\r
883\r
884 DEBUG ((EFI_D_INFO, "FV@%p Checksum is 0x%x, expected 0x%x\n",\r
885 FwVolHeader, FwVolHeader->Checksum, Expected));\r
886 return EFI_NOT_FOUND;\r
887 }\r
888\r
889 return EFI_SUCCESS;\r
890}\r
891\r
892STATIC\r
893EFI_STATUS\r
894MarkMemoryRangeForRuntimeAccess (\r
895 EFI_PHYSICAL_ADDRESS BaseAddress,\r
896 UINT64 Length\r
897 )\r
898{\r
899 EFI_STATUS Status;\r
900\r
901 //\r
902 // Mark flash region as runtime memory\r
903 //\r
904 Status = gDS->RemoveMemorySpace (\r
905 BaseAddress,\r
906 Length\r
907 );\r
908\r
909 Status = gDS->AddMemorySpace (\r
910 EfiGcdMemoryTypeSystemMemory,\r
911 BaseAddress,\r
912 Length,\r
913 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME\r
914 );\r
915 ASSERT_EFI_ERROR (Status);\r
916\r
917 Status = gBS->AllocatePages (\r
918 AllocateAddress,\r
919 EfiRuntimeServicesData,\r
920 (UINTN) EFI_SIZE_TO_PAGES (Length),\r
921 &BaseAddress\r
922 );\r
923 ASSERT_EFI_ERROR (Status);\r
924\r
925 return Status;\r
926}\r
927\r
928STATIC\r
929EFI_STATUS\r
930InitializeVariableFvHeader (\r
931 VOID\r
932 )\r
933{\r
934 EFI_STATUS Status;\r
935 EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader;\r
936 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
937 UINTN Length;\r
938 UINTN WriteLength;\r
939 UINTN BlockSize;\r
940\r
941 FwVolHeader =\r
942 (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)\r
943 PcdGet32 (PcdOvmfFlashNvStorageVariableBase);\r
944\r
945 Length = \r
946 (FixedPcdGet32 (PcdFlashNvStorageVariableSize) +\r
947 FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +\r
948 FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) +\r
949 FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize));\r
950\r
951 BlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);\r
952\r
953 Status = ValidateFvHeader (FwVolHeader);\r
954 if (!EFI_ERROR (Status)) {\r
955 if (FwVolHeader->FvLength != Length ||\r
956 FwVolHeader->BlockMap[0].Length != BlockSize) {\r
957 Status = EFI_VOLUME_CORRUPTED;\r
958 }\r
959 }\r
960 if (EFI_ERROR (Status)) {\r
961 UINTN Offset;\r
962 UINTN Start;\r
963\r
964 DEBUG ((EFI_D_INFO, "Variable FV header is not valid. It will be reinitialized.\n"));\r
965\r
966 //\r
967 // Get FvbInfo to provide in FwhInstance.\r
968 //\r
969 Status = GetFvbInfo (Length, &GoodFwVolHeader);\r
970 ASSERT (!EFI_ERROR (Status));\r
971\r
972 Start = (UINTN)(UINT8*) FwVolHeader - PcdGet32 (PcdOvmfFdBaseAddress);\r
973 ASSERT (Start % BlockSize == 0 && Length % BlockSize == 0);\r
974 ASSERT (GoodFwVolHeader->HeaderLength <= BlockSize);\r
975\r
976 //\r
977 // Erase all the blocks\r
978 //\r
979 for (Offset = Start; Offset < Start + Length; Offset += BlockSize) {\r
980 Status = QemuFlashEraseBlock ((EFI_LBA) Offset / BlockSize);\r
981 ASSERT_EFI_ERROR (Status);\r
982 }\r
983\r
984 //\r
985 // Write good FV header\r
986 //\r
987 WriteLength = GoodFwVolHeader->HeaderLength;\r
988 Status = QemuFlashWrite (\r
989 (EFI_LBA) Start / BlockSize,\r
990 0,\r
991 &WriteLength,\r
992 (UINT8 *) GoodFwVolHeader);\r
993 ASSERT_EFI_ERROR (Status);\r
994 ASSERT (WriteLength == GoodFwVolHeader->HeaderLength);\r
995 }\r
996\r
997 return Status;\r
998}\r
999\r
1000EFI_STATUS\r
1001EFIAPI\r
1002FvbInitialize (\r
1003 IN EFI_HANDLE ImageHandle,\r
1004 IN EFI_SYSTEM_TABLE *SystemTable\r
1005 )\r
1006/*++\r
1007\r
1008Routine Description:\r
1009 This function does common initialization for FVB services\r
1010\r
1011Arguments:\r
1012\r
1013Returns:\r
1014\r
1015--*/\r
1016{\r
1017 EFI_STATUS Status;\r
1018 EFI_FW_VOL_INSTANCE *FwhInstance;\r
1019 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
1020 UINT32 BufferSize;\r
1021 EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;\r
1022 EFI_HANDLE FwbHandle;\r
1023 EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;\r
1024 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface;\r
1025 UINT32 MaxLbaSize;\r
1026 EFI_PHYSICAL_ADDRESS BaseAddress;\r
1027 UINT64 Length;\r
1028 UINTN NumOfBlocks;\r
1029 EFI_EVENT VirtualAddressChangeEvent;\r
1030\r
1031 if (EFI_ERROR (QemuFlashInitialize ())) {\r
1032 //\r
1033 // Return an error so image will be unloaded\r
1034 //\r
1035 DEBUG ((EFI_D_INFO, "QEMU flash was not detected. Writable FVB is not being installed.\n"));\r
1036 return EFI_WRITE_PROTECTED;\r
1037 }\r
1038\r
1039 //\r
1040 // Allocate runtime services data for global variable, which contains\r
1041 // the private data of all firmware volume block instances\r
1042 //\r
1043 mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL));\r
1044 ASSERT (mFvbModuleGlobal != NULL);\r
1045\r
1046 BaseAddress = (UINTN) PcdGet32 (PcdOvmfFdBaseAddress);\r
1047 Length = PcdGet32 (PcdOvmfFirmwareFdSize);\r
1048\r
1049 Status = InitializeVariableFvHeader ();\r
1050 if (EFI_ERROR (Status)) {\r
1051 DEBUG ((EFI_D_INFO, "QEMU Flash: Unable to initialize variable FV header\n"));\r
1052 return EFI_WRITE_PROTECTED;\r
1053 }\r
1054\r
1055 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;\r
1056 Status = ValidateFvHeader (FwVolHeader);\r
1057 if (EFI_ERROR (Status)) {\r
1058 //\r
1059 // Get FvbInfo\r
1060 //\r
1061 Status = GetFvbInfo (Length, &FwVolHeader);\r
1062 if (EFI_ERROR (Status)) {\r
1063 DEBUG ((EFI_D_INFO, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));\r
1064 return EFI_WRITE_PROTECTED;\r
1065 }\r
1066 }\r
1067\r
1068 BufferSize = (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER));\r
1069\r
1070 //\r
1071 // Only need to allocate once. There is only one copy of physical memory for\r
1072 // the private data of each FV instance. But in virtual mode or in physical\r
1073 // mode, the address of the the physical memory may be different.\r
1074 //\r
1075 mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] = AllocateRuntimePool (BufferSize);\r
1076 ASSERT (mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] != NULL);\r
1077\r
1078 //\r
1079 // Make a virtual copy of the FvInstance pointer.\r
1080 //\r
1081 FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];\r
1082 mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;\r
1083\r
1084 mFvbModuleGlobal->NumFv = 0;\r
1085 MaxLbaSize = 0;\r
1086\r
1087 FwVolHeader =\r
1088 (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN)\r
1089 PcdGet32 (PcdOvmfFlashNvStorageVariableBase);\r
1090\r
1091 FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;\r
1092 FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress;\r
1093\r
1094 CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);\r
1095 FwVolHeader = &(FwhInstance->VolumeHeader);\r
1096 EfiInitializeLock (&(FwhInstance->FvbDevLock), TPL_HIGH_LEVEL);\r
1097\r
1098 NumOfBlocks = 0;\r
1099\r
1100 for (PtrBlockMapEntry = FwVolHeader->BlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
1101 //\r
1102 // Get the maximum size of a block.\r
1103 //\r
1104 if (MaxLbaSize < PtrBlockMapEntry->Length) {\r
1105 MaxLbaSize = PtrBlockMapEntry->Length;\r
1106 }\r
1107\r
1108 NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;\r
1109 }\r
1110\r
1111 //\r
1112 // The total number of blocks in the FV.\r
1113 //\r
1114 FwhInstance->NumOfBlocks = NumOfBlocks;\r
1115\r
1116 //\r
1117 // Add a FVB Protocol Instance\r
1118 //\r
1119 FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));\r
1120 ASSERT (FvbDevice != NULL);\r
1121\r
1122 CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));\r
1123\r
1124 FvbDevice->Instance = mFvbModuleGlobal->NumFv;\r
1125 mFvbModuleGlobal->NumFv++;\r
1126\r
1127 //\r
1128 // Set up the devicepath\r
1129 //\r
1130 if (FwVolHeader->ExtHeaderOffset == 0) {\r
1131 //\r
1132 // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH\r
1133 //\r
1134 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);\r
1135 ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress;\r
1136 ((FV_MEMMAP_DEVICE_PATH *) FvbDevice->DevicePath)->MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;\r
1137 } else {\r
1138 FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);\r
1139 CopyGuid (\r
1140 &((FV_PIWG_DEVICE_PATH *)FvbDevice->DevicePath)->FvDevPath.FvName, \r
1141 (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)\r
1142 );\r
1143 }\r
1144\r
1145 //\r
1146 // Find a handle with a matching device path that has supports FW Block protocol\r
1147 //\r
1148 Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &FvbDevice->DevicePath, &FwbHandle);\r
1149 if (EFI_ERROR (Status)) {\r
1150 //\r
1151 // LocateDevicePath fails so install a new interface and device path\r
1152 //\r
1153 FwbHandle = NULL;\r
1154 DEBUG ((EFI_D_INFO, "Installing QEMU flash FVB\n"));\r
1155 Status = gBS->InstallMultipleProtocolInterfaces (\r
1156 &FwbHandle,\r
1157 &gEfiFirmwareVolumeBlockProtocolGuid,\r
1158 &FvbDevice->FwVolBlockInstance,\r
1159 &gEfiDevicePathProtocolGuid,\r
1160 FvbDevice->DevicePath,\r
1161 NULL\r
1162 );\r
1163 ASSERT_EFI_ERROR (Status);\r
1164 } else if (IsDevicePathEnd (FvbDevice->DevicePath)) {\r
1165 //\r
1166 // Device already exists, so reinstall the FVB protocol\r
1167 //\r
1168 Status = gBS->HandleProtocol (\r
1169 FwbHandle,\r
1170 &gEfiFirmwareVolumeBlockProtocolGuid,\r
1171 (VOID**)&OldFwbInterface\r
1172 );\r
1173 ASSERT_EFI_ERROR (Status);\r
1174\r
1175 DEBUG ((EFI_D_INFO, "Reinstalling FVB for QEMU flash region\n"));\r
1176 Status = gBS->ReinstallProtocolInterface (\r
1177 FwbHandle,\r
1178 &gEfiFirmwareVolumeBlockProtocolGuid,\r
1179 OldFwbInterface,\r
1180 &FvbDevice->FwVolBlockInstance\r
1181 );\r
1182 ASSERT_EFI_ERROR (Status);\r
1183 } else {\r
1184 //\r
1185 // There was a FVB protocol on an End Device Path node\r
1186 //\r
1187 ASSERT (FALSE);\r
1188 }\r
1189\r
1190 MarkMemoryRangeForRuntimeAccess (BaseAddress, Length);\r
1191\r
1192 //\r
1193 // Set several PCD values to point to flash\r
1194 //\r
1195 PcdSet64 (\r
1196 PcdFlashNvStorageVariableBase64,\r
1197 (UINTN) PcdGet32 (PcdOvmfFlashNvStorageVariableBase)\r
1198 );\r
1199 PcdSet32 (\r
1200 PcdFlashNvStorageFtwWorkingBase,\r
1201 PcdGet32 (PcdOvmfFlashNvStorageFtwWorkingBase)\r
1202 );\r
1203 PcdSet32 (\r
1204 PcdFlashNvStorageFtwSpareBase,\r
1205 PcdGet32 (PcdOvmfFlashNvStorageFtwSpareBase)\r
1206 );\r
1207\r
1208 FwhInstance = (EFI_FW_VOL_INSTANCE *)\r
1209 (\r
1210 (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +\r
1211 (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))\r
1212 );\r
1213\r
1214 VirtualAddressChangeEvent = NULL;\r
1215 Status = gBS->CreateEventEx (\r
1216 EVT_NOTIFY_SIGNAL,\r
1217 TPL_NOTIFY,\r
1218 FvbVirtualddressChangeEvent,\r
1219 NULL,\r
1220 &gEfiEventVirtualAddressChangeGuid,\r
1221 &VirtualAddressChangeEvent\r
1222 );\r
1223 ASSERT_EFI_ERROR (Status);\r
1224\r
9d35ac26 1225 PcdSetBool (PcdOvmfFlashVariablesEnable, TRUE);\r
a4ce9ffd
JJ
1226 return EFI_SUCCESS;\r
1227}\r