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