3 The API to parse the binary.
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <sys/types.h>
17 #include "BinaryParse.h"
18 #include "BinaryCreate.h"
19 #include "VariableCommon.h"
20 #include "FirmwareVolumeBufferLib.h"
22 extern G_EFI_FD_INFO gEfiFdInfo
;
23 extern EFI_HANDLE mParsedGuidedSectionTools
;
24 extern CHAR8 mInputFdName
[MAX_FILENAME_LEN
];
27 // The Guid to sign the position of Vfr and Uni array in FV
29 EFI_GUID gVfrArrayAttractGuid
= EFI_VFR_ATTRACT_GUID
;
30 EFI_GUID gUniStrArrayAttractGuid
= EFI_UNI_STR_ATTRACT_GUID
;
31 EFI_GUID gEfiSystemNvDataFvGuid
= EFI_SYSTEM_NVDATA_FV_GUID
;
32 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid
= EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID
;
35 Converts a three byte length value into a UINT32.
37 @param ThreeByteLength Pointer to the first of the 3 byte length.
39 @retval Length Size of the section
45 IN UINT8
*ThreeByteLength
52 if (ThreeByteLength
== NULL
) {
56 Length
= *((UINT32
*) ThreeByteLength
);
57 Length
= Length
& 0x00FFFFFF;
63 Generate the unique template filename.
73 TemString
= CloneString (tmpnam (NULL
));
75 CHAR8 tmp
[] = "/tmp/fileXXXXXX";
78 TemString
= CloneString(tmp
);
85 Check whether exist the same Ifr FFS. If not existed, return TRUE.
87 @param[in] FfsImage The pointer to the binary.
88 @param[in] FileSize The size of binary.
90 @return The string after convert.
102 while (gEfiFdInfo
.FfsArray
[Index
] != NULL
) {
103 if (memcmp (gEfiFdInfo
.FfsArray
[Index
], FfsImage
, sizeof (EFI_GUID
)) == 0) {
112 This function returns the next larger size that meets the alignment
113 requirement specified.
115 @param ActualSize The size.
116 @param Alignment The desired alignment.
118 @retval The Occupied length
124 IN UINT32 ActualSize
,
130 OccupiedSize
= ActualSize
;
131 while ((OccupiedSize
& (Alignment
- 1)) != 0) {
140 Parses FFS Sections, and remove the FFS headers. Tis function olny handle one efi in this FFS.
142 @param SectionBuffer The section base address
143 @param BufferLength The length of FFS.
144 @param EfiBufferHeader The structure dual pointer to the efi informations
146 @retval EFI_SUCCESS The application exited normally.
147 @retval EFI_ABORTED An error occurred.
152 IN BOOLEAN IsFfsOrEfi
,
153 IN OUT UINT8
*SectionBuffer
,
154 IN UINT32 BufferLength
,
155 IN OUT EFI_SECTION_STRUCT
**EfiBufferHeader
159 EFI_SECTION_TYPE Type
;
161 UINT32 SectionLength
;
162 UINT8
*CompressedBuffer
;
163 UINT32 CompressedLength
;
164 UINT8
*UncompressedBuffer
;
165 UINT32 UncompressedLength
;
166 UINT8 CompressionType
;
167 DECOMPRESS_FUNCTION DecompressFunction
;
168 GETINFO_FUNCTION GetInfoFunction
;
170 UINT8
*ScratchBuffer
;
173 CHAR8
*ExtractionTool
;
174 CHAR8
*ToolInputFile
;
175 CHAR8
*ToolOutputFile
;
176 CHAR8
*SystemCommandFormatString
;
177 CHAR8
*SystemCommand
;
178 UINT8
*ToolOutputBuffer
;
179 UINT32 ToolOutputLength
;
180 BOOLEAN HasDepexSection
;
184 CompressedBuffer
= NULL
;
185 CompressedLength
= 0;
186 UncompressedBuffer
= NULL
;
187 UncompressedLength
= 0;
190 ScratchBuffer
= NULL
;
191 Status
= EFI_SUCCESS
;
193 ExtractionTool
= NULL
;
194 ToolInputFile
= NULL
;
195 ToolOutputFile
= NULL
;
196 SystemCommandFormatString
= NULL
;
197 SystemCommand
= NULL
;
200 // Jump the FFS header
203 SectionBuffer
= SectionBuffer
+ sizeof (EFI_FFS_FILE_HEADER
);
204 BufferLength
= BufferLength
- sizeof (EFI_FFS_FILE_HEADER
);
207 HasDepexSection
= FALSE
;
208 ExtractionTool
= NULL
;
209 ToolOutputLength
= 0;
210 ToolOutputBuffer
= NULL
;
212 (*EfiBufferHeader
)->Length
= BufferLength
;
214 while (ParsedLength
< BufferLength
) {
215 Ptr
= SectionBuffer
+ ParsedLength
;
217 SectionLength
= Get3ByteLength (((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Size
);
218 Type
= ((EFI_COMMON_SECTION_HEADER
*) Ptr
)->Type
;
221 // This is sort of an odd check, but is necessary because FFS files are
222 // padded to a QWORD boundary, meaning there is potentially a whole section
223 // header worth of 0xFF bytes.
225 if ((SectionLength
== 0xffffff) && (Type
== 0xff)) {
232 case EFI_SECTION_PE32
:
235 //Got the correct address
237 (*EfiBufferHeader
)->BufferBase
= (UINTN
)(Ptr
+ sizeof (EFI_COMMON_SECTION_HEADER
));
240 case EFI_SECTION_RAW
:
241 case EFI_SECTION_PIC
:
244 case EFI_SECTION_USER_INTERFACE
:
245 HasDepexSection
= FALSE
;
248 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE
:
249 case EFI_SECTION_COMPATIBILITY16
:
250 case EFI_SECTION_FREEFORM_SUBTYPE_GUID
:
253 case EFI_SECTION_PEI_DEPEX
:
254 case EFI_SECTION_DXE_DEPEX
:
255 case EFI_SECTION_SMM_DEPEX
:
256 HasDepexSection
= TRUE
;
259 case EFI_SECTION_VERSION
:
261 case EFI_SECTION_COMPRESSION
:
262 UncompressedBuffer
= NULL
;
263 CompressedLength
= SectionLength
- sizeof (EFI_COMPRESSION_SECTION
);
264 UncompressedLength
= ((EFI_COMPRESSION_SECTION
*) Ptr
)->UncompressedLength
;
265 CompressionType
= ((EFI_COMPRESSION_SECTION
*) Ptr
)->CompressionType
;
267 if (CompressionType
== EFI_NOT_COMPRESSED
) {
268 if (CompressedLength
!= UncompressedLength
) {
273 "file is not compressed, but the compressed length does not match the uncompressed length",
279 UncompressedBuffer
= Ptr
+ sizeof (EFI_COMPRESSION_SECTION
);
280 } else if (CompressionType
== EFI_STANDARD_COMPRESSION
) {
281 GetInfoFunction
= EfiGetInfo
;
282 DecompressFunction
= EfiDecompress
;
283 CompressedBuffer
= Ptr
+ sizeof (EFI_COMPRESSION_SECTION
);
285 Status
= GetInfoFunction (
291 if (EFI_ERROR (Status
)) {
292 Error (NULL
, 0, 0003, "error getting compression info from compression section", NULL
);
296 if (DstSize
!= UncompressedLength
) {
297 Error (NULL
, 0, 0003, "compression error in the compression section", NULL
);
301 ScratchBuffer
= malloc (ScratchSize
);
302 if (ScratchBuffer
== NULL
) {
305 UncompressedBuffer
= malloc (UncompressedLength
);
306 if (UncompressedBuffer
== NULL
) {
307 free (ScratchBuffer
);
310 memset (UncompressedBuffer
, 0, UncompressedLength
);
312 Status
= DecompressFunction (
320 free (ScratchBuffer
);
321 if (Status
!= EFI_SUCCESS
) {
322 Error (NULL
, 0, 0003, "decompress failed", NULL
);
323 free (UncompressedBuffer
);
327 Error (NULL
, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType
);
331 Status
= ParseSection (FALSE
, UncompressedBuffer
, UncompressedLength
, EfiBufferHeader
);
332 if (Status
!= EFI_SUCCESS
) {
333 Error (NULL
, 0, 0003, "failed to parse section", NULL
);
334 free (UncompressedBuffer
);
335 UncompressedBuffer
= NULL
;
340 // Store the allocate memory address for UncompressedBuffer
342 if (UncompressedBuffer
!= NULL
) {
343 (*EfiBufferHeader
)->UncompressedBuffer
[(*EfiBufferHeader
)->UnCompressIndex
] = (UINTN
) UncompressedBuffer
;
344 (*EfiBufferHeader
)->UnCompressIndex
= (*EfiBufferHeader
)->UnCompressIndex
+ 1;
348 case EFI_SECTION_GUID_DEFINED
:
350 // Decompress failed, and then check for CRC32 sections which we can handle internally if needed.
351 // Maybe this section is no-compressed.
354 &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
,
355 &gEfiCrc32GuidedSectionExtractionProtocolGuid
358 // CRC32 guided section
360 Status
= ParseSection (
362 SectionBuffer
+ ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
,
363 BufferLength
- ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
,
366 if (EFI_ERROR (Status
)) {
367 Error (NULL
, 0, 0003, "parse of CRC32 GUIDED section failed", NULL
);
373 ExtractionTool
= LookupGuidedSectionToolPath (
374 mParsedGuidedSectionTools
,
375 &((EFI_GUID_DEFINED_SECTION
*) Ptr
)->SectionDefinitionGuid
378 if (ExtractionTool
!= NULL
) {
379 ToolInputFile
= GenTempFile ();
380 ToolOutputFile
= GenTempFile ();
382 // Construction 'system' command string
384 SystemCommandFormatString
= "%s -d -o \"%s\" \"%s\"";
385 SystemCommand
= malloc (
386 strlen (SystemCommandFormatString
) \
387 + strlen (ExtractionTool
) \
388 + strlen (ToolInputFile
) \
389 + strlen (ToolOutputFile
) \
392 if (SystemCommand
== NULL
) {
393 free (ExtractionTool
);
394 free (ToolInputFile
);
395 free (ToolOutputFile
);
400 "%s -d -o \"%s\" \"%s\"",
405 free (ExtractionTool
);
407 Status
= PutFileImage (
409 (CHAR8
*) Ptr
+ ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
,
410 SectionLength
- ((EFI_GUID_DEFINED_SECTION
*) Ptr
)->DataOffset
413 if (HasDepexSection
) {
414 HasDepexSection
= FALSE
;
417 system (SystemCommand
);
418 remove (ToolInputFile
);
419 free (ToolInputFile
);
420 ToolInputFile
= NULL
;
421 free (SystemCommand
);
422 SystemCommand
= NULL
;
424 if (EFI_ERROR (Status
)) {
425 Error ("FCE", 0, 0004, "unable to decoded GUIDED section", NULL
);
426 free (ToolOutputFile
);
430 Status
= GetFileImage (
432 (CHAR8
**)&ToolOutputBuffer
,
435 remove (ToolOutputFile
);
436 free (ToolOutputFile
);
437 ToolOutputFile
= NULL
;
438 if (EFI_ERROR (Status
)) {
442 Status
= ParseSection (
448 if (EFI_ERROR (Status
)) {
449 Error (NULL
, 0, 0003, "parse of decoded GUIDED section failed", NULL
);
458 ParsedLength
+= SectionLength
;
460 // We make then next section begin on a 4-byte boundary
462 ParsedLength
= GetOccupiedSize (ParsedLength
, 4);
478 if (*Offset
>= Len
|| Len
- *Offset
<= sizeof (EFI_GUID
)) {
482 for (NextOffset
= *Offset
; NextOffset
< Len
- sizeof (EFI_GUID
); NextOffset
++) {
483 if (CompareGuid(Guid
, (EFI_GUID
*)(Data
+ NextOffset
)) == 0) {
484 *Offset
= NextOffset
+ sizeof(EFI_GUID
);
492 Get the address by Guid.
494 Parse the FFS image, and find the GUID address.There may be some Guids matching the
497 @param Fv the Pointer to the image.
498 @param Guid The Guid need to find.
499 @param Offset The dual Pointer to the offset.
500 @param NumOfMatchGuid The number of matching Guid offset.
502 @retval EFI_SUCCESS The Search was complete successfully
503 @return EFI_ABORTED An error occurred
511 OUT UINT8
*NumOfMatchGuid
517 EFI_RAW_SECTION
* Section
;
522 UINTN TotalSectionsSize
;
527 if( (Fv
== NULL
) || (Fv
== NULL
) || (Guid
== NULL
) || Len
== 0 ){
536 if (NumOfMatchGuid
!= NULL
) {
540 SectionStart
= (VOID
*)((UINTN
)LocalFv
+ FvBufGetFfsHeaderSize(LocalFv
));
541 TotalSectionsSize
= Len
- FvBufGetFfsHeaderSize(LocalFv
);
543 Status
= FvBufFindNextSection (
549 if (Section
== NULL
|| EFI_ERROR (Status
)) {
553 if (EFI_SECTION_RAW
== Section
->Type
) {
554 if ((*(UINT32
*)Section
->Size
& 0xffffff) == 0xffffff) {
555 SecLen
= ((EFI_RAW_SECTION2
*)Section
)->ExtendedSize
;
556 SecHdr
= sizeof(EFI_RAW_SECTION2
);
558 SecLen
= *(UINT32
*)Section
->Size
& 0xffffff;
559 SecHdr
= sizeof(EFI_RAW_SECTION
);
561 if (SecLen
<= SecHdr
|| SecLen
- SecHdr
< sizeof(EFI_GUID
)) {
564 RawData
= (UINT8
*)Section
+ SecHdr
;
566 while (GetNextOffset(RawData
, Guid
, SecLen
- SecHdr
, &NextOffset
)) {
568 if ((NumOfMatchGuid
!= NULL
) && (Offset
!= NULL
)) {
569 if (*NumOfMatchGuid
== 0) {
570 *Offset
= malloc (sizeof (UINTN
) * MAX_MATCH_GUID_NUM
);
571 if (*Offset
== NULL
) {
574 memset (*Offset
, 0, sizeof (UINTN
) * MAX_MATCH_GUID_NUM
);
576 *(*Offset
+ *NumOfMatchGuid
) = NextOffset
+ (RawData
- (UINT8
*)Fv
);
592 Search the VfrBin Base address.
594 According the known GUID gVfrArrayAttractGuid to get the base address from FFS.
596 @param Fv the Pointer to the FFS
597 @param EfiAddr the Pointer to the EFI in FFS
598 @param Length the length of Fv
599 @param Offset the Pointer to the Addr (Offset)
600 @param NumOfMachingOffset the number of Addr (Offset)
602 @retval EFI_SUCCESS Get the address successfully.
610 OUT UINT8
*NumOfMachingOffset
618 Status
= EFI_SUCCESS
;
621 if ((Fv
== NULL
) || (Offset
== NULL
)) {
624 Status
= GetAddressByGuid (
626 &gVfrArrayAttractGuid
,
631 if (Status
!= EFI_SUCCESS
) {
635 while (Index
< *NumOfMachingOffset
) {
637 // Got the virOffset after the GUID
639 VirOffValue
= *(UINTN
*)((UINTN
)Fv
+ *(*Offset
+ Index
));
641 //Transfer the offset to the VA address. One modules may own more VfrBin address.
643 *(*Offset
+ Index
) = (UINTN
) EfiAddr
+ VirOffValue
;
650 Search the UniBin Base address.
652 According the known GUID gUniStrArrayAttractGuid to get the base address from FFS.
654 @param Fv the Pointer to the FFS
655 @param EfiAddr the Pointer to the EFI in FFS
656 @param Length the length of Fv
657 @param Offset the Pointer to the Addr (Offset)
659 @retval Base address Get the address successfully.
669 UINT8 NumOfMachingOffset
;
673 NumOfMachingOffset
= 0;
674 Status
= EFI_SUCCESS
;
677 if ((Fv
== NULL
) || (Offset
== NULL
)) {
680 Status
= GetAddressByGuid (
682 &gUniStrArrayAttractGuid
,
687 if (Status
!= EFI_SUCCESS
) {
691 //Transfer the offset to the VA address. There is only one UniArray in one modules.
693 if (NumOfMachingOffset
== 1) {
694 VirOffValue
= *(UINTN
*)((UINTN
)Fv
+ **Offset
);
695 **Offset
= (UINTN
) EfiAddr
+ VirOffValue
;
697 printf ("Error. Find more than 1 UniBin in FFS.\n");
705 SearchNvStoreDatabaseInFd(
712 PCD_NV_STORE_DEFAULT_BUFFER_HEADER
*NvStoreHeader
;
713 Status
= EFI_SUCCESS
;
716 printf ("The FV is NULL.");
719 while (Offset
< (length
- sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER
))){
720 NvStoreHeader
= (PCD_NV_STORE_DEFAULT_BUFFER_HEADER
*)((UINT8
*)Fv
+ Offset
);
721 if (NvStoreHeader
->Signature
== PCD_NV_STORE_DEFAULT_BUFFER_SIGNATURE
) {
722 gEfiFdInfo
.ExistNvStoreDatabase
= TRUE
;
723 gEfiFdInfo
.NvStoreDatabase
= (UINT8
*) NvStoreHeader
;
728 if (Offset
== (length
- sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER
)) || gEfiFdInfo
.ExistNvStoreDatabase
!= TRUE
) {
729 //printf ("Not found the PcdNvStoreDefaultValueBuffer\n");
736 Get the address by Guid.
738 Parse the FD image, and find the GUID address.There may be some Guids matching the
741 @param Fv the Pointer to the image.
742 @param Guid The Guid need to find.
743 @param Offset The dual Pointer to the offset.
744 @param NumOfMatchGuid The number of matching Guid offset.
746 @retval EFI_SUCCESS The Search was complete successfully
747 @return EFI_ABORTED An error occurred
750 GetVariableAddressByGuid (
755 OUT UINT8
*NumOfMatchGuid
761 if( (Fv
== NULL
) || (Fv
== NULL
) || (Guid
== NULL
) ){
768 if (NumOfMatchGuid
!= NULL
) {
771 while (GetNextOffset(Fv
, Guid
, Len
, &NextOffset
)) {
773 if (NumOfMatchGuid
!= NULL
&& Offset
!= NULL
) {
774 if (*NumOfMatchGuid
== 0) {
775 *Offset
= malloc (sizeof (UINTN
) * MAX_MATCH_GUID_NUM
);
776 if (*Offset
== NULL
) {
779 memset (*Offset
, 0, sizeof (UINTN
) * MAX_MATCH_GUID_NUM
);
781 *(*Offset
+ *NumOfMatchGuid
) = NextOffset
;
795 Search the EFI Variable Base address.
797 According the known GUID gEfiSystemNvDataFvGuid to get the base address from FFS.
799 @param Fv the Pointer to the FFS
800 @param Length the length of Fv
801 @param Offset the Pointer to the Addr (Offset)
802 @param NumOfMachingOffset the number of IFR array in one FFS
804 @retval EFI_SUCCESS Get the address successfully.
805 @retval EFI_ABORTED An error occured.
812 OUT UINT8
*NumOfMachingOffset
818 Status
= EFI_SUCCESS
;
821 if ((Fv
== NULL
) || (Offset
== NULL
)) {
822 printf ("The FV or offset is NULL.");
825 Status
= GetVariableAddressByGuid (
827 &gEfiSystemNvDataFvGuid
,
832 if (Status
!= EFI_SUCCESS
) {
836 //Transfer the offset to the VA address.
838 while (Index
< *NumOfMachingOffset
) {
839 *(*Offset
+ Index
) = (UINTN
) Fv
+ *(*Offset
+ Index
);
846 Parse the Ffs header to get the size.
848 @param InputFile The pointer to the input file
849 @param FvSize The pointer to the file size
851 @return EFI_SUCCESS Get the file size successfully
859 EFI_FFS_FILE_HEADER FfsHeader
;
860 EFI_FV_FILETYPE Type
;
863 // Check input parameters
865 if ((InputFile
== NULL
) || (FvSize
== NULL
)) {
873 sizeof (EFI_FFS_FILE_HEADER
),
877 Type
= FfsHeader
.Type
;
879 if (Type
== EFI_FV_FILETYPE_DRIVER
) {
880 *FvSize
= *(UINT32
*)FfsHeader
.Size
& 0xffffff;
881 } else if (Type
== EFI_FV_FILETYPE_APPLICATION
) {
882 *FvSize
= *(UINT32
*)FfsHeader
.Size
& 0xffffff;
883 } else if (Type
== EFI_FV_FILETYPE_FREEFORM
) {
884 *FvSize
= *(UINT32
*)FfsHeader
.Size
& 0xffffff;
892 Read the length of the whole FD
894 This function determines the size of the FV.
896 @param InputFile The file that contains the FV image.
897 @param FvSize The size of the FV.
899 @retval EFI_SUCCESS The application exited normally.
900 @retval EFI_ABORTED An error occurred.
911 // Check input parameters
913 if ((InputFile
== NULL
) || (FvSize
== NULL
)) {
918 // Get the total size of FD file (Fixed the length)
920 fseek(InputFile
,0,SEEK_END
);
921 *FvSize
= ftell(InputFile
);
922 fseek(InputFile
,0,SEEK_SET
);
931 Read the file to memory.
933 @param InputFile The file that contains the FV image.
934 @param Size The size of the file.
936 @retval The pointer to the begining position of memory.
952 Status
= EFI_SUCCESS
;
954 InFile
= fopen (FileName
,"rb");
955 if (InFile
== NULL
) {
959 // Determine the size of FV
961 Status
= ReadFdHeader (InFile
, Size
);
962 if (Status
!= EFI_SUCCESS
) {
967 // Allocate a buffer for the FV image
969 Address
= malloc (*Size
);
970 if (Address
== NULL
) {
974 memset (Address
, 0, *Size
);
976 // Seek to the start of the image, then read the entire FV to the buffer
978 fseek (InFile
, 0, SEEK_SET
);
979 BytesRead
= fread (Address
, 1, *Size
, InFile
);
981 if ((UINTN
) BytesRead
!= *Size
) {
989 Search the EFI variables address in Fd.
991 Open and read the *.fd to the memory, initialize the global structure.
992 Update the EFI variables addr and the begining position of memory.
994 @retval EFI_SUCCESS Get the address successfully.
997 GetEfiVariablesAddr (
1005 UINT8 NumOfMachingVar
;
1008 EFI_FIRMWARE_VOLUME_HEADER
*Variable
;
1009 BOOLEAN AuthencitatedMonotonicOrNot
;
1010 BOOLEAN AuthencitatedBasedTimeOrNot
;
1011 BOOLEAN NormalOrNot
;
1015 Status
= EFI_SUCCESS
;
1017 NumOfMachingVar
= 0;
1022 FdImage
= ReadFileToMemory (mInputFdName
, &FdSize
);
1023 if (FdImage
== NULL
) {
1027 Status
= SearchNvStoreDatabaseInFd(FdImage
, FdSize
);
1028 if (EFI_ERROR (Status
)) {
1032 Status
= SearchEfiVarInFFS (
1038 if (EFI_ERROR (Status
)) {
1042 // Check the signature "_FVH"
1047 while (Index
< NumOfMachingVar
) {
1048 Variable
= (EFI_FIRMWARE_VOLUME_HEADER
*)(*(EfiVarAddr
+ Index
) - 0x20);
1049 if (Variable
->Signature
== 0x4856465F) {
1050 AuthencitatedMonotonicOrNot
= CheckMonotonicBasedVarStore ((UINT8
*)Variable
+ Variable
->HeaderLength
);
1051 AuthencitatedBasedTimeOrNot
= CheckTimeBasedVarStoreOrNot ((UINT8
*)Variable
+ Variable
->HeaderLength
);
1052 NormalOrNot
= CheckNormalVarStoreOrNot ((UINT8
*)Variable
+ Variable
->HeaderLength
);
1053 if (AuthencitatedMonotonicOrNot
|| AuthencitatedBasedTimeOrNot
|| NormalOrNot
) {
1055 gEfiFdInfo
.EfiVariableAddr
= (UINTN
)Variable
;
1065 gEfiFdInfo
.Fd
= FdImage
;
1066 gEfiFdInfo
.FdSize
= FdSize
;
1072 Pick up the FFS which includes IFR section.
1074 Parse all FFS extracted by BfmLib, and save all which includes IFR
1075 Binary to gEfiFdInfo structure.
1077 @retval EFI_SUCCESS Get the address successfully.
1078 @retval EFI_BUFFER_TOO_SMALL Memory can't be allocated.
1079 @retval EFI_ABORTED Read FFS Failed.
1083 IN CHAR8
*FolderName
,
1084 OUT BOOLEAN
*ExistStorageInBfv
,
1085 OUT BOOLEAN
*SizeOptimized
1089 CHAR8
*CurFolderName
;
1091 UINTN MaxFileNameLen
;
1093 CHAR8 FileNameArry
[MAX_FILENAME_LEN
];
1100 WIN32_FIND_DATA FindFileData
;
1102 struct dirent
*pDirent
;
1107 CurFolderName
= NULL
;
1108 Status
= EFI_SUCCESS
;
1116 MaxFileNameLen
= strlen (FolderName
) + MAX_FILENAME_LEN
;
1117 CurFolderName
= (CHAR8
*)calloc(
1118 strlen (FolderName
) + strlen (OS_SEP_STR
) + strlen ("*.*")+ 1,
1121 if (CurFolderName
== NULL
) {
1122 return EFI_BUFFER_TOO_SMALL
;
1124 strcpy (CurFolderName
, FolderName
);
1125 strcat (CurFolderName
, OS_SEP_STR
);
1126 strcat (CurFolderName
, "*.*");
1127 FileName
= (CHAR8
*)calloc(
1131 if (FileName
== NULL
) {
1132 free (CurFolderName
);
1133 return EFI_BUFFER_TOO_SMALL
;
1137 if((FindHandle
= FindFirstFile(CurFolderName
, &FindFileData
)) != INVALID_HANDLE_VALUE
){
1139 memset (FileName
, 0, MaxFileNameLen
);
1140 if ((strcmp (FindFileData
.cFileName
, ".") == 0)
1141 || (strcmp (FindFileData
.cFileName
, "..") == 0)
1145 if (strlen(FolderName
) + strlen ("\\") + strlen (FindFileData
.cFileName
) > MAX_FILENAME_LEN
- 1) {
1146 Status
= EFI_ABORTED
;
1149 snprintf (FileNameArry
, MAX_FILENAME_LEN
, "%s%c%s", FolderName
, OS_SEP
, FindFileData
.cFileName
);
1150 FfsFile
= fopen (FileNameArry
, "rb");
1151 if (FfsFile
== NULL
) {
1152 Status
= EFI_ABORTED
;
1155 Status
= ReadFfsHeader (FfsFile
, (UINT32
*)&FileSize
);
1156 if (EFI_ERROR (Status
)) {
1158 Status
= EFI_SUCCESS
;
1162 // Allocate a buffer for the FFS file
1164 FfsImage
= malloc (FileSize
);
1165 if (FfsImage
== NULL
) {
1167 Status
= EFI_BUFFER_TOO_SMALL
;
1171 // Seek to the start of the image, then read the entire FV to the buffer
1173 fseek (FfsFile
, 0, SEEK_SET
);
1174 BytesRead
= fread (FfsImage
, 1, FileSize
, FfsFile
);
1177 if ((UINTN
) BytesRead
!= FileSize
) {
1179 Status
= EFI_ABORTED
;
1183 // Check whether exists the storage ffs in BFV for multi-platform mode
1185 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid
,(EFI_GUID
*) FfsImage
) == 0) {
1186 *ExistStorageInBfv
= TRUE
;
1187 *SizeOptimized
= FALSE
;
1188 gEfiFdInfo
.StorageFfsInBfv
= FfsImage
;
1192 // Check whether exists the optimized storage ffs in BFV for multi-platform mode
1194 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2
,(EFI_GUID
*) FfsImage
) == 0) {
1195 *ExistStorageInBfv
= TRUE
;
1196 *SizeOptimized
= TRUE
;
1197 gEfiFdInfo
.StorageFfsInBfv
= FfsImage
;
1201 // Check whether current FFS includes IFR
1203 Status
= GetAddressByGuid (
1205 &gVfrArrayAttractGuid
,
1210 if (EFI_ERROR (Status
)) {
1212 Status
= EFI_SUCCESS
;
1215 // Check whether existed same IFR binary. If existed, not insert the new one.
1217 if (NotExistSameFfsIfr (FfsImage
)) {
1218 gEfiFdInfo
.FfsArray
[Index
] = FfsImage
;
1219 gEfiFdInfo
.Length
[Index
++] = FileSize
;
1223 } while (FindNextFile (FindHandle
, &FindFileData
));
1224 FindClose(FindHandle
);
1226 Status
= EFI_ABORTED
;
1231 free (CurFolderName
);
1235 if((pDir
= opendir(FolderName
)) != NULL
){
1236 while ((pDirent
= readdir(pDir
)) != NULL
){
1237 memset (FileName
, 0, MaxFileNameLen
);
1238 if ((strcmp (pDirent
->d_name
, ".") == 0)
1239 || (strcmp (pDirent
->d_name
, "..") == 0)
1243 sprintf (FileNameArry
, "%s%c%s", FolderName
, OS_SEP
, pDirent
->d_name
);
1244 FfsFile
= fopen (FileNameArry
, "rb");
1245 Status
= ReadFfsHeader (FfsFile
, (UINT32
*)&FileSize
);
1246 if (EFI_ERROR (Status
)) {
1248 Status
= EFI_SUCCESS
;
1252 // Allocate a buffer for the FFS file
1254 FfsImage
= malloc (FileSize
);
1255 if (FfsImage
== NULL
) {
1257 Status
= EFI_BUFFER_TOO_SMALL
;
1261 // Seek to the start of the image, then read the entire FV to the buffer
1263 fseek (FfsFile
, 0, SEEK_SET
);
1264 BytesRead
= fread (FfsImage
, 1, FileSize
, FfsFile
);
1267 if ((UINTN
) BytesRead
!= FileSize
) {
1269 Status
= EFI_ABORTED
;
1273 // Check whether exists the storage ffs in BFV for multi-platform mode
1275 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid
,(EFI_GUID
*) FfsImage
) == 0) {
1276 *ExistStorageInBfv
= TRUE
;
1277 *SizeOptimized
= FALSE
;
1278 gEfiFdInfo
.StorageFfsInBfv
= FfsImage
;
1282 // Check whether exists the optimized storage ffs in BFV for multi-platform mode
1284 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2
,(EFI_GUID
*) FfsImage
) == 0) {
1285 *ExistStorageInBfv
= TRUE
;
1286 *SizeOptimized
= TRUE
;
1287 gEfiFdInfo
.StorageFfsInBfv
= FfsImage
;
1291 // Check whether current FFS includes IFR
1293 Status
= GetAddressByGuid (
1295 &gVfrArrayAttractGuid
,
1300 if (EFI_ERROR (Status
)) {
1302 Status
= EFI_SUCCESS
;
1305 // Check whether existed same IFR binary. If existed, not insert the new one.
1307 if (NotExistSameFfsIfr (FfsImage
)) {
1308 gEfiFdInfo
.FfsArray
[Index
] = FfsImage
;
1309 gEfiFdInfo
.Length
[Index
++] = FileSize
;
1316 Status
= EFI_ABORTED
;
1321 free (CurFolderName
);