]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/FCE/BinaryParse.c
Revert "BaseTools/FMMT: Add a tool FMMT"
[mirror_edk2.git] / BaseTools / Source / C / FCE / BinaryParse.c
CommitLineData
3c59d946
SZ
1/** @file\r
2\r
3 The API to parse the binary.\r
4\r
5 Copyright (c) 2011-2019, Intel Corporation. All rights reserved.<BR>\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7\r
8**/\r
9\r
10#ifndef __GNUC__\r
11#include "windows.h"\r
12#else\r
13#include <sys/types.h>\r
14#include <dirent.h>\r
15#include <unistd.h>\r
16#endif\r
17#include "BinaryParse.h"\r
18#include "BinaryCreate.h"\r
19#include "VariableCommon.h"\r
20#include "FirmwareVolumeBufferLib.h"\r
21\r
22extern G_EFI_FD_INFO gEfiFdInfo;\r
23extern EFI_HANDLE mParsedGuidedSectionTools;\r
24extern CHAR8 mInputFdName[MAX_FILENAME_LEN];\r
25\r
26//\r
27// The Guid to sign the position of Vfr and Uni array in FV\r
28//\r
29EFI_GUID gVfrArrayAttractGuid = EFI_VFR_ATTRACT_GUID;\r
30EFI_GUID gUniStrArrayAttractGuid = EFI_UNI_STR_ATTRACT_GUID;\r
31EFI_GUID gEfiSystemNvDataFvGuid = EFI_SYSTEM_NVDATA_FV_GUID;\r
32EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
33\r
34/**\r
35 Converts a three byte length value into a UINT32.\r
36\r
37 @param ThreeByteLength Pointer to the first of the 3 byte length.\r
38\r
39 @retval Length Size of the section\r
40\r
41**/\r
42static\r
43UINT32\r
44Get3ByteLength (\r
45 IN UINT8 *ThreeByteLength\r
46 )\r
47{\r
48 UINT32 Length;\r
49\r
50 Length = 0;\r
51\r
52 if (ThreeByteLength == NULL) {\r
53 return 0;\r
54 }\r
55\r
56 Length = *((UINT32 *) ThreeByteLength);\r
57 Length = Length & 0x00FFFFFF;\r
58\r
59 return Length;\r
60}\r
61\r
62/**\r
63 Generate the unique template filename.\r
64**/\r
65CHAR8 *\r
66GenTempFile (\r
67 VOID\r
68 )\r
69{\r
70 CHAR8 *TemString;\r
71 TemString = NULL;\r
72#ifndef __GNUC__\r
73 TemString = CloneString (tmpnam (NULL));\r
74#else\r
75 CHAR8 tmp[] = "/tmp/fileXXXXXX";\r
76 UINTN Fdtmp;\r
77 Fdtmp = mkstemp(tmp);\r
78 TemString = CloneString(tmp);\r
79 close(Fdtmp);\r
80#endif\r
81 return TemString;\r
82}\r
83\r
84/**\r
85 Check whether exist the same Ifr FFS. If not existed, return TRUE.\r
86\r
87 @param[in] FfsImage The pointer to the binary.\r
88 @param[in] FileSize The size of binary.\r
89\r
90 @return The string after convert.\r
91**/\r
92static\r
93BOOLEAN\r
94NotExistSameFfsIfr (\r
95 IN VOID *FfsImage\r
96)\r
97{\r
98 UINT32 Index;\r
99\r
100 Index = 0;\r
101\r
102 while (gEfiFdInfo.FfsArray[Index] != NULL) {\r
103 if (memcmp (gEfiFdInfo.FfsArray[Index], FfsImage, sizeof (EFI_GUID)) == 0) {\r
104 return FALSE;\r
105 }\r
106 Index++;\r
107 }\r
108 return TRUE;\r
109}\r
110\r
111/**\r
112 This function returns the next larger size that meets the alignment\r
113 requirement specified.\r
114\r
115 @param ActualSize The size.\r
116 @param Alignment The desired alignment.\r
117\r
118 @retval The Occupied length\r
119\r
120**/\r
121static\r
122UINT32\r
123GetOccupiedSize (\r
124 IN UINT32 ActualSize,\r
125 IN UINT32 Alignment\r
126 )\r
127{\r
128 UINT32 OccupiedSize;\r
129\r
130 OccupiedSize = ActualSize;\r
131 while ((OccupiedSize & (Alignment - 1)) != 0) {\r
132 OccupiedSize++;\r
133 }\r
134\r
135 return OccupiedSize;\r
136}\r
137\r
138\r
139/**\r
140 Parses FFS Sections, and remove the FFS headers. Tis function olny handle one efi in this FFS.\r
141\r
142 @param SectionBuffer The section base address\r
143 @param BufferLength The length of FFS.\r
144 @param EfiBufferHeader The structure dual pointer to the efi informations\r
145\r
146 @retval EFI_SUCCESS The application exited normally.\r
147 @retval EFI_ABORTED An error occurred.\r
148\r
149**/\r
150EFI_STATUS\r
151ParseSection (\r
152 IN BOOLEAN IsFfsOrEfi,\r
153 IN OUT UINT8 *SectionBuffer,\r
154 IN UINT32 BufferLength,\r
155 IN OUT EFI_SECTION_STRUCT **EfiBufferHeader\r
156 )\r
157{\r
158 UINT32 ParsedLength;\r
159 EFI_SECTION_TYPE Type;\r
160 UINT8 *Ptr;\r
161 UINT32 SectionLength;\r
162 UINT8 *CompressedBuffer;\r
163 UINT32 CompressedLength;\r
164 UINT8 *UncompressedBuffer;\r
165 UINT32 UncompressedLength;\r
166 UINT8 CompressionType;\r
167 DECOMPRESS_FUNCTION DecompressFunction;\r
168 GETINFO_FUNCTION GetInfoFunction;\r
169 UINT32 ScratchSize;\r
170 UINT8 *ScratchBuffer;\r
171 EFI_STATUS Status;\r
172 UINT32 DstSize;\r
173 CHAR8 *ExtractionTool;\r
174 CHAR8 *ToolInputFile;\r
175 CHAR8 *ToolOutputFile;\r
176 CHAR8 *SystemCommandFormatString;\r
177 CHAR8 *SystemCommand;\r
178 UINT8 *ToolOutputBuffer;\r
179 UINT32 ToolOutputLength;\r
180 BOOLEAN HasDepexSection;\r
181\r
182 Ptr = NULL;\r
183 SectionLength = 0;\r
184 CompressedBuffer = NULL;\r
185 CompressedLength = 0;\r
186 UncompressedBuffer = NULL;\r
187 UncompressedLength = 0;\r
188 CompressionType = 0;\r
189 ScratchSize = 0;\r
190 ScratchBuffer = NULL;\r
191 Status = EFI_SUCCESS;\r
192 DstSize = 0;\r
193 ExtractionTool = NULL;\r
194 ToolInputFile = NULL;\r
195 ToolOutputFile = NULL;\r
196 SystemCommandFormatString = NULL;\r
197 SystemCommand = NULL;\r
198\r
199 //\r
200 // Jump the FFS header\r
201 //\r
202 if (IsFfsOrEfi) {\r
203 SectionBuffer = SectionBuffer + sizeof (EFI_FFS_FILE_HEADER);\r
204 BufferLength = BufferLength - sizeof (EFI_FFS_FILE_HEADER);\r
205 }\r
206 ParsedLength = 0;\r
207 HasDepexSection = FALSE;\r
208 ExtractionTool = NULL;\r
209 ToolOutputLength = 0;\r
210 ToolOutputBuffer = NULL;\r
211\r
212 (*EfiBufferHeader)->Length = BufferLength;\r
213\r
214 while (ParsedLength < BufferLength) {\r
215 Ptr = SectionBuffer + ParsedLength;\r
216\r
217 SectionLength = Get3ByteLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);\r
218 Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;\r
219\r
220 //\r
221 // This is sort of an odd check, but is necessary because FFS files are\r
222 // padded to a QWORD boundary, meaning there is potentially a whole section\r
223 // header worth of 0xFF bytes.\r
224 //\r
225 if ((SectionLength == 0xffffff) && (Type == 0xff)) {\r
226 ParsedLength += 4;\r
227 continue;\r
228 }\r
229\r
230 switch (Type) {\r
231\r
232 case EFI_SECTION_PE32:\r
233 case EFI_SECTION_TE:\r
234 //\r
235 //Got the correct address\r
236 //\r
237 (*EfiBufferHeader)->BufferBase = (UINTN)(Ptr + sizeof (EFI_COMMON_SECTION_HEADER));\r
238 return EFI_SUCCESS;\r
239\r
240 case EFI_SECTION_RAW:\r
241 case EFI_SECTION_PIC:\r
242 break;\r
243\r
244 case EFI_SECTION_USER_INTERFACE:\r
245 HasDepexSection = FALSE;\r
246 break;\r
247\r
248 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
249 case EFI_SECTION_COMPATIBILITY16:\r
250 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:\r
251 break;\r
252\r
253 case EFI_SECTION_PEI_DEPEX:\r
254 case EFI_SECTION_DXE_DEPEX:\r
255 case EFI_SECTION_SMM_DEPEX:\r
256 HasDepexSection = TRUE;\r
257 break;\r
258\r
259 case EFI_SECTION_VERSION:\r
260 break;\r
261 case EFI_SECTION_COMPRESSION:\r
262 UncompressedBuffer = NULL;\r
263 CompressedLength = SectionLength - sizeof (EFI_COMPRESSION_SECTION);\r
264 UncompressedLength = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength;\r
265 CompressionType = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType;\r
266\r
267 if (CompressionType == EFI_NOT_COMPRESSED) {\r
268 if (CompressedLength != UncompressedLength) {\r
269 Error (\r
270 NULL,\r
271 0,\r
272 0,\r
273 "file is not compressed, but the compressed length does not match the uncompressed length",\r
274 NULL\r
275 );\r
276 return EFI_ABORTED;\r
277 }\r
278\r
279 UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);\r
280 } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
281 GetInfoFunction = EfiGetInfo;\r
282 DecompressFunction = EfiDecompress;\r
283 CompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);\r
284\r
285 Status = GetInfoFunction (\r
286 CompressedBuffer,\r
287 CompressedLength,\r
288 &DstSize,\r
289 &ScratchSize\r
290 );\r
291 if (EFI_ERROR (Status)) {\r
292 Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);\r
293 return EFI_ABORTED;\r
294 }\r
295\r
296 if (DstSize != UncompressedLength) {\r
297 Error (NULL, 0, 0003, "compression error in the compression section", NULL);\r
298 return EFI_ABORTED;\r
299 }\r
300\r
301 ScratchBuffer = malloc (ScratchSize);\r
302 if (ScratchBuffer == NULL) {\r
303 return EFI_ABORTED;\r
304 }\r
305 UncompressedBuffer = malloc (UncompressedLength);\r
306 if (UncompressedBuffer == NULL) {\r
307 free (ScratchBuffer);\r
308 return EFI_ABORTED;\r
309 }\r
310 memset (UncompressedBuffer, 0, UncompressedLength);\r
311\r
312 Status = DecompressFunction (\r
313 CompressedBuffer,\r
314 CompressedLength,\r
315 UncompressedBuffer,\r
316 UncompressedLength,\r
317 ScratchBuffer,\r
318 ScratchSize\r
319 );\r
320 free (ScratchBuffer);\r
321 if (Status != EFI_SUCCESS) {\r
322 Error (NULL, 0, 0003, "decompress failed", NULL);\r
323 free (UncompressedBuffer);\r
324 return EFI_ABORTED;\r
325 }\r
326 } else {\r
327 Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);\r
328 return EFI_ABORTED;\r
329 }\r
330\r
331 Status = ParseSection (FALSE, UncompressedBuffer, UncompressedLength, EfiBufferHeader);\r
332 if (Status != EFI_SUCCESS) {\r
333 Error (NULL, 0, 0003, "failed to parse section", NULL);\r
334 free (UncompressedBuffer);\r
335 UncompressedBuffer = NULL;\r
336 } else {\r
337 return EFI_SUCCESS;\r
338 }\r
339 //\r
340 // Store the allocate memory address for UncompressedBuffer\r
341 //\r
342 if (UncompressedBuffer != NULL) {\r
343 (*EfiBufferHeader)->UncompressedBuffer[(*EfiBufferHeader)->UnCompressIndex] = (UINTN) UncompressedBuffer;\r
344 (*EfiBufferHeader)->UnCompressIndex = (*EfiBufferHeader)->UnCompressIndex + 1;\r
345 }\r
346 break;\r
347\r
348 case EFI_SECTION_GUID_DEFINED:\r
349 //\r
350 // Decompress failed, and then check for CRC32 sections which we can handle internally if needed.\r
351 // Maybe this section is no-compressed.\r
352 //\r
353 if (!CompareGuid (\r
354 &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid,\r
355 &gEfiCrc32GuidedSectionExtractionProtocolGuid\r
356 )) {\r
357 //\r
358 // CRC32 guided section\r
359 //\r
360 Status = ParseSection (\r
361 FALSE,\r
362 SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,\r
363 BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,\r
364 EfiBufferHeader\r
365 );\r
366 if (EFI_ERROR (Status)) {\r
367 Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);\r
368 return EFI_ABORTED;\r
369 } else {\r
370 return EFI_SUCCESS;\r
371 }\r
372 } else {\r
373 ExtractionTool = LookupGuidedSectionToolPath (\r
374 mParsedGuidedSectionTools,\r
375 &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid\r
376 );\r
377\r
378 if (ExtractionTool != NULL) {\r
379 ToolInputFile = GenTempFile ();\r
380 ToolOutputFile = GenTempFile ();\r
381 //\r
382 // Construction 'system' command string\r
383 //\r
384 SystemCommandFormatString = "%s -d -o \"%s\" \"%s\"";\r
385 SystemCommand = malloc (\r
386 strlen (SystemCommandFormatString) \\r
387 + strlen (ExtractionTool) \\r
388 + strlen (ToolInputFile) \\r
389 + strlen (ToolOutputFile) \\r
390 + 1\r
391 );\r
392 if (SystemCommand == NULL) {\r
393 free (ExtractionTool);\r
394 free (ToolInputFile);\r
395 free (ToolOutputFile);\r
396 return EFI_ABORTED;\r
397 }\r
398 sprintf (\r
399 SystemCommand,\r
400 "%s -d -o \"%s\" \"%s\"",\r
401 ExtractionTool,\r
402 ToolOutputFile,\r
403 ToolInputFile\r
404 );\r
405 free (ExtractionTool);\r
406\r
407 Status = PutFileImage (\r
408 ToolInputFile,\r
409 (CHAR8*) Ptr + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,\r
410 SectionLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset\r
411 );\r
412\r
413 if (HasDepexSection) {\r
414 HasDepexSection = FALSE;\r
415 }\r
416\r
417 system (SystemCommand);\r
418 remove (ToolInputFile);\r
419 free (ToolInputFile);\r
420 ToolInputFile = NULL;\r
421 free (SystemCommand);\r
422 SystemCommand = NULL;\r
423\r
424 if (EFI_ERROR (Status)) {\r
425 Error ("FCE", 0, 0004, "unable to decoded GUIDED section", NULL);\r
426 free (ToolOutputFile);\r
427 return EFI_ABORTED;\r
428 }\r
429\r
430 Status = GetFileImage (\r
431 ToolOutputFile,\r
432 (CHAR8 **)&ToolOutputBuffer,\r
433 &ToolOutputLength\r
434 );\r
435 remove (ToolOutputFile);\r
436 free (ToolOutputFile);\r
437 ToolOutputFile = NULL;\r
438 if (EFI_ERROR (Status)) {\r
439 return EFI_ABORTED;\r
440 }\r
441 }\r
442 Status = ParseSection (\r
443 FALSE,\r
444 ToolOutputBuffer,\r
445 ToolOutputLength,\r
446 EfiBufferHeader\r
447 );\r
448 if (EFI_ERROR (Status)) {\r
449 Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
450 return EFI_ABORTED;\r
451 }\r
452 }\r
453 break;\r
454\r
455 default:\r
456 ;\r
457 }\r
458 ParsedLength += SectionLength;\r
459 //\r
460 // We make then next section begin on a 4-byte boundary\r
461 //\r
462 ParsedLength = GetOccupiedSize (ParsedLength, 4);\r
463 }\r
464\r
465 return EFI_ABORTED;\r
466}\r
467\r
468static\r
469BOOLEAN\r
470GetNextOffset (\r
471 IN UINT8 *Data,\r
472 IN EFI_GUID *Guid,\r
473 IN UINTN Len,\r
474 IN OUT UINTN *Offset\r
475 )\r
476{\r
477 UINTN NextOffset;\r
478 if (*Offset >= Len || Len - *Offset <= sizeof (EFI_GUID)) {\r
479 return FALSE;\r
480 }\r
481\r
482 for (NextOffset = *Offset; NextOffset < Len - sizeof (EFI_GUID); NextOffset++) {\r
483 if (CompareGuid(Guid, (EFI_GUID*)(Data + NextOffset)) == 0) {\r
484 *Offset = NextOffset + sizeof(EFI_GUID);\r
485 return TRUE;\r
486 }\r
487 }\r
488 return FALSE;\r
489}\r
490\r
491/**\r
492 Get the address by Guid.\r
493\r
494 Parse the FFS image, and find the GUID address.There may be some Guids matching the\r
495 searched Guid.\r
496\r
497 @param Fv the Pointer to the image.\r
498 @param Guid The Guid need to find.\r
499 @param Offset The dual Pointer to the offset.\r
500 @param NumOfMatchGuid The number of matching Guid offset.\r
501\r
502 @retval EFI_SUCCESS The Search was complete successfully\r
503 @return EFI_ABORTED An error occurred\r
504**/\r
505EFI_STATUS\r
506GetAddressByGuid (\r
507 IN VOID *Fv,\r
508 IN EFI_GUID *Guid,\r
509 IN UINTN Len,\r
510 OUT UINTN **Offset,\r
511 OUT UINT8 *NumOfMatchGuid\r
512 )\r
513{\r
514 VOID *LocalFv;\r
515 UINT8 Flag;\r
516\r
517 EFI_RAW_SECTION* Section;\r
518 UINT8 *RawData;\r
519 VOID* SectionStart;\r
520 UINTN NextOffset;\r
521 UINTN Key;\r
522 UINTN TotalSectionsSize;\r
523 UINTN SecLen;\r
524 UINTN SecHdr;\r
525 EFI_STATUS Status;\r
526\r
527 if( (Fv == NULL) || (Fv == NULL) || (Guid == NULL) || Len == 0 ){\r
528 return EFI_ABORTED;\r
529 }\r
530\r
531 LocalFv = Fv;\r
532 Flag = 0;\r
533 Section = NULL;\r
534 Key = 0;\r
535\r
536 if (NumOfMatchGuid != NULL) {\r
537 *NumOfMatchGuid = 0;\r
538 }\r
539\r
540 SectionStart = (VOID*)((UINTN)LocalFv + FvBufGetFfsHeaderSize(LocalFv));\r
541 TotalSectionsSize = Len - FvBufGetFfsHeaderSize(LocalFv);\r
542 while (TRUE) {\r
543 Status = FvBufFindNextSection (\r
544 SectionStart,\r
545 TotalSectionsSize,\r
546 &Key,\r
547 (VOID **)&Section\r
548 );\r
549 if (Section == NULL || EFI_ERROR (Status)) {\r
550 break;\r
551 }\r
552\r
553 if (EFI_SECTION_RAW == Section->Type) {\r
554 if ((*(UINT32 *)Section->Size & 0xffffff) == 0xffffff) {\r
555 SecLen = ((EFI_RAW_SECTION2 *)Section)->ExtendedSize;\r
556 SecHdr = sizeof(EFI_RAW_SECTION2);\r
557 } else {\r
558 SecLen = *(UINT32 *)Section->Size & 0xffffff;\r
559 SecHdr = sizeof(EFI_RAW_SECTION);\r
560 }\r
561 if (SecLen <= SecHdr || SecLen - SecHdr < sizeof(EFI_GUID)) {\r
562 continue;\r
563 }\r
564 RawData = (UINT8 *)Section + SecHdr;\r
565 NextOffset = 0;\r
566 while (GetNextOffset(RawData, Guid, SecLen - SecHdr, &NextOffset)) {\r
567 Flag = 1;\r
568 if ((NumOfMatchGuid != NULL) && (Offset != NULL)) {\r
569 if (*NumOfMatchGuid == 0) {\r
570 *Offset = malloc (sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
571 if (*Offset == NULL) {\r
572 return EFI_ABORTED;\r
573 }\r
574 memset (*Offset, 0, sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
575 }\r
576 *(*Offset + *NumOfMatchGuid) = NextOffset + (RawData - (UINT8 *)Fv);\r
577 (*NumOfMatchGuid)++;\r
578 } else {\r
579 return EFI_SUCCESS;\r
580 }\r
581 }\r
582 }\r
583 }\r
584\r
585 if( Flag == 0 ) {\r
586 return EFI_ABORTED;\r
587 }\r
588 return EFI_SUCCESS;\r
589}\r
590\r
591/**\r
592 Search the VfrBin Base address.\r
593\r
594 According the known GUID gVfrArrayAttractGuid to get the base address from FFS.\r
595\r
596 @param Fv the Pointer to the FFS\r
597 @param EfiAddr the Pointer to the EFI in FFS\r
598 @param Length the length of Fv\r
599 @param Offset the Pointer to the Addr (Offset)\r
600 @param NumOfMachingOffset the number of Addr (Offset)\r
601\r
602 @retval EFI_SUCCESS Get the address successfully.\r
603**/\r
604EFI_STATUS\r
605SearchVfrBinInFFS (\r
606 IN VOID *Fv,\r
607 IN VOID *EfiAddr,\r
608 IN UINTN Length,\r
609 OUT UINTN **Offset,\r
610 OUT UINT8 *NumOfMachingOffset\r
611 )\r
612{\r
613 UINTN Index;\r
614 EFI_STATUS Status;\r
615 UINTN VirOffValue;\r
616\r
617 Index = 0;\r
618 Status = EFI_SUCCESS;\r
619 VirOffValue = 0;\r
620\r
621 if ((Fv == NULL) || (Offset == NULL)) {\r
622 return EFI_ABORTED;\r
623 }\r
624 Status = GetAddressByGuid (\r
625 Fv,\r
626 &gVfrArrayAttractGuid,\r
627 Length,\r
628 Offset,\r
629 NumOfMachingOffset\r
630 );\r
631 if (Status != EFI_SUCCESS) {\r
632 return EFI_ABORTED;\r
633 }\r
634\r
635 while (Index < *NumOfMachingOffset) {\r
636 //\r
637 // Got the virOffset after the GUID\r
638 //\r
639 VirOffValue = *(UINTN *)((UINTN)Fv + *(*Offset + Index));\r
640 //\r
641 //Transfer the offset to the VA address. One modules may own more VfrBin address.\r
642 //\r
643 *(*Offset + Index) = (UINTN) EfiAddr + VirOffValue;\r
644 Index++;\r
645 }\r
646 return EFI_SUCCESS;\r
647}\r
648\r
649/**\r
650 Search the UniBin Base address.\r
651\r
652 According the known GUID gUniStrArrayAttractGuid to get the base address from FFS.\r
653\r
654 @param Fv the Pointer to the FFS\r
655 @param EfiAddr the Pointer to the EFI in FFS\r
656 @param Length the length of Fv\r
657 @param Offset the Pointer to the Addr (Offset)\r
658\r
659 @retval Base address Get the address successfully.\r
660**/\r
661EFI_STATUS\r
662SearchUniBinInFFS (\r
663 IN VOID *Fv,\r
664 IN VOID *EfiAddr,\r
665 IN UINTN Length,\r
666 OUT UINTN **Offset\r
667 )\r
668{\r
669 UINT8 NumOfMachingOffset;\r
670 EFI_STATUS Status;\r
671 UINTN VirOffValue;\r
672\r
673 NumOfMachingOffset = 0;\r
674 Status = EFI_SUCCESS;\r
675 VirOffValue = 0;\r
676\r
677 if ((Fv == NULL) || (Offset == NULL)) {\r
678 return EFI_ABORTED;\r
679 }\r
680 Status = GetAddressByGuid (\r
681 Fv,\r
682 &gUniStrArrayAttractGuid,\r
683 Length,\r
684 Offset,\r
685 &NumOfMachingOffset\r
686 );\r
687 if (Status != EFI_SUCCESS) {\r
688 return EFI_ABORTED;\r
689 }\r
690 //\r
691 //Transfer the offset to the VA address. There is only one UniArray in one modules.\r
692 //\r
693 if (NumOfMachingOffset == 1) {\r
694 VirOffValue = *(UINTN *)((UINTN)Fv + **Offset);\r
695 **Offset = (UINTN) EfiAddr + VirOffValue;\r
696 } else {\r
697 printf ("Error. Find more than 1 UniBin in FFS.\n");\r
698 return EFI_ABORTED;\r
699 }\r
700\r
701 return EFI_SUCCESS;\r
702}\r
703\r
704EFI_STATUS\r
705SearchNvStoreDatabaseInFd(\r
706 IN VOID *Fv,\r
707 IN UINTN length\r
708 )\r
709{\r
710 EFI_STATUS Status;\r
711 UINTN Offset;\r
712 PCD_NV_STORE_DEFAULT_BUFFER_HEADER *NvStoreHeader;\r
713 Status = EFI_SUCCESS;\r
714 Offset = 0;\r
715 if (Fv == NULL) {\r
716 printf ("The FV is NULL.");\r
717 return EFI_ABORTED;\r
718 }\r
719 while (Offset < (length - sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER))){\r
720 NvStoreHeader = (PCD_NV_STORE_DEFAULT_BUFFER_HEADER *)((UINT8*)Fv + Offset);\r
721 if (NvStoreHeader->Signature == PCD_NV_STORE_DEFAULT_BUFFER_SIGNATURE) {\r
722 gEfiFdInfo.ExistNvStoreDatabase = TRUE;\r
723 gEfiFdInfo.NvStoreDatabase = (UINT8 *) NvStoreHeader;\r
724 break;\r
725 }\r
726 Offset++;\r
727 }\r
728 if (Offset == (length - sizeof(PCD_NV_STORE_DEFAULT_BUFFER_HEADER)) || gEfiFdInfo.ExistNvStoreDatabase != TRUE) {\r
729 //printf ("Not found the PcdNvStoreDefaultValueBuffer\n");\r
730 return Status;\r
731 }\r
732 return Status;\r
733}\r
734\r
735/**\r
736 Get the address by Guid.\r
737\r
738 Parse the FD image, and find the GUID address.There may be some Guids matching the\r
739 searched Guid.\r
740\r
741 @param Fv the Pointer to the image.\r
742 @param Guid The Guid need to find.\r
743 @param Offset The dual Pointer to the offset.\r
744 @param NumOfMatchGuid The number of matching Guid offset.\r
745\r
746 @retval EFI_SUCCESS The Search was complete successfully\r
747 @return EFI_ABORTED An error occurred\r
748**/\r
749EFI_STATUS\r
750GetVariableAddressByGuid (\r
751 IN VOID *Fv,\r
752 IN EFI_GUID *Guid,\r
753 IN UINTN Len,\r
754 OUT UINTN **Offset,\r
755 OUT UINT8 *NumOfMatchGuid\r
756 )\r
757{\r
758 UINTN NextOffset;\r
759 UINT8 Flag;\r
760\r
761 if( (Fv == NULL) || (Fv == NULL) || (Guid == NULL) ){\r
762 return EFI_ABORTED;\r
763 }\r
764\r
765 Flag = 0;\r
766 NextOffset = 0;\r
767\r
768 if (NumOfMatchGuid != NULL) {\r
769 *NumOfMatchGuid = 0;\r
770 }\r
771 while (GetNextOffset(Fv, Guid, Len, &NextOffset)) {\r
772 Flag = 1;\r
773 if (NumOfMatchGuid != NULL && Offset != NULL) {\r
774 if (*NumOfMatchGuid == 0) {\r
775 *Offset = malloc (sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
776 if (*Offset == NULL) {\r
777 return EFI_ABORTED;\r
778 }\r
779 memset (*Offset, 0, sizeof (UINTN) * MAX_MATCH_GUID_NUM);\r
780 }\r
781 *(*Offset + *NumOfMatchGuid) = NextOffset;\r
782 (*NumOfMatchGuid)++;\r
783 } else {\r
784 return EFI_SUCCESS;\r
785 }\r
786 }\r
787\r
788 if( Flag == 0 ) {\r
789 return EFI_ABORTED;\r
790 }\r
791 return EFI_SUCCESS;\r
792}\r
793\r
794/**\r
795 Search the EFI Variable Base address.\r
796\r
797 According the known GUID gEfiSystemNvDataFvGuid to get the base address from FFS.\r
798\r
799 @param Fv the Pointer to the FFS\r
800 @param Length the length of Fv\r
801 @param Offset the Pointer to the Addr (Offset)\r
802 @param NumOfMachingOffset the number of IFR array in one FFS\r
803\r
804 @retval EFI_SUCCESS Get the address successfully.\r
805 @retval EFI_ABORTED An error occured.\r
806**/\r
807EFI_STATUS\r
808SearchEfiVarInFFS (\r
809 IN VOID *Fv,\r
810 IN UINTN Length,\r
811 OUT UINTN **Offset,\r
812 OUT UINT8 *NumOfMachingOffset\r
813 )\r
814{\r
815 EFI_STATUS Status;\r
816 UINT8 Index;\r
817\r
818 Status = EFI_SUCCESS;\r
819 Index = 0;\r
820\r
821 if ((Fv == NULL) || (Offset == NULL)) {\r
822 printf ("The FV or offset is NULL.");\r
823 return EFI_ABORTED;\r
824 }\r
825 Status = GetVariableAddressByGuid (\r
826 Fv,\r
827 &gEfiSystemNvDataFvGuid,\r
828 Length,\r
829 Offset,\r
830 NumOfMachingOffset\r
831 );\r
832 if (Status != EFI_SUCCESS) {\r
833 return EFI_ABORTED;\r
834 }\r
835 //\r
836 //Transfer the offset to the VA address.\r
837 //\r
838 while (Index < *NumOfMachingOffset) {\r
839 *(*Offset + Index) = (UINTN) Fv + *(*Offset + Index);\r
840 Index++;\r
841 }\r
842 return EFI_SUCCESS;\r
843}\r
844\r
845/**\r
846 Parse the Ffs header to get the size.\r
847\r
848 @param InputFile The pointer to the input file\r
849 @param FvSize The pointer to the file size\r
850\r
851 @return EFI_SUCCESS Get the file size successfully\r
852**/\r
853EFI_STATUS\r
854ReadFfsHeader (\r
855 IN FILE *InputFile,\r
856 OUT UINT32 *FvSize\r
857 )\r
858{\r
859 EFI_FFS_FILE_HEADER FfsHeader;\r
860 EFI_FV_FILETYPE Type;\r
861\r
862 //\r
863 // Check input parameters\r
864 //\r
865 if ((InputFile == NULL) || (FvSize == NULL)) {\r
866 return EFI_ABORTED;\r
867 }\r
868 //\r
869 // Read the header\r
870 //\r
871 fread (\r
872 &FfsHeader,\r
873 sizeof (EFI_FFS_FILE_HEADER),\r
874 1,\r
875 InputFile\r
876 );\r
877 Type = FfsHeader.Type;\r
878\r
879 if (Type == EFI_FV_FILETYPE_DRIVER) {\r
880 *FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;\r
881 } else if (Type == EFI_FV_FILETYPE_APPLICATION) {\r
882 *FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;\r
883 } else if (Type == EFI_FV_FILETYPE_FREEFORM) {\r
884 *FvSize = *(UINT32 *)FfsHeader.Size & 0xffffff;\r
885 } else {\r
886 return EFI_ABORTED;\r
887 }\r
888 return EFI_SUCCESS;\r
889}\r
890\r
891/*\r
892 Read the length of the whole FD\r
893\r
894 This function determines the size of the FV.\r
895\r
896 @param InputFile The file that contains the FV image.\r
897 @param FvSize The size of the FV.\r
898\r
899 @retval EFI_SUCCESS The application exited normally.\r
900 @retval EFI_ABORTED An error occurred.\r
901\r
902**/\r
903static\r
904EFI_STATUS\r
905ReadFdHeader (\r
906 IN FILE *InputFile,\r
907 OUT UINT32 *FvSize\r
908 )\r
909{\r
910 //\r
911 // Check input parameters\r
912 //\r
913 if ((InputFile == NULL) || (FvSize == NULL)) {\r
914 return EFI_ABORTED;\r
915 }\r
916 *FvSize = 0;\r
917 //\r
918 // Get the total size of FD file (Fixed the length)\r
919 //\r
920 fseek(InputFile,0,SEEK_END);\r
921 *FvSize = ftell(InputFile);\r
922 fseek(InputFile,0,SEEK_SET);\r
923\r
924 if (*FvSize == 0) {\r
925 return EFI_ABORTED;\r
926 }\r
927 return EFI_SUCCESS;\r
928}\r
929\r
930/**\r
931 Read the file to memory.\r
932\r
933 @param InputFile The file that contains the FV image.\r
934 @param Size The size of the file.\r
935\r
936 @retval The pointer to the begining position of memory.\r
937**/\r
938VOID *\r
939ReadFileToMemory (\r
940 IN CHAR8 *FileName,\r
941 OUT UINT32 *Size\r
942 )\r
943{\r
944 FILE *InFile;\r
945 VOID *Address;\r
946 UINT32 BytesRead;\r
947 EFI_STATUS Status;\r
948\r
949 InFile = NULL;\r
950 Address = NULL;\r
951 BytesRead = 0;\r
952 Status = EFI_SUCCESS;\r
953\r
954 InFile = fopen (FileName,"rb");\r
955 if (InFile == NULL) {\r
956 return NULL;\r
957 }\r
958 //\r
959 // Determine the size of FV\r
960 //\r
961 Status = ReadFdHeader (InFile, Size);\r
962 if (Status != EFI_SUCCESS) {\r
963 fclose (InFile);\r
964 return NULL;\r
965 }\r
966 //\r
967 // Allocate a buffer for the FV image\r
968 //\r
969 Address = malloc (*Size);\r
970 if (Address == NULL) {\r
971 fclose (InFile);\r
972 return NULL;\r
973 }\r
974 memset (Address, 0, *Size);\r
975 //\r
976 // Seek to the start of the image, then read the entire FV to the buffer\r
977 //\r
978 fseek (InFile, 0, SEEK_SET);\r
979 BytesRead = fread (Address, 1, *Size, InFile);\r
980 fclose (InFile);\r
981 if ((UINTN) BytesRead != *Size) {\r
982 free (Address);\r
983 return NULL;\r
984 }\r
985 return Address;\r
986}\r
987\r
988/**\r
989 Search the EFI variables address in Fd.\r
990\r
991 Open and read the *.fd to the memory, initialize the global structure.\r
992 Update the EFI variables addr and the begining position of memory.\r
993\r
994 @retval EFI_SUCCESS Get the address successfully.\r
995**/\r
996EFI_STATUS\r
997GetEfiVariablesAddr (\r
998 BOOLEAN UqiIsSet\r
999 )\r
1000{\r
1001 VOID *FdImage;\r
1002 UINT32 FdSize;\r
1003 EFI_STATUS Status;\r
1004 UINTN *EfiVarAddr;\r
1005 UINT8 NumOfMachingVar;\r
1006 UINT32 Index;\r
1007 BOOLEAN GotFlag;\r
1008 EFI_FIRMWARE_VOLUME_HEADER *Variable;\r
1009 BOOLEAN AuthencitatedMonotonicOrNot;\r
1010 BOOLEAN AuthencitatedBasedTimeOrNot;\r
1011 BOOLEAN NormalOrNot;\r
1012\r
1013 FdImage = NULL;\r
1014 FdSize = 0;\r
1015 Status = EFI_SUCCESS;\r
1016 EfiVarAddr = NULL;\r
1017 NumOfMachingVar = 0;\r
1018 Index = 0;\r
1019 GotFlag = TRUE;\r
1020 Variable = NULL;\r
1021\r
1022 FdImage = ReadFileToMemory (mInputFdName, &FdSize);\r
1023 if (FdImage == NULL) {\r
1024 return EFI_ABORTED;\r
1025 }\r
1026 if (!UqiIsSet) {\r
1027 Status = SearchNvStoreDatabaseInFd(FdImage, FdSize);\r
1028 if (EFI_ERROR (Status)) {\r
1029 return EFI_ABORTED;\r
1030 }\r
1031 }\r
1032 Status = SearchEfiVarInFFS (\r
1033 FdImage,\r
1034 FdSize,\r
1035 &EfiVarAddr,\r
1036 &NumOfMachingVar\r
1037 );\r
1038 if (EFI_ERROR (Status)) {\r
1039 return EFI_ABORTED;\r
1040 }\r
1041 //\r
1042 // Check the signature "_FVH"\r
1043 //\r
1044 Index = 0;\r
1045 GotFlag = FALSE;\r
1046\r
1047 while (Index < NumOfMachingVar) {\r
1048 Variable = (EFI_FIRMWARE_VOLUME_HEADER *)(*(EfiVarAddr + Index) - 0x20);\r
1049 if (Variable->Signature == 0x4856465F) {\r
1050 AuthencitatedMonotonicOrNot = CheckMonotonicBasedVarStore ((UINT8 *)Variable + Variable->HeaderLength);\r
1051 AuthencitatedBasedTimeOrNot = CheckTimeBasedVarStoreOrNot ((UINT8 *)Variable + Variable->HeaderLength);\r
1052 NormalOrNot = CheckNormalVarStoreOrNot ((UINT8 *)Variable + Variable->HeaderLength);\r
1053 if (AuthencitatedMonotonicOrNot || AuthencitatedBasedTimeOrNot || NormalOrNot) {\r
1054 GotFlag = TRUE;\r
1055 gEfiFdInfo.EfiVariableAddr = (UINTN)Variable;\r
1056 break;\r
1057 }\r
1058 }\r
1059 Index++;\r
1060 }\r
1061 free (EfiVarAddr);\r
1062 if (!GotFlag) {\r
1063 return EFI_ABORTED;\r
1064 }\r
1065 gEfiFdInfo.Fd = FdImage;\r
1066 gEfiFdInfo.FdSize = FdSize;\r
1067\r
1068 return EFI_SUCCESS;\r
1069}\r
1070\r
1071/**\r
1072 Pick up the FFS which includes IFR section.\r
1073\r
1074 Parse all FFS extracted by BfmLib, and save all which includes IFR\r
1075 Binary to gEfiFdInfo structure.\r
1076\r
1077 @retval EFI_SUCCESS Get the address successfully.\r
1078 @retval EFI_BUFFER_TOO_SMALL Memory can't be allocated.\r
1079 @retval EFI_ABORTED Read FFS Failed.\r
1080**/\r
1081EFI_STATUS\r
1082FindFileInFolder (\r
1083 IN CHAR8 *FolderName,\r
1084 OUT BOOLEAN *ExistStorageInBfv,\r
1085 OUT BOOLEAN *SizeOptimized\r
1086)\r
1087{\r
1088 CHAR8 *FileName;\r
1089 CHAR8 *CurFolderName;\r
1090 EFI_STATUS Status;\r
1091 UINTN MaxFileNameLen;\r
1092 UINTN Index;\r
1093 CHAR8 FileNameArry[MAX_FILENAME_LEN];\r
1094 FILE *FfsFile;\r
1095 UINTN FileSize;\r
1096 VOID *FfsImage;\r
1097 UINTN BytesRead;\r
1098#ifndef __GNUC__\r
1099 HANDLE FindHandle;\r
1100 WIN32_FIND_DATA FindFileData;\r
1101#else\r
1102 struct dirent *pDirent;\r
1103 DIR *pDir;\r
1104#endif\r
1105\r
1106 FileName = NULL;\r
1107 CurFolderName = NULL;\r
1108 Status = EFI_SUCCESS;\r
1109 MaxFileNameLen = 0;\r
1110 Index = 0;\r
1111 FileSize = 0;\r
1112 BytesRead = 0;\r
1113 FfsImage = NULL;\r
1114 FfsFile = NULL;\r
1115\r
1116 MaxFileNameLen = strlen (FolderName) + MAX_FILENAME_LEN;\r
1117 CurFolderName = (CHAR8 *)calloc(\r
1118 strlen (FolderName) + strlen (OS_SEP_STR) + strlen ("*.*")+ 1,\r
1119 sizeof(CHAR8)\r
1120 );\r
1121 if (CurFolderName == NULL) {\r
1122 return EFI_BUFFER_TOO_SMALL;\r
1123 }\r
1124 strcpy (CurFolderName, FolderName);\r
1125 strcat (CurFolderName, OS_SEP_STR);\r
1126 strcat (CurFolderName, "*.*");\r
1127 FileName = (CHAR8 *)calloc(\r
1128 MaxFileNameLen,\r
1129 sizeof(CHAR8)\r
1130 );\r
1131 if (FileName == NULL) {\r
1132 free (CurFolderName);\r
1133 return EFI_BUFFER_TOO_SMALL;\r
1134 }\r
1135\r
1136#ifndef __GNUC__\r
1137 if((FindHandle = FindFirstFile(CurFolderName, &FindFileData)) != INVALID_HANDLE_VALUE){\r
1138 do {\r
1139 memset (FileName, 0, MaxFileNameLen);\r
1140 if ((strcmp (FindFileData.cFileName, ".") == 0)\r
1141 || (strcmp (FindFileData.cFileName, "..") == 0)\r
1142 ) {\r
1143 continue;\r
1144 }\r
1145 if (strlen(FolderName) + strlen ("\\") + strlen (FindFileData.cFileName) > MAX_FILENAME_LEN - 1) {\r
1146 Status = EFI_ABORTED;\r
1147 goto Done;\r
1148 }\r
1149 snprintf (FileNameArry, MAX_FILENAME_LEN, "%s%c%s", FolderName, OS_SEP, FindFileData.cFileName);\r
1150 FfsFile = fopen (FileNameArry, "rb");\r
1151 if (FfsFile == NULL) {\r
1152 Status = EFI_ABORTED;\r
1153 goto Done;\r
1154 }\r
1155 Status = ReadFfsHeader (FfsFile, (UINT32 *)&FileSize);\r
1156 if (EFI_ERROR (Status)) {\r
1157 fclose (FfsFile);\r
1158 Status = EFI_SUCCESS;\r
1159 continue;\r
1160 }\r
1161 //\r
1162 // Allocate a buffer for the FFS file\r
1163 //\r
1164 FfsImage = malloc (FileSize);\r
1165 if (FfsImage == NULL) {\r
1166 fclose (FfsFile);\r
1167 Status = EFI_BUFFER_TOO_SMALL;\r
1168 goto Done;\r
1169 }\r
1170 //\r
1171 // Seek to the start of the image, then read the entire FV to the buffer\r
1172 //\r
1173 fseek (FfsFile, 0, SEEK_SET);\r
1174 BytesRead = fread (FfsImage, 1, FileSize, FfsFile);\r
1175 fclose (FfsFile);\r
1176\r
1177 if ((UINTN) BytesRead != FileSize) {\r
1178 free (FfsImage);\r
1179 Status = EFI_ABORTED;\r
1180 goto Done;\r
1181 }\r
1182 //\r
1183 // Check whether exists the storage ffs in BFV for multi-platform mode\r
1184 //\r
1185 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid,(EFI_GUID *) FfsImage) == 0) {\r
1186 *ExistStorageInBfv = TRUE;\r
1187 *SizeOptimized = FALSE;\r
1188 gEfiFdInfo.StorageFfsInBfv = FfsImage;\r
1189 continue;\r
1190 }\r
1191 //\r
1192 // Check whether exists the optimized storage ffs in BFV for multi-platform mode\r
1193 //\r
1194 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2,(EFI_GUID *) FfsImage) == 0) {\r
1195 *ExistStorageInBfv = TRUE;\r
1196 *SizeOptimized = TRUE;\r
1197 gEfiFdInfo.StorageFfsInBfv = FfsImage;\r
1198 continue;\r
1199 }\r
1200 //\r
1201 // Check whether current FFS includes IFR\r
1202 //\r
1203 Status = GetAddressByGuid (\r
1204 FfsImage,\r
1205 &gVfrArrayAttractGuid,\r
1206 FileSize,\r
1207 NULL,\r
1208 NULL\r
1209 );\r
1210 if (EFI_ERROR (Status)) {\r
1211 free (FfsImage);\r
1212 Status = EFI_SUCCESS;\r
1213 } else {\r
1214 //\r
1215 // Check whether existed same IFR binary. If existed, not insert the new one.\r
1216 //\r
1217 if (NotExistSameFfsIfr (FfsImage)) {\r
1218 gEfiFdInfo.FfsArray[Index] = FfsImage;\r
1219 gEfiFdInfo.Length[Index++] = FileSize;\r
1220 }\r
1221 }\r
1222\r
1223 } while (FindNextFile (FindHandle, &FindFileData));\r
1224 FindClose(FindHandle);\r
1225 } else {\r
1226 Status = EFI_ABORTED;\r
1227 goto Done;\r
1228 }\r
1229\r
1230Done:\r
1231 free (CurFolderName);\r
1232 free (FileName);\r
1233\r
1234#else\r
1235 if((pDir = opendir(FolderName)) != NULL){\r
1236 while ((pDirent = readdir(pDir)) != NULL){\r
1237 memset (FileName, 0, MaxFileNameLen);\r
1238 if ((strcmp (pDirent->d_name, ".") == 0)\r
1239 || (strcmp (pDirent->d_name, "..") == 0)\r
1240 ) {\r
1241 continue;\r
1242 }\r
1243 sprintf (FileNameArry, "%s%c%s", FolderName, OS_SEP, pDirent->d_name);\r
1244 FfsFile = fopen (FileNameArry, "rb");\r
1245 Status = ReadFfsHeader (FfsFile, (UINT32 *)&FileSize);\r
1246 if (EFI_ERROR (Status)) {\r
1247 fclose (FfsFile);\r
1248 Status = EFI_SUCCESS;\r
1249 continue;\r
1250 }\r
1251 //\r
1252 // Allocate a buffer for the FFS file\r
1253 //\r
1254 FfsImage = malloc (FileSize);\r
1255 if (FfsImage == NULL) {\r
1256 fclose (FfsFile);\r
1257 Status = EFI_BUFFER_TOO_SMALL;\r
1258 goto Done;\r
1259 }\r
1260 //\r
1261 // Seek to the start of the image, then read the entire FV to the buffer\r
1262 //\r
1263 fseek (FfsFile, 0, SEEK_SET);\r
1264 BytesRead = fread (FfsImage, 1, FileSize, FfsFile);\r
1265 fclose (FfsFile);\r
1266\r
1267 if ((UINTN) BytesRead != FileSize) {\r
1268 free (FfsImage);\r
1269 Status = EFI_ABORTED;\r
1270 goto Done;\r
1271 }\r
1272 //\r
1273 // Check whether exists the storage ffs in BFV for multi-platform mode\r
1274 //\r
1275 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid,(EFI_GUID *) FfsImage) == 0) {\r
1276 *ExistStorageInBfv = TRUE;\r
1277 *SizeOptimized = FALSE;\r
1278 gEfiFdInfo.StorageFfsInBfv = FfsImage;\r
1279 continue;\r
1280 }\r
1281 //\r
1282 // Check whether exists the optimized storage ffs in BFV for multi-platform mode\r
1283 //\r
1284 if (CompareGuid(&gEfiFfsBfvForMultiPlatformGuid2,(EFI_GUID *) FfsImage) == 0) {\r
1285 *ExistStorageInBfv = TRUE;\r
1286 *SizeOptimized = TRUE;\r
1287 gEfiFdInfo.StorageFfsInBfv = FfsImage;\r
1288 continue;\r
1289 }\r
1290 //\r
1291 // Check whether current FFS includes IFR\r
1292 //\r
1293 Status = GetAddressByGuid (\r
1294 FfsImage,\r
1295 &gVfrArrayAttractGuid,\r
1296 FileSize,\r
1297 NULL,\r
1298 NULL\r
1299 );\r
1300 if (EFI_ERROR (Status)) {\r
1301 free (FfsImage);\r
1302 Status = EFI_SUCCESS;\r
1303 } else {\r
1304 //\r
1305 // Check whether existed same IFR binary. If existed, not insert the new one.\r
1306 //\r
1307 if (NotExistSameFfsIfr (FfsImage)) {\r
1308 gEfiFdInfo.FfsArray[Index] = FfsImage;\r
1309 gEfiFdInfo.Length[Index++] = FileSize;\r
1310 }\r
1311 }\r
1312\r
1313 }\r
1314 closedir(pDir);\r
1315 } else {\r
1316 Status = EFI_ABORTED;\r
1317 goto Done;\r
1318 }\r
1319\r
1320Done:\r
1321 free (CurFolderName);\r
1322 free (FileName);\r
1323#endif\r
1324 return Status;\r
1325}\r
1326\r