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