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