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