]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools/VolInfo: Add definitions for command format strings
[mirror_edk2.git] / BaseTools / Source / C / VolInfo / VolInfo.c
CommitLineData
f51461c8 1/** @file\r
97fa0ee9 2The tool dumps the contents of a firmware volume\r
f51461c8 3\r
45258285 4Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
f51461c8
LG
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
f51461c8
LG
13**/\r
14\r
15#include <stdio.h>\r
16#include <stdlib.h>\r
17#include <string.h>\r
18#include <ctype.h>\r
19#include <assert.h>\r
868c9c35
YZ
20#ifdef __GNUC__\r
21#include <unistd.h>\r
9947f576
YZ
22#else\r
23#include <direct.h>\r
868c9c35 24#endif\r
f51461c8
LG
25\r
26#include <FvLib.h>\r
27#include <Common/UefiBaseTypes.h>\r
28#include <Common/UefiCapsule.h>\r
29#include <Common/PiFirmwareFile.h>\r
30#include <Common/PiFirmwareVolume.h>\r
31#include <Guid/PiFirmwareFileSystem.h>\r
32#include <IndustryStandard/PeImage.h>\r
33#include <Protocol/GuidedSectionExtraction.h>\r
34\r
35#include "Compress.h"\r
36#include "Decompress.h"\r
37#include "VolInfo.h"\r
38#include "CommonLib.h"\r
39#include "EfiUtilityMsgs.h"\r
40#include "FirmwareVolumeBufferLib.h"\r
41#include "OsPath.h"\r
42#include "ParseGuidedSectionTools.h"\r
43#include "StringFuncs.h"\r
730ffca1 44#include "ParseInf.h"\r
9947f576 45#include "PeCoffLib.h"\r
f51461c8
LG
46\r
47//\r
48// Utility global variables\r
49//\r
50\r
51EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;\r
52\r
45258285
LG
53#define UTILITY_MAJOR_VERSION 1\r
54#define UTILITY_MINOR_VERSION 0\r
f51461c8
LG
55\r
56#define UTILITY_NAME "VolInfo"\r
57\r
58#define EFI_SECTION_ERROR EFIERR (100)\r
59\r
60#define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable\r
61\r
62//\r
63// Structure to keep a list of guid-to-basenames\r
64//\r
65typedef struct _GUID_TO_BASENAME {\r
66 struct _GUID_TO_BASENAME *Next;\r
67 INT8 Guid[PRINTED_GUID_BUFFER_SIZE];\r
68 INT8 BaseName[MAX_BASENAME_LEN];\r
69} GUID_TO_BASENAME;\r
70\r
71static GUID_TO_BASENAME *mGuidBaseNameList = NULL;\r
72\r
73//\r
74// Store GUIDed Section guid->tool mapping\r
75//\r
76EFI_HANDLE mParsedGuidedSectionTools = NULL;\r
77\r
78CHAR8* mUtilityFilename = NULL;\r
79\r
9947f576
YZ
80BOOLEAN EnableHash = FALSE;\r
81CHAR8 *OpenSslPath = NULL;\r
82\r
f51461c8
LG
83EFI_STATUS\r
84ParseGuidBaseNameFile (\r
85 CHAR8 *FileName\r
86 );\r
87\r
88EFI_STATUS\r
89FreeGuidBaseNameList (\r
90 VOID\r
91 );\r
92\r
93EFI_STATUS\r
94PrintGuidName (\r
95 IN UINT8 *GuidStr\r
96 );\r
97\r
98EFI_STATUS\r
99ParseSection (\r
100 IN UINT8 *SectionBuffer,\r
101 IN UINT32 BufferLength\r
102 );\r
103\r
104EFI_STATUS\r
105DumpDepexSection (\r
106 IN UINT8 *Ptr,\r
107 IN UINT32 SectionLength\r
108 );\r
109\r
110STATIC\r
111EFI_STATUS\r
112ReadHeader (\r
113 IN FILE *InputFile,\r
114 OUT UINT32 *FvSize,\r
115 OUT BOOLEAN *ErasePolarity\r
116 );\r
117\r
118STATIC\r
119EFI_STATUS\r
120PrintFileInfo (\r
121 EFI_FIRMWARE_VOLUME_HEADER *FvImage,\r
122 EFI_FFS_FILE_HEADER *FileHeader,\r
123 BOOLEAN ErasePolarity\r
124 );\r
125\r
126static\r
127EFI_STATUS\r
128PrintFvInfo (\r
129 IN VOID *Fv,\r
130 IN BOOLEAN IsChildFv\r
131 );\r
132\r
133static\r
134VOID\r
135LoadGuidedSectionToolsTxt (\r
136 IN CHAR8* FirmwareVolumeFilename\r
137 );\r
138\r
9947f576
YZ
139EFI_STATUS\r
140CombinePath (\r
141 IN CHAR8* DefaultPath,\r
142 IN CHAR8* AppendPath,\r
143 OUT CHAR8* NewPath\r
144);\r
145\r
f51461c8
LG
146void\r
147Usage (\r
148 VOID\r
149 );\r
150\r
151int\r
152main (\r
153 int argc,\r
154 char *argv[]\r
155 )\r
156/*++\r
157\r
158Routine Description:\r
159\r
160 GC_TODO: Add function description\r
161\r
162Arguments:\r
163\r
164 argc - GC_TODO: add argument description\r
165 ] - GC_TODO: add argument description\r
166\r
167Returns:\r
168\r
169 GC_TODO: add return values\r
170\r
171--*/\r
172{\r
173 FILE *InputFile;\r
174 int BytesRead;\r
175 EFI_FIRMWARE_VOLUME_HEADER *FvImage;\r
176 UINT32 FvSize;\r
177 EFI_STATUS Status;\r
178 int Offset;\r
179 BOOLEAN ErasePolarity;\r
730ffca1 180 UINT64 LogLevel;\r
9947f576
YZ
181 CHAR8 *OpenSslEnv;\r
182 CHAR8 *OpenSslCommand;\r
f51461c8
LG
183\r
184 SetUtilityName (UTILITY_NAME);\r
185 //\r
186 // Print utility header\r
187 //\r
45258285 188 printf ("%s Version %d.%d Build %s\n",\r
f51461c8
LG
189 UTILITY_NAME,\r
190 UTILITY_MAJOR_VERSION,\r
191 UTILITY_MINOR_VERSION,\r
45258285 192 __BUILD_VERSION\r
f51461c8
LG
193 );\r
194\r
730ffca1
YZ
195 if (argc == 1) {\r
196 Usage ();\r
197 return -1;\r
198 }\r
199\r
f51461c8
LG
200 argc--;\r
201 argv++;\r
730ffca1 202 LogLevel = 0;\r
f51461c8
LG
203 Offset = 0;\r
204\r
730ffca1
YZ
205 //\r
206 // Look for help options\r
207 //\r
208 if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) ||\r
209 (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) {\r
210 Usage();\r
211 return STATUS_SUCCESS;\r
212 }\r
213 //\r
214 // Version has already be printed, so just return success\r
215 //\r
216 if (strcmp(argv[0], "--version") == 0) {\r
217 return STATUS_SUCCESS;\r
218 }\r
219\r
f51461c8
LG
220 //\r
221 // If they specified -x xref guid/basename cross-reference files, process it.\r
222 // This will print the basename beside each file guid. To use it, specify\r
223 // -x xref_filename to processdsc, then use xref_filename as a parameter\r
224 // here.\r
225 //\r
730ffca1 226 while (argc > 0) {\r
f51461c8
LG
227 if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) {\r
228 ParseGuidBaseNameFile (argv[1]);\r
229 printf("ParseGuidBaseNameFile: %s\n", argv[1]);\r
230 argc -= 2;\r
231 argv += 2;\r
730ffca1
YZ
232 continue;\r
233 }\r
234 if (strcmp(argv[0], "--offset") == 0) {\r
f51461c8
LG
235 //\r
236 // Hex or decimal?\r
237 //\r
238 if ((argv[1][0] == '0') && (tolower ((int)argv[1][1]) == 'x')) {\r
239 if (sscanf (argv[1], "%x", &Offset) != 1) {\r
240 Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]);\r
241 return GetUtilityStatus ();\r
242 }\r
243 } else {\r
244 if (sscanf (argv[1], "%d", &Offset) != 1) {\r
245 Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]);\r
246 return GetUtilityStatus ();\r
247 }\r
248 //\r
249 // See if they said something like "64K"\r
250 //\r
251 if (tolower ((int)argv[1][strlen (argv[1]) - 1]) == 'k') {\r
252 Offset *= 1024;\r
253 }\r
254 }\r
255\r
256 argc -= 2;\r
257 argv += 2;\r
730ffca1 258 continue;\r
f51461c8 259 }\r
9947f576 260 if ((stricmp (argv[0], "--hash") == 0)) {\r
85006654
HW
261 if (EnableHash == TRUE) {\r
262 //\r
263 // --hash already given in the option, ignore this one\r
264 //\r
265 argc --;\r
266 argv ++;\r
267 continue;\r
268 }\r
9947f576
YZ
269 EnableHash = TRUE;\r
270 OpenSslCommand = "openssl";\r
271 OpenSslEnv = getenv("OPENSSL_PATH");\r
272 if (OpenSslEnv == NULL) {\r
273 OpenSslPath = OpenSslCommand;\r
274 } else {\r
275 OpenSslPath = malloc(strlen(OpenSslEnv)+strlen(OpenSslCommand)+1);\r
9dd00cb6
HW
276 if (OpenSslPath == NULL) {\r
277 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
278 return GetUtilityStatus ();\r
279 }\r
9947f576
YZ
280 CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath);\r
281 }\r
282 if (OpenSslPath == NULL){\r
283 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);\r
284 return GetUtilityStatus ();\r
285 }\r
286 argc --;\r
287 argv ++;\r
288 continue;\r
289 }\r
730ffca1
YZ
290\r
291 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
292 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
293 argc --;\r
294 argv ++;\r
295 continue;\r
296 }\r
297\r
298 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
299 SetPrintLevel (KEY_LOG_LEVEL);\r
300 argc --;\r
301 argv ++;\r
302 continue;\r
303 }\r
304\r
305 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
306 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
307 if (EFI_ERROR (Status)) {\r
308 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
309 return -1;\r
310 }\r
311 if (LogLevel > 9) {\r
312 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);\r
313 return -1;\r
314 }\r
315 SetPrintLevel (LogLevel);\r
316 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
317 argc -= 2;\r
318 argv += 2;\r
319 continue;\r
320 }\r
321\r
322 mUtilityFilename = argv[0];\r
323 argc --;\r
324 argv ++;\r
f51461c8 325 }\r
730ffca1 326\r
f51461c8
LG
327 //\r
328 // Open the file containing the FV\r
329 //\r
730ffca1
YZ
330 if (mUtilityFilename == NULL) {\r
331 Error (NULL, 0, 1001, "Missing option", "Input files are not specified");\r
332 return GetUtilityStatus ();\r
333 }\r
334 InputFile = fopen (LongFilePath (mUtilityFilename), "rb");\r
f51461c8 335 if (InputFile == NULL) {\r
730ffca1 336 Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename);\r
f51461c8
LG
337 return GetUtilityStatus ();\r
338 }\r
339 //\r
340 // Skip over pad bytes if specified. This is used if they prepend 0xff\r
341 // data to the FV image binary.\r
342 //\r
343 if (Offset != 0) {\r
344 fseek (InputFile, Offset, SEEK_SET);\r
345 }\r
346 //\r
347 // Determine size of FV\r
348 //\r
349 Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);\r
350 if (EFI_ERROR (Status)) {\r
730ffca1 351 Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename);\r
f51461c8
LG
352 fclose (InputFile);\r
353 return GetUtilityStatus ();\r
354 }\r
355 //\r
356 // Allocate a buffer for the FV image\r
357 //\r
358 FvImage = malloc (FvSize);\r
359 if (FvImage == NULL) {\r
360 Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL);\r
361 fclose (InputFile);\r
362 return GetUtilityStatus ();\r
363 }\r
364 //\r
365 // Seek to the start of the image, then read the entire FV to the buffer\r
366 //\r
367 fseek (InputFile, Offset, SEEK_SET);\r
368 BytesRead = fread (FvImage, 1, FvSize, InputFile);\r
369 fclose (InputFile);\r
370 if ((unsigned int) BytesRead != FvSize) {\r
730ffca1 371 Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename);\r
f51461c8
LG
372 free (FvImage);\r
373 return GetUtilityStatus ();\r
374 }\r
375\r
730ffca1 376 LoadGuidedSectionToolsTxt (mUtilityFilename);\r
f51461c8
LG
377\r
378 PrintFvInfo (FvImage, FALSE);\r
379\r
380 //\r
381 // Clean up\r
382 //\r
383 free (FvImage);\r
384 FreeGuidBaseNameList ();\r
385 return GetUtilityStatus ();\r
386}\r
387\r
388\r
389static\r
390EFI_STATUS\r
391PrintFvInfo (\r
392 IN VOID *Fv,\r
393 IN BOOLEAN IsChildFv\r
394 )\r
395/*++\r
396\r
397Routine Description:\r
398\r
399 GC_TODO: Add function description\r
400\r
401Arguments:\r
402\r
403 Fv - Firmware Volume to print information about\r
404 IsChildFv - Flag specifies whether the input FV is a child FV.\r
405\r
406Returns:\r
407\r
408 EFI_STATUS\r
409\r
410--*/\r
411{\r
412 EFI_STATUS Status;\r
413 UINTN NumberOfFiles;\r
414 BOOLEAN ErasePolarity;\r
415 UINTN FvSize;\r
416 EFI_FFS_FILE_HEADER *CurrentFile;\r
417 UINTN Key;\r
418\r
419 Status = FvBufGetSize (Fv, &FvSize);\r
420\r
421 NumberOfFiles = 0;\r
422 ErasePolarity =\r
423 (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ?\r
424 TRUE : FALSE;\r
425\r
426 //\r
427 // Get the first file\r
428 //\r
429 Key = 0;\r
430 Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);\r
431 if (EFI_ERROR (Status)) {\r
432 Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image");\r
433 return GetUtilityStatus ();\r
434 }\r
435 //\r
436 // Display information about files found\r
437 //\r
438 while (CurrentFile != NULL) {\r
439 //\r
440 // Increment the number of files counter\r
441 //\r
442 NumberOfFiles++;\r
443\r
444 //\r
445 // Display info about this file\r
446 //\r
447 Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity);\r
448 if (EFI_ERROR (Status)) {\r
449 Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV");\r
450 return GetUtilityStatus ();\r
451 }\r
452 //\r
453 // Get the next file\r
454 //\r
455 Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile);\r
456 if (Status == EFI_NOT_FOUND) {\r
457 CurrentFile = NULL;\r
458 } else if (EFI_ERROR (Status)) {\r
459 Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image");\r
460 return GetUtilityStatus ();\r
461 }\r
462 }\r
463\r
464 if (IsChildFv) {\r
465 printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles);\r
466 } else {\r
467 printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles);\r
468 }\r
469\r
470 return EFI_SUCCESS;\r
471}\r
472\r
473UINT32\r
474GetOccupiedSize (\r
475 IN UINT32 ActualSize,\r
476 IN UINT32 Alignment\r
477 )\r
478/*++\r
479\r
480Routine Description:\r
481\r
482 This function returns the next larger size that meets the alignment \r
483 requirement specified.\r
484\r
485Arguments:\r
486\r
487 ActualSize The size.\r
488 Alignment The desired alignment.\r
489 \r
490Returns:\r
491 \r
492 EFI_SUCCESS Function completed successfully.\r
493 EFI_ABORTED The function encountered an error.\r
494\r
495--*/\r
496{\r
497 UINT32 OccupiedSize;\r
498\r
499 OccupiedSize = ActualSize;\r
500 while ((OccupiedSize & (Alignment - 1)) != 0) {\r
501 OccupiedSize++;\r
502 }\r
503\r
504 return OccupiedSize;\r
505}\r
506\r
507static\r
508CHAR8 *\r
509SectionNameToStr (\r
510 IN EFI_SECTION_TYPE Type\r
511 )\r
512/*++\r
513\r
514Routine Description:\r
515\r
516 Converts EFI Section names to Strings\r
517\r
518Arguments:\r
519\r
520 Type - The EFI Section type\r
521\r
522Returns:\r
523\r
524 CHAR8* - Pointer to the String containing the section name.\r
525\r
526--*/\r
527{\r
528 CHAR8 *SectionStr;\r
529 CHAR8 *SectionTypeStringTable[] = {\r
530 //\r
531 // 0X00\r
532 //\r
533 "EFI_SECTION_ALL",\r
534 //\r
535 // 0x01\r
536 //\r
537 "EFI_SECTION_COMPRESSION",\r
538 //\r
539 // 0x02\r
540 //\r
541 "EFI_SECTION_GUID_DEFINED", \r
542 //\r
543 // 0x03\r
544 //\r
545 "Unknown section type - Reserved 0x03",\r
546 //\r
547 // 0x04\r
548 //\r
549 "Unknown section type - Reserved 0x04",\r
550 //\r
551 // 0x05\r
552 //\r
553 "Unknown section type - Reserved 0x05",\r
554 //\r
555 // 0x06\r
556 //\r
557 "Unknown section type - Reserved 0x06",\r
558 //\r
559 // 0x07\r
560 //\r
561 "Unknown section type - Reserved 0x07",\r
562 //\r
563 // 0x08\r
564 //\r
565 "Unknown section type - Reserved 0x08",\r
566 //\r
567 // 0x09\r
568 //\r
569 "Unknown section type - Reserved 0x09",\r
570 //\r
571 // 0x0A\r
572 //\r
573 "Unknown section type - Reserved 0x0A",\r
574 //\r
575 // 0x0B\r
576 //\r
577 "Unknown section type - Reserved 0x0B",\r
578 //\r
579 // 0x0C\r
580 //\r
581 "Unknown section type - Reserved 0x0C",\r
582 //\r
583 // 0x0D\r
584 //\r
585 "Unknown section type - Reserved 0x0D",\r
586 //\r
587 // 0x0E\r
588 //\r
589 "Unknown section type - Reserved 0x0E",\r
590 //\r
591 // 0x0F\r
592 //\r
593 "Unknown section type - Reserved 0x0E",\r
594 //\r
595 // 0x10\r
596 //\r
597 "EFI_SECTION_PE32",\r
598 //\r
599 // 0x11\r
600 //\r
601 "EFI_SECTION_PIC",\r
602 //\r
603 // 0x12\r
604 //\r
605 "EFI_SECTION_TE", \r
606 //\r
607 // 0x13\r
608 //\r
609 "EFI_SECTION_DXE_DEPEX", \r
610 //\r
611 // 0x14\r
612 //\r
613 "EFI_SECTION_VERSION",\r
614 //\r
615 // 0x15\r
616 //\r
617 "EFI_SECTION_USER_INTERFACE",\r
618 //\r
619 // 0x16\r
620 //\r
621 "EFI_SECTION_COMPATIBILITY16",\r
622 //\r
623 // 0x17\r
624 //\r
625 "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",\r
626 //\r
627 // 0x18\r
628 //\r
629 "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",\r
630 //\r
631 // 0x19\r
632 //\r
633 "EFI_SECTION_RAW",\r
634 //\r
635 // 0x1A\r
636 //\r
637 "Unknown section type - 0x1A",\r
638 //\r
639 // 0x1B\r
640 //\r
641 "EFI_SECTION_PEI_DEPEX",\r
642 //\r
643 // 0x1C\r
644 //\r
645 "EFI_SECTION_SMM_DEPEX",\r
646 //\r
647 // 0x1C+\r
648 //\r
649 "Unknown section type - Reserved - beyond last defined section"\r
650 };\r
651\r
652 if (Type > EFI_SECTION_LAST_SECTION_TYPE) {\r
653 Type = EFI_SECTION_LAST_SECTION_TYPE + 1;\r
654 }\r
655\r
656 SectionStr = malloc (100);\r
657 if (SectionStr == NULL) {\r
658 printf ("Error: Out of memory resources.\n");\r
659 return SectionStr;\r
660 }\r
661 strcpy (SectionStr, SectionTypeStringTable[Type]);\r
662 return SectionStr;\r
663}\r
664\r
665STATIC\r
666EFI_STATUS\r
667ReadHeader (\r
668 IN FILE *InputFile,\r
669 OUT UINT32 *FvSize,\r
670 OUT BOOLEAN *ErasePolarity\r
671 )\r
672/*++\r
673\r
674Routine Description:\r
675\r
676 This function determines the size of the FV and the erase polarity. The \r
677 erase polarity is the FALSE value for file state.\r
678\r
679Arguments:\r
680\r
681 InputFile The file that contains the FV image.\r
682 FvSize The size of the FV.\r
683 ErasePolarity The FV erase polarity.\r
684 \r
685Returns:\r
686 \r
687 EFI_SUCCESS Function completed successfully.\r
688 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.\r
689 EFI_ABORTED The function encountered an error.\r
690\r
691--*/\r
692{\r
693 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;\r
694 EFI_FV_BLOCK_MAP_ENTRY BlockMap;\r
695 UINTN Signature[2];\r
696 UINTN BytesRead;\r
697 UINT32 Size;\r
698\r
699 BytesRead = 0;\r
700 Size = 0;\r
701 //\r
702 // Check input parameters\r
703 //\r
704 if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) {\r
705 Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function");\r
706 return EFI_INVALID_PARAMETER;\r
707 }\r
708 //\r
709 // Read the header\r
710 //\r
711 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
712 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
713 Signature[0] = VolumeHeader.Signature;\r
714 Signature[1] = 0;\r
715\r
716 //\r
717 // Print FV header information\r
718 //\r
719 printf ("Signature: %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature);\r
720 printf ("Attributes: %X\n", (unsigned) VolumeHeader.Attributes);\r
721\r
722 if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) {\r
723 printf (" EFI_FVB2_READ_DISABLED_CAP\n");\r
724 }\r
725\r
726 if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) {\r
727 printf (" EFI_FVB2_READ_ENABLED_CAP\n");\r
728 }\r
729\r
730 if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) {\r
731 printf (" EFI_FVB2_READ_STATUS\n");\r
732 }\r
733\r
734 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) {\r
735 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");\r
736 }\r
737\r
738 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) {\r
739 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");\r
740 }\r
741\r
742 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) {\r
743 printf (" EFI_FVB2_WRITE_STATUS\n");\r
744 }\r
745\r
746 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) {\r
747 printf (" EFI_FVB2_LOCK_CAP\n");\r
748 }\r
749\r
750 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) {\r
751 printf (" EFI_FVB2_LOCK_STATUS\n");\r
752 }\r
753\r
754 if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) {\r
755 printf (" EFI_FVB2_STICKY_WRITE\n");\r
756 }\r
757\r
758 if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) {\r
759 printf (" EFI_FVB2_MEMORY_MAPPED\n");\r
760 }\r
761\r
762 if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) {\r
763 printf (" EFI_FVB2_ERASE_POLARITY\n");\r
764 *ErasePolarity = TRUE;\r
765 }\r
766\r
767#if (PI_SPECIFICATION_VERSION < 0x00010000)\r
768 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {\r
769 printf (" EFI_FVB2_ALIGNMENT\n");\r
770 }\r
771\r
772 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {\r
773 printf (" EFI_FVB2_ALIGNMENT_2\n");\r
774 }\r
775\r
776 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {\r
777 printf (" EFI_FVB2_ALIGNMENT_4\n");\r
778 }\r
779\r
780 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {\r
781 printf (" EFI_FVB2_ALIGNMENT_8\n");\r
782 }\r
783\r
784 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {\r
785 printf (" EFI_FVB2_ALIGNMENT_16\n");\r
786 }\r
787\r
788 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {\r
789 printf (" EFI_FVB2_ALIGNMENT_32\n");\r
790 }\r
791\r
792 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {\r
793 printf (" EFI_FVB2_ALIGNMENT_64\n");\r
794 }\r
795\r
796 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {\r
797 printf (" EFI_FVB2_ALIGNMENT_128\n");\r
798 }\r
799\r
800 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {\r
801 printf (" EFI_FVB2_ALIGNMENT_256\n");\r
802 }\r
803\r
804 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {\r
805 printf (" EFI_FVB2_ALIGNMENT_512\n");\r
806 }\r
807\r
808 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {\r
809 printf (" EFI_FVB2_ALIGNMENT_1K\n");\r
810 }\r
811\r
812 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {\r
813 printf (" EFI_FVB2_ALIGNMENT_2K\n");\r
814 }\r
815\r
816 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {\r
817 printf (" EFI_FVB2_ALIGNMENT_4K\n");\r
818 }\r
819\r
820 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {\r
821 printf (" EFI_FVB2_ALIGNMENT_8K\n");\r
822 }\r
823\r
824 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {\r
825 printf (" EFI_FVB2_ALIGNMENT_16K\n");\r
826 }\r
827\r
828 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {\r
829 printf (" EFI_FVB2_ALIGNMENT_32K\n");\r
830 }\r
831\r
832 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {\r
833 printf (" EFI_FVB2_ALIGNMENT_64K\n");\r
834 }\r
835 \r
836#else\r
837\r
838 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {\r
839 printf (" EFI_FVB2_READ_LOCK_CAP\n");\r
840 }\r
841\r
842 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) {\r
843 printf (" EFI_FVB2_READ_LOCK_STATUS\n");\r
844 }\r
845\r
846 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) {\r
847 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");\r
848 }\r
849\r
850 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) {\r
851 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");\r
852 }\r
853\r
854 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) {\r
855 printf (" EFI_FVB2_ALIGNMENT_1\n");\r
856 }\r
857\r
858 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {\r
859 printf (" EFI_FVB2_ALIGNMENT_2\n");\r
860 }\r
861\r
862 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {\r
863 printf (" EFI_FVB2_ALIGNMENT_4\n");\r
864 }\r
865\r
866 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {\r
867 printf (" EFI_FVB2_ALIGNMENT_8\n");\r
868 }\r
869\r
870 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {\r
871 printf (" EFI_FVB2_ALIGNMENT_16\n");\r
872 }\r
873\r
874 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {\r
875 printf (" EFI_FVB2_ALIGNMENT_32\n");\r
876 }\r
877\r
878 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {\r
879 printf (" EFI_FVB2_ALIGNMENT_64\n");\r
880 }\r
881\r
882 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {\r
883 printf (" EFI_FVB2_ALIGNMENT_128\n");\r
884 }\r
885\r
886 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {\r
887 printf (" EFI_FVB2_ALIGNMENT_256\n");\r
888 }\r
889\r
890 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {\r
891 printf (" EFI_FVB2_ALIGNMENT_512\n");\r
892 }\r
893\r
894 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {\r
895 printf (" EFI_FVB2_ALIGNMENT_1K\n");\r
896 }\r
897\r
898 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {\r
899 printf (" EFI_FVB2_ALIGNMENT_2K\n");\r
900 }\r
901\r
902 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {\r
903 printf (" EFI_FVB2_ALIGNMENT_4K\n");\r
904 }\r
905\r
906 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {\r
907 printf (" EFI_FVB2_ALIGNMENT_8K\n");\r
908 }\r
909\r
910 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {\r
911 printf (" EFI_FVB2_ALIGNMENT_16K\n");\r
912 }\r
913\r
914 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {\r
915 printf (" EFI_FVB2_ALIGNMENT_32K\n");\r
916 }\r
917\r
918 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {\r
919 printf (" EFI_FVB2_ALIGNMENT_64K\n");\r
920 }\r
921\r
922 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) {\r
923 printf (" EFI_FVB2_ALIGNMENT_128K\n");\r
924 }\r
925\r
926 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) {\r
927 printf (" EFI_FVB2_ALIGNMENT_256K\n");\r
928 }\r
929\r
930 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) {\r
931 printf (" EFI_FVB2_ALIGNMENT_512K\n");\r
932 }\r
933\r
934 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) {\r
935 printf (" EFI_FVB2_ALIGNMENT_1M\n");\r
936 }\r
937\r
938 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) {\r
939 printf (" EFI_FVB2_ALIGNMENT_2M\n");\r
940 }\r
941\r
942 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) {\r
943 printf (" EFI_FVB2_ALIGNMENT_4M\n");\r
944 }\r
945\r
946 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) {\r
947 printf (" EFI_FVB2_ALIGNMENT_8M\n");\r
948 }\r
949\r
950 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) {\r
951 printf (" EFI_FVB2_ALIGNMENT_16M\n");\r
952 }\r
953\r
954 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) {\r
955 printf (" EFI_FVB2_ALIGNMENT_32M\n");\r
956 }\r
957\r
958 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {\r
959 printf (" EFI_FVB2_ALIGNMENT_64M\n");\r
960 }\r
961\r
962 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {\r
963 printf (" EFI_FVB2_ALIGNMENT_128M\n");\r
964 }\r
965\r
966 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {\r
967 printf (" EFI_FVB2_ALIGNMENT_64M\n");\r
968 }\r
969\r
970 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {\r
971 printf (" EFI_FVB2_ALIGNMENT_128M\n");\r
972 }\r
973\r
974 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) {\r
975 printf (" EFI_FVB2_ALIGNMENT_256M\n");\r
976 }\r
977\r
978 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) {\r
979 printf (" EFI_FVB2_ALIGNMENT_512M\n");\r
980 }\r
981\r
982 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) {\r
983 printf (" EFI_FVB2_ALIGNMENT_1G\n");\r
984 }\r
985\r
986 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) {\r
987 printf (" EFI_FVB2_ALIGNMENT_2G\n");\r
988 }\r
989\r
990#endif\r
991 printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength);\r
992 printf ("File System ID: ");\r
993 PrintGuid (&VolumeHeader.FileSystemGuid);\r
994 //\r
995 // printf ("\n");\r
996 //\r
997 printf ("Revision: 0x%04X\n", VolumeHeader.Revision);\r
998\r
999 do {\r
1000 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);\r
1001 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);\r
1002\r
1003 if (BlockMap.NumBlocks != 0) {\r
1004 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap.NumBlocks);\r
1005 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap.Length);\r
1006 Size += BlockMap.NumBlocks * BlockMap.Length;\r
1007 }\r
1008\r
1009 } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));\r
1010\r
1011 if (BytesRead != VolumeHeader.HeaderLength) {\r
1012 printf ("ERROR: Header length not consistent with Block Maps!\n");\r
1013 return EFI_ABORTED;\r
1014 }\r
1015\r
1016 if (VolumeHeader.FvLength != Size) {\r
1017 printf ("ERROR: Volume Size not consistant with Block Maps!\n");\r
1018 return EFI_ABORTED;\r
1019 }\r
1020\r
1021 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size);\r
1022\r
1023 *FvSize = Size;\r
1024\r
1025 //\r
1026 // rewind (InputFile);\r
1027 //\r
1028 return EFI_SUCCESS;\r
1029}\r
1030\r
1031STATIC\r
1032EFI_STATUS\r
1033PrintFileInfo (\r
1034 EFI_FIRMWARE_VOLUME_HEADER *FvImage,\r
1035 EFI_FFS_FILE_HEADER *FileHeader,\r
1036 BOOLEAN ErasePolarity\r
1037 )\r
1038/*++\r
1039\r
1040Routine Description:\r
1041\r
1042 GC_TODO: Add function description\r
1043\r
1044Arguments:\r
1045\r
1046 FvImage - GC_TODO: add argument description\r
1047 FileHeader - GC_TODO: add argument description\r
1048 ErasePolarity - GC_TODO: add argument description\r
1049\r
1050Returns:\r
1051\r
1052 EFI_SUCCESS - GC_TODO: Add description for return value\r
1053 EFI_ABORTED - GC_TODO: Add description for return value\r
1054\r
1055--*/\r
1056{\r
1057 UINT32 FileLength;\r
1058 UINT8 FileState;\r
1059 UINT8 Checksum;\r
e4ac870f 1060 EFI_FFS_FILE_HEADER2 BlankHeader;\r
f51461c8
LG
1061 EFI_STATUS Status;\r
1062 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
e4ac870f 1063 UINT32 HeaderSize;\r
f51461c8
LG
1064#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
1065 UINT16 *Tail;\r
1066#endif\r
1067 //\r
1068 // Check if we have free space\r
1069 //\r
e4ac870f 1070 HeaderSize = FvBufGetFfsHeaderSize(FileHeader);\r
f51461c8 1071 if (ErasePolarity) {\r
e4ac870f 1072 memset (&BlankHeader, -1, HeaderSize);\r
f51461c8 1073 } else {\r
e4ac870f 1074 memset (&BlankHeader, 0, HeaderSize);\r
f51461c8
LG
1075 }\r
1076\r
e4ac870f 1077 if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) {\r
f51461c8
LG
1078 return EFI_SUCCESS;\r
1079 }\r
1080 //\r
1081 // Print file information.\r
1082 //\r
1083 printf ("============================================================\n");\r
1084\r
1085 printf ("File Name: ");\r
1086 PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE);\r
1087 printf ("%s ", GuidBuffer);\r
1088 PrintGuidName (GuidBuffer);\r
1089 printf ("\n");\r
1090\r
1091 //\r
1092 // PrintGuid (&FileHeader->Name);\r
1093 // printf ("\n");\r
1094 //\r
e4ac870f 1095 FileLength = FvBufGetFfsFileSize (FileHeader);\r
f51461c8
LG
1096 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));\r
1097 printf ("File Length: 0x%08X\n", (unsigned) FileLength);\r
1098 printf ("File Attributes: 0x%02X\n", FileHeader->Attributes);\r
1099 printf ("File State: 0x%02X\n", FileHeader->State);\r
1100\r
1101 //\r
1102 // Print file state\r
1103 //\r
1104 FileState = GetFileState (ErasePolarity, FileHeader);\r
1105\r
1106 switch (FileState) {\r
1107\r
1108 case EFI_FILE_HEADER_CONSTRUCTION:\r
1109 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");\r
1110 return EFI_SUCCESS;\r
1111\r
1112 case EFI_FILE_HEADER_INVALID:\r
1113 printf (" EFI_FILE_HEADER_INVALID\n");\r
1114 return EFI_SUCCESS;\r
1115\r
1116 case EFI_FILE_HEADER_VALID:\r
1117 printf (" EFI_FILE_HEADER_VALID\n");\r
e4ac870f 1118 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);\r
f51461c8
LG
1119 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
1120 Checksum = (UINT8) (Checksum - FileHeader->State);\r
1121 if (Checksum != 0) {\r
1122 printf ("ERROR: Header checksum invalid.\n");\r
1123 return EFI_ABORTED;\r
1124 }\r
1125\r
1126 return EFI_SUCCESS;\r
1127\r
1128 case EFI_FILE_DELETED:\r
1129 printf (" EFI_FILE_DELETED\n");\r
1130\r
1131 case EFI_FILE_MARKED_FOR_UPDATE:\r
1132 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");\r
1133\r
1134 case EFI_FILE_DATA_VALID:\r
1135 printf (" EFI_FILE_DATA_VALID\n");\r
1136\r
1137 //\r
1138 // Calculate header checksum\r
1139 //\r
e4ac870f 1140 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);\r
f51461c8
LG
1141 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);\r
1142 Checksum = (UINT8) (Checksum - FileHeader->State);\r
1143 if (Checksum != 0) {\r
1144 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);\r
1145 return EFI_ABORTED;\r
1146 }\r
1147\r
e4ac870f 1148 FileLength = FvBufGetFfsFileSize (FileHeader);\r
f51461c8
LG
1149\r
1150 if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {\r
1151 //\r
1152 // Calculate file checksum\r
1153 //\r
e4ac870f 1154 Checksum = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize);\r
f51461c8
LG
1155 Checksum = Checksum + FileHeader->IntegrityCheck.Checksum.File;\r
1156 if (Checksum != 0) {\r
1157 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);\r
1158 return EFI_ABORTED;\r
1159 }\r
1160 } else {\r
1161 if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {\r
1162 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer);\r
1163 return EFI_ABORTED;\r
1164 }\r
1165 }\r
1166#if (PI_SPECIFICATION_VERSION < 0x00010000) \r
1167 //\r
1168 // Verify tail if present\r
1169 //\r
1170 if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {\r
1171 //\r
1172 // Verify tail is complement of integrity check field in the header.\r
1173 //\r
1174 Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK));\r
1175 if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) {\r
1176 Error (NULL, 0, 0003, "error parsing FFS file", \\r
1177 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer);\r
1178 return EFI_ABORTED;\r
1179 }\r
1180 }\r
1181 #endif \r
1182 break;\r
1183\r
1184 default:\r
1185 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);\r
1186 return EFI_ABORTED;\r
1187 }\r
1188\r
1189 printf ("File Type: 0x%02X ", FileHeader->Type);\r
1190\r
1191 switch (FileHeader->Type) {\r
1192\r
1193 case EFI_FV_FILETYPE_RAW:\r
1194 printf ("EFI_FV_FILETYPE_RAW\n");\r
1195 break;\r
1196\r
1197 case EFI_FV_FILETYPE_FREEFORM:\r
1198 printf ("EFI_FV_FILETYPE_FREEFORM\n");\r
1199 break;\r
1200\r
1201 case EFI_FV_FILETYPE_SECURITY_CORE:\r
1202 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");\r
1203 break;\r
1204\r
1205 case EFI_FV_FILETYPE_PEI_CORE:\r
1206 printf ("EFI_FV_FILETYPE_PEI_CORE\n");\r
1207 break;\r
1208\r
1209 case EFI_FV_FILETYPE_DXE_CORE:\r
1210 printf ("EFI_FV_FILETYPE_DXE_CORE\n");\r
1211 break;\r
1212\r
1213 case EFI_FV_FILETYPE_PEIM:\r
1214 printf ("EFI_FV_FILETYPE_PEIM\n");\r
1215 break;\r
1216\r
1217 case EFI_FV_FILETYPE_DRIVER:\r
1218 printf ("EFI_FV_FILETYPE_DRIVER\n");\r
1219 break;\r
1220\r
1221 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:\r
1222 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");\r
1223 break;\r
1224\r
1225 case EFI_FV_FILETYPE_APPLICATION:\r
1226 printf ("EFI_FV_FILETYPE_APPLICATION\n");\r
1227 break;\r
1228\r
1229 case EFI_FV_FILETYPE_SMM:\r
1230 printf ("EFI_FV_FILETYPE_SMM\n");\r
1231 break;\r
1232\r
1233 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:\r
1234 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");\r
1235 break;\r
1236\r
1237 case EFI_FV_FILETYPE_COMBINED_SMM_DXE:\r
1238 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");\r
1239 break;\r
1240\r
1241 case EFI_FV_FILETYPE_SMM_CORE:\r
1242 printf ("EFI_FV_FILETYPE_SMM_CORE\n");\r
1243 break;\r
1244\r
1245 case EFI_FV_FILETYPE_FFS_PAD:\r
1246 printf ("EFI_FV_FILETYPE_FFS_PAD\n");\r
1247 break;\r
1248\r
1249 default:\r
1250 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type);\r
1251 return EFI_ABORTED;\r
1252 break;\r
1253 }\r
1254\r
1255 switch (FileHeader->Type) {\r
1256\r
1257 case EFI_FV_FILETYPE_ALL:\r
1258 case EFI_FV_FILETYPE_RAW:\r
1259 case EFI_FV_FILETYPE_FFS_PAD:\r
1260 break;\r
1261\r
1262 default:\r
1263 //\r
1264 // All other files have sections\r
1265 //\r
1266 Status = ParseSection (\r
e4ac870f
LG
1267 (UINT8 *) ((UINTN) FileHeader + HeaderSize),\r
1268 FvBufGetFfsFileSize (FileHeader) - HeaderSize\r
f51461c8
LG
1269 );\r
1270 if (EFI_ERROR (Status)) {\r
1271 //\r
1272 // printf ("ERROR: Parsing the FFS file.\n");\r
1273 //\r
1274 return EFI_ABORTED;\r
1275 }\r
1276 break;\r
1277 }\r
1278\r
1279 return EFI_SUCCESS;\r
1280}\r
1281\r
9947f576
YZ
1282EFI_STATUS\r
1283RebaseImageRead (\r
1284 IN VOID *FileHandle,\r
1285 IN UINTN FileOffset,\r
1286 IN OUT UINT32 *ReadSize,\r
1287 OUT VOID *Buffer\r
1288 )\r
1289/*++\r
1290\r
1291Routine Description:\r
1292\r
1293 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1294\r
1295Arguments:\r
1296\r
1297 FileHandle - The handle to the PE/COFF file\r
1298\r
1299 FileOffset - The offset, in bytes, into the file to read\r
1300\r
1301 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1302\r
1303 Buffer - A pointer to the buffer to read the data into.\r
1304\r
1305Returns:\r
1306\r
1307 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1308\r
1309--*/\r
1310{\r
1311 CHAR8 *Destination8;\r
1312 CHAR8 *Source8;\r
1313 UINT32 Length;\r
1314\r
1315 Destination8 = Buffer;\r
1316 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1317 Length = *ReadSize;\r
1318 while (Length--) {\r
1319 *(Destination8++) = *(Source8++);\r
1320 }\r
1321\r
1322 return EFI_SUCCESS;\r
1323}\r
1324\r
1325EFI_STATUS\r
1326SetAddressToSectionHeader (\r
1327 IN CHAR8 *FileName,\r
1328 IN OUT UINT8 *FileBuffer,\r
1329 IN UINT64 NewPe32BaseAddress\r
1330 )\r
1331/*++\r
1332\r
1333Routine Description:\r
1334\r
1335 Set new base address into the section header of PeImage\r
1336\r
1337Arguments:\r
1338\r
1339 FileName - Name of file\r
1340 FileBuffer - Pointer to PeImage.\r
1341 NewPe32BaseAddress - New Base Address for PE image.\r
1342\r
1343Returns:\r
1344\r
1345 EFI_SUCCESS Set new base address into this image successfully.\r
1346\r
1347--*/\r
1348{\r
1349 EFI_STATUS Status;\r
1350 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1351 UINTN Index;\r
1352 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
1353 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1354\r
1355 //\r
1356 // Initialize context\r
1357 //\r
1358 memset (&ImageContext, 0, sizeof (ImageContext));\r
1359 ImageContext.Handle = (VOID *) FileBuffer;\r
1360 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
1361 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
1362 if (EFI_ERROR (Status)) {\r
1363 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
1364 return Status;\r
1365 }\r
1366\r
1367 if (ImageContext.RelocationsStripped) {\r
1368 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
1369 return Status;\r
1370 }\r
1371\r
1372 //\r
1373 // Get PeHeader pointer\r
1374 //\r
1375 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
1376\r
1377 //\r
1378 // Get section header list\r
1379 //\r
1380 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
1381 (UINTN) ImgHdr +\r
1382 sizeof (UINT32) +\r
1383 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1384 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
1385 );\r
1386\r
1387 //\r
1388 // Set base address into the first section header that doesn't point to code section.\r
1389 //\r
1390 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1391 if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
1392 *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;\r
1393 break;\r
1394 }\r
1395 }\r
1396\r
9947f576
YZ
1397 //\r
1398 // BaseAddress is set to section header.\r
1399 //\r
1400 return EFI_SUCCESS;\r
1401}\r
1402\r
1403EFI_STATUS\r
1404RebaseImage (\r
1405 IN CHAR8 *FileName,\r
1406 IN OUT UINT8 *FileBuffer,\r
1407 IN UINT64 NewPe32BaseAddress\r
1408 )\r
1409/*++\r
1410\r
1411Routine Description:\r
1412\r
1413 Set new base address into PeImage, and fix up PeImage based on new address.\r
1414\r
1415Arguments:\r
1416\r
1417 FileName - Name of file\r
1418 FileBuffer - Pointer to PeImage.\r
1419 NewPe32BaseAddress - New Base Address for PE image.\r
1420\r
1421Returns:\r
1422\r
1423 EFI_INVALID_PARAMETER - BaseAddress is not valid.\r
1424 EFI_SUCCESS - Update PeImage is correctly.\r
1425\r
1426--*/\r
1427{\r
1428 EFI_STATUS Status;\r
1429 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1430 UINTN Index;\r
1431 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
1432 UINT8 *MemoryImagePointer;\r
1433 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1434\r
1435 //\r
1436 // Initialize context\r
1437 //\r
1438 memset (&ImageContext, 0, sizeof (ImageContext));\r
1439 ImageContext.Handle = (VOID *) FileBuffer;\r
1440 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
1441 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
1442 if (EFI_ERROR (Status)) {\r
1443 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
1444 return Status;\r
1445 }\r
1446\r
1447 if (ImageContext.RelocationsStripped) {\r
1448 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
1449 return Status;\r
1450 }\r
1451\r
1452 //\r
1453 // Get PeHeader pointer\r
1454 //\r
1455 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
1456\r
1457 //\r
1458 // Load and Relocate Image Data\r
1459 //\r
1460 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
1461 if (MemoryImagePointer == NULL) {\r
1462 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
1463 return EFI_OUT_OF_RESOURCES;\r
1464 }\r
1465 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
1466 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));\r
1467\r
1468 Status = PeCoffLoaderLoadImage (&ImageContext);\r
1469 if (EFI_ERROR (Status)) {\r
1470 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
1471 free ((VOID *) MemoryImagePointer);\r
1472 return Status;\r
1473 }\r
1474\r
1475 ImageContext.DestinationAddress = NewPe32BaseAddress;\r
1476 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
1477 if (EFI_ERROR (Status)) {\r
1478 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
1479 free ((VOID *) MemoryImagePointer);\r
1480 return Status;\r
1481 }\r
1482\r
1483 //\r
1484 // Copy Relocated data to raw image file.\r
1485 //\r
1486 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
1487 (UINTN) ImgHdr +\r
1488 sizeof (UINT32) +\r
1489 sizeof (EFI_IMAGE_FILE_HEADER) +\r
1490 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
1491 );\r
1492\r
1493 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1494 CopyMem (\r
1495 FileBuffer + SectionHeader->PointerToRawData,\r
1496 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),\r
1497 SectionHeader->SizeOfRawData\r
1498 );\r
1499 }\r
1500\r
1501 free ((VOID *) MemoryImagePointer);\r
1502\r
1503 //\r
1504 // Update Image Base Address\r
1505 //\r
1506 if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\r
1507 ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
1508 } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1509 ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
1510 } else {\r
1511 Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
1512 ImgHdr->Pe32.OptionalHeader.Magic,\r
1513 FileName\r
1514 );\r
1515 return EFI_ABORTED;\r
1516 }\r
1517\r
1518 //\r
1519 // Set new base address into section header\r
1520 //\r
1521 Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);\r
1522\r
1523 return Status;\r
1524}\r
1525\r
1526EFI_STATUS\r
1527CombinePath (\r
1528 IN CHAR8* DefaultPath,\r
1529 IN CHAR8* AppendPath,\r
1530 OUT CHAR8* NewPath\r
1531)\r
1532{\r
1533 UINT32 DefaultPathLen;\r
1534 DefaultPathLen = strlen(DefaultPath);\r
1535 strcpy(NewPath, DefaultPath);\r
1536 UINT64 Index = 0;\r
1537 for (; Index < DefaultPathLen; Index ++) {\r
1538 if (NewPath[Index] == '\\' || NewPath[Index] == '/') {\r
1539 if (NewPath[Index + 1] != '\0') {\r
1540 NewPath[Index] = '/';\r
1541 }\r
1542 }\r
1543 }\r
1544 if (NewPath[Index -1] != '/') {\r
1545 NewPath[Index] = '/';\r
1546 NewPath[Index + 1] = '\0';\r
1547 }\r
1548 strcat(NewPath, AppendPath);\r
1549 return EFI_SUCCESS;\r
1550}\r
1551\r
f51461c8
LG
1552EFI_STATUS\r
1553ParseSection (\r
1554 IN UINT8 *SectionBuffer,\r
1555 IN UINT32 BufferLength\r
1556 )\r
1557/*++\r
1558\r
1559Routine Description:\r
1560\r
1561 Parses EFI Sections\r
1562\r
1563Arguments:\r
1564\r
1565 SectionBuffer - Buffer containing the section to parse.\r
1566 BufferLength - Length of SectionBuffer\r
1567\r
1568Returns:\r
1569\r
1570 EFI_SECTION_ERROR - Problem with section parsing.\r
1571 (a) compression errors\r
1572 (b) unrecognized section \r
1573 EFI_UNSUPPORTED - Do not know how to parse the section.\r
1574 EFI_SUCCESS - Section successfully parsed.\r
1575 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1576\r
1577--*/\r
1578{\r
1579 EFI_SECTION_TYPE Type;\r
1580 UINT8 *Ptr;\r
1581 UINT32 SectionLength;\r
e4ac870f 1582 UINT32 SectionHeaderLen;\r
f51461c8
LG
1583 CHAR8 *SectionName;\r
1584 EFI_STATUS Status;\r
1585 UINT32 ParsedLength;\r
1586 UINT8 *CompressedBuffer;\r
1587 UINT32 CompressedLength;\r
1588 UINT8 *UncompressedBuffer;\r
1589 UINT32 UncompressedLength;\r
1590 UINT8 *ToolOutputBuffer;\r
1591 UINT32 ToolOutputLength;\r
1592 UINT8 CompressionType;\r
1593 UINT32 DstSize;\r
1594 UINT32 ScratchSize;\r
1595 UINT8 *ScratchBuffer;\r
1596 DECOMPRESS_FUNCTION DecompressFunction;\r
1597 GETINFO_FUNCTION GetInfoFunction;\r
1598 // CHAR16 *name;\r
1599 CHAR8 *ExtractionTool;\r
1600 CHAR8 *ToolInputFile;\r
1601 CHAR8 *ToolOutputFile;\r
f51461c8 1602 CHAR8 *SystemCommand;\r
e4ac870f
LG
1603 EFI_GUID *EfiGuid;\r
1604 UINT16 DataOffset;\r
1605 UINT16 Attributes;\r
1606 UINT32 RealHdrLen;\r
9947f576
YZ
1607 CHAR8 *ToolInputFileName;\r
1608 CHAR8 *ToolOutputFileName;\r
f51461c8
LG
1609\r
1610 ParsedLength = 0;\r
9947f576
YZ
1611 ToolInputFileName = NULL;\r
1612 ToolOutputFileName = NULL;\r
1613\r
f51461c8
LG
1614 while (ParsedLength < BufferLength) {\r
1615 Ptr = SectionBuffer + ParsedLength;\r
1616\r
1617 SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);\r
1618 Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;\r
1619\r
1620 //\r
1621 // This is sort of an odd check, but is necessary because FFS files are\r
1622 // padded to a QWORD boundary, meaning there is potentially a whole section\r
1623 // header worth of 0xFF bytes.\r
1624 //\r
1625 if (SectionLength == 0xffffff && Type == 0xff) {\r
1626 ParsedLength += 4;\r
1627 continue;\r
1628 }\r
1629\r
e4ac870f
LG
1630 //\r
1631 // Get real section file size\r
1632 //\r
1633 SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr);\r
1634 SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
1635\r
f51461c8 1636 SectionName = SectionNameToStr (Type);\r
9dd00cb6
HW
1637 if (SectionName != NULL) {\r
1638 printf ("------------------------------------------------------------\n");\r
1639 printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength);\r
1640 free (SectionName);\r
1641 }\r
f51461c8
LG
1642\r
1643 switch (Type) {\r
1644 case EFI_SECTION_RAW:\r
f51461c8
LG
1645 case EFI_SECTION_PIC:\r
1646 case EFI_SECTION_TE:\r
1647 // default is no more information\r
1648 break;\r
1649\r
9947f576
YZ
1650 case EFI_SECTION_PE32:\r
1651 if (EnableHash) {\r
1652 ToolInputFileName = "edk2Temp_InputEfi.tmp";\r
1653 ToolOutputFileName = "edk2Temp_OutputHash.tmp";\r
1654 RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);\r
1655 PutFileImage (\r
1656 ToolInputFileName,\r
1657 (CHAR8*)Ptr + SectionHeaderLen,\r
1658 SectionLength - SectionHeaderLen\r
1659 );\r
1660\r
9947f576 1661 SystemCommand = malloc (\r
aeadb1c4 1662 strlen (OPENSSL_COMMAND_FORMAT_STRING) +\r
9947f576
YZ
1663 strlen (OpenSslPath) +\r
1664 strlen (ToolInputFileName) +\r
1665 strlen (ToolOutputFileName) +\r
1666 1\r
1667 );\r
9dd00cb6
HW
1668 if (SystemCommand == NULL) {\r
1669 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1670 return EFI_OUT_OF_RESOURCES;\r
1671 }\r
9947f576
YZ
1672 sprintf (\r
1673 SystemCommand,\r
aeadb1c4 1674 OPENSSL_COMMAND_FORMAT_STRING,\r
9947f576
YZ
1675 OpenSslPath,\r
1676 ToolOutputFileName,\r
1677 ToolInputFileName\r
1678 );\r
1679\r
1680 if (system (SystemCommand) != EFI_SUCCESS) {\r
1681 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);\r
1682 }\r
1683 else {\r
1684 FILE *fp;\r
1685 CHAR8 *StrLine;\r
1686 CHAR8 *NewStr;\r
1687 UINT32 nFileLen;\r
1688 if((fp = fopen(ToolOutputFileName,"r")) == NULL) {\r
1689 Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);\r
1690 }\r
1691 else {\r
1692 fseek(fp,0,SEEK_SET);\r
1693 fseek(fp,0,SEEK_END);\r
1694 nFileLen = ftell(fp);\r
1695 fseek(fp,0,SEEK_SET);\r
1696 StrLine = malloc(nFileLen);\r
9dd00cb6
HW
1697 if (StrLine == NULL) {\r
1698 fclose(fp);\r
1699 free (SystemCommand);\r
1700 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1701 return EFI_OUT_OF_RESOURCES;\r
1702 }\r
9947f576
YZ
1703 fgets(StrLine, nFileLen, fp);\r
1704 NewStr = strrchr (StrLine, '=');\r
1705 printf (" SHA1: %s\n", NewStr + 1);\r
1706 free (StrLine);\r
9dd00cb6 1707 fclose(fp);\r
9947f576 1708 }\r
9947f576
YZ
1709 }\r
1710 remove(ToolInputFileName);\r
1711 remove(ToolOutputFileName);\r
1712 free (SystemCommand);\r
1713 }\r
1714 break;\r
1715\r
f51461c8 1716 case EFI_SECTION_USER_INTERFACE:\r
ed9ff268 1717 printf (" String: %ls\n", (wchar_t *) &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString);\r
f51461c8
LG
1718 break;\r
1719\r
1720 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
e4ac870f 1721 Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE);\r
f51461c8
LG
1722 if (EFI_ERROR (Status)) {\r
1723 Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);\r
1724 return EFI_SECTION_ERROR;\r
1725 }\r
1726 break;\r
1727\r
1728 case EFI_SECTION_COMPATIBILITY16:\r
1729 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:\r
1730 //\r
1731 // Section does not contain any further header information.\r
1732 //\r
1733 break;\r
1734\r
1735 case EFI_SECTION_PEI_DEPEX:\r
1736 case EFI_SECTION_DXE_DEPEX:\r
1737 case EFI_SECTION_SMM_DEPEX:\r
1738 DumpDepexSection (Ptr, SectionLength);\r
1739 break;\r
1740\r
1741 case EFI_SECTION_VERSION:\r
e4ac870f
LG
1742 printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen));\r
1743 printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16)));\r
f51461c8
LG
1744 break;\r
1745\r
1746 case EFI_SECTION_COMPRESSION:\r
1747 UncompressedBuffer = NULL;\r
e4ac870f
LG
1748 if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) {\r
1749 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION);\r
1750 UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength;\r
1751 CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType;\r
1752 } else {\r
1753 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2);\r
1754 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength;\r
1755 CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType;\r
1756 }\r
1757 CompressedLength = SectionLength - RealHdrLen;\r
f51461c8
LG
1758 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength);\r
1759\r
1760 if (CompressionType == EFI_NOT_COMPRESSED) {\r
1761 printf (" Compression Type: EFI_NOT_COMPRESSED\n");\r
1762 if (CompressedLength != UncompressedLength) {\r
1763 Error (\r
1764 NULL,\r
1765 0,\r
1766 0,\r
1767 "file is not compressed, but the compressed length does not match the uncompressed length",\r
1768 NULL\r
1769 );\r
1770 return EFI_SECTION_ERROR;\r
1771 }\r
1772\r
e4ac870f 1773 UncompressedBuffer = Ptr + RealHdrLen;\r
f51461c8
LG
1774 } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
1775 GetInfoFunction = EfiGetInfo;\r
1776 DecompressFunction = EfiDecompress;\r
1777 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");\r
1778\r
e4ac870f 1779 CompressedBuffer = Ptr + RealHdrLen;\r
f51461c8
LG
1780\r
1781 Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);\r
1782 if (EFI_ERROR (Status)) {\r
1783 Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);\r
1784 return EFI_SECTION_ERROR;\r
1785 }\r
1786\r
1787 if (DstSize != UncompressedLength) {\r
1788 Error (NULL, 0, 0003, "compression error in the compression section", NULL);\r
1789 return EFI_SECTION_ERROR;\r
1790 }\r
1791\r
1792 ScratchBuffer = malloc (ScratchSize);\r
85006654
HW
1793 if (ScratchBuffer == NULL) {\r
1794 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1795 return EFI_OUT_OF_RESOURCES;\r
1796 }\r
f51461c8 1797 UncompressedBuffer = malloc (UncompressedLength);\r
85006654
HW
1798 if (UncompressedBuffer == NULL) {\r
1799 free (ScratchBuffer);\r
1800 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
f51461c8
LG
1801 return EFI_OUT_OF_RESOURCES;\r
1802 }\r
1803 Status = DecompressFunction (\r
1804 CompressedBuffer,\r
1805 CompressedLength,\r
1806 UncompressedBuffer,\r
1807 UncompressedLength,\r
1808 ScratchBuffer,\r
1809 ScratchSize\r
1810 );\r
1811 free (ScratchBuffer);\r
1812 if (EFI_ERROR (Status)) {\r
1813 Error (NULL, 0, 0003, "decompress failed", NULL);\r
1814 free (UncompressedBuffer);\r
1815 return EFI_SECTION_ERROR;\r
1816 }\r
1817 } else {\r
1818 Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);\r
1819 return EFI_SECTION_ERROR;\r
1820 }\r
1821\r
1822 Status = ParseSection (UncompressedBuffer, UncompressedLength);\r
1823\r
1824 if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
1825 //\r
1826 // We need to deallocate Buffer\r
1827 //\r
1828 free (UncompressedBuffer);\r
1829 }\r
1830\r
1831 if (EFI_ERROR (Status)) {\r
1832 Error (NULL, 0, 0003, "failed to parse section", NULL);\r
1833 return EFI_SECTION_ERROR;\r
1834 }\r
1835 break;\r
1836\r
1837 case EFI_SECTION_GUID_DEFINED:\r
e4ac870f
LG
1838 if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) {\r
1839 EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid;\r
1840 DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset;\r
1841 Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes;\r
1842 } else {\r
1843 EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid;\r
1844 DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset;\r
1845 Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes;\r
1846 }\r
f51461c8 1847 printf (" SectionDefinitionGuid: ");\r
e4ac870f 1848 PrintGuid (EfiGuid);\r
f51461c8 1849 printf ("\n");\r
e4ac870f
LG
1850 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset);\r
1851 printf (" Attributes: 0x%04X\n", (unsigned) Attributes);\r
f51461c8
LG
1852\r
1853 ExtractionTool =\r
1854 LookupGuidedSectionToolPath (\r
1855 mParsedGuidedSectionTools,\r
e4ac870f 1856 EfiGuid\r
f51461c8
LG
1857 );\r
1858\r
1859 if (ExtractionTool != NULL) {\r
868c9c35 1860 #ifndef __GNUC__\r
f51461c8
LG
1861 ToolInputFile = CloneString (tmpnam (NULL));\r
1862 ToolOutputFile = CloneString (tmpnam (NULL));\r
868c9c35
YZ
1863 #else\r
1864 char tmp1[] = "/tmp/fileXXXXXX";\r
1865 char tmp2[] = "/tmp/fileXXXXXX";\r
1866 int fd1;\r
1867 int fd2;\r
1868 fd1 = mkstemp(tmp1);\r
1869 fd2 = mkstemp(tmp2);\r
1870 ToolInputFile = CloneString(tmp1);\r
1871 ToolOutputFile = CloneString(tmp2);\r
1872 close(fd1);\r
1873 close(fd2);\r
1874 #endif\r
f51461c8 1875\r
9dd00cb6
HW
1876 if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) {\r
1877 if (ToolInputFile != NULL) {\r
1878 free (ToolInputFile);\r
1879 }\r
1880 if (ToolOutputFile != NULL) {\r
1881 free (ToolOutputFile);\r
1882 }\r
1883 free (ExtractionTool);\r
1884\r
1885 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1886 return EFI_OUT_OF_RESOURCES;\r
1887 }\r
1888\r
f51461c8
LG
1889 //\r
1890 // Construction 'system' command string\r
1891 //\r
f51461c8 1892 SystemCommand = malloc (\r
aeadb1c4 1893 strlen (EXTRACT_COMMAND_FORMAT_STRING) +\r
f51461c8
LG
1894 strlen (ExtractionTool) +\r
1895 strlen (ToolInputFile) +\r
1896 strlen (ToolOutputFile) +\r
1897 1\r
1898 );\r
9dd00cb6
HW
1899 if (SystemCommand == NULL) {\r
1900 free (ToolInputFile);\r
1901 free (ToolOutputFile);\r
1902 free (ExtractionTool);\r
1903\r
1904 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1905 return EFI_OUT_OF_RESOURCES;\r
1906 }\r
f51461c8
LG
1907 sprintf (\r
1908 SystemCommand,\r
aeadb1c4 1909 EXTRACT_COMMAND_FORMAT_STRING,\r
f51461c8
LG
1910 ExtractionTool,\r
1911 ToolOutputFile,\r
1912 ToolInputFile\r
1913 );\r
1914 free (ExtractionTool);\r
1915\r
1916 Status =\r
1917 PutFileImage (\r
1918 ToolInputFile,\r
e4ac870f
LG
1919 (CHAR8*) SectionBuffer + DataOffset,\r
1920 BufferLength - DataOffset\r
f51461c8
LG
1921 );\r
1922\r
1923 system (SystemCommand);\r
1924 remove (ToolInputFile);\r
1925 free (ToolInputFile);\r
1926\r
1927 Status =\r
1928 GetFileImage (\r
1929 ToolOutputFile,\r
1930 (CHAR8 **)&ToolOutputBuffer,\r
1931 &ToolOutputLength\r
1932 );\r
1933 remove (ToolOutputFile);\r
1934 free (ToolOutputFile);\r
9dd00cb6 1935 free (SystemCommand);\r
f51461c8
LG
1936 if (EFI_ERROR (Status)) {\r
1937 Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);\r
1938 return EFI_SECTION_ERROR;\r
1939 }\r
1940\r
1941 Status = ParseSection (\r
1942 ToolOutputBuffer,\r
1943 ToolOutputLength\r
1944 );\r
1945 if (EFI_ERROR (Status)) {\r
1946 Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
1947 return EFI_SECTION_ERROR;\r
1948 }\r
1949\r
1950 //\r
1951 // Check for CRC32 sections which we can handle internally if needed.\r
1952 //\r
1953 } else if (!CompareGuid (\r
e4ac870f 1954 EfiGuid,\r
f51461c8
LG
1955 &gEfiCrc32GuidedSectionExtractionProtocolGuid\r
1956 )\r
1957 ) {\r
1958 //\r
1959 // CRC32 guided section\r
1960 //\r
1961 Status = ParseSection (\r
e4ac870f
LG
1962 SectionBuffer + DataOffset,\r
1963 BufferLength - DataOffset\r
f51461c8
LG
1964 );\r
1965 if (EFI_ERROR (Status)) {\r
1966 Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);\r
1967 return EFI_SECTION_ERROR;\r
1968 }\r
1969 } else {\r
1970 //\r
1971 // We don't know how to parse it now.\r
1972 //\r
1973 Error (NULL, 0, 0003, "Error parsing section", \\r
1974 "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory).");\r
1975 return EFI_UNSUPPORTED;\r
1976 }\r
1977 break;\r
1978\r
1979 default:\r
1980 //\r
1981 // Unknown section, return error\r
1982 //\r
1983 Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type);\r
1984 return EFI_SECTION_ERROR;\r
1985 }\r
1986\r
1987 ParsedLength += SectionLength;\r
1988 //\r
1989 // We make then next section begin on a 4-byte boundary\r
1990 //\r
1991 ParsedLength = GetOccupiedSize (ParsedLength, 4);\r
1992 }\r
1993\r
1994 if (ParsedLength < BufferLength) {\r
1995 Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);\r
1996 return EFI_SECTION_ERROR;\r
1997 }\r
1998\r
1999 return EFI_SUCCESS;\r
2000}\r
2001\r
2002EFI_STATUS\r
2003DumpDepexSection (\r
2004 IN UINT8 *Ptr,\r
2005 IN UINT32 SectionLength\r
2006 )\r
2007/*++\r
2008\r
2009Routine Description:\r
2010\r
2011 GC_TODO: Add function description\r
2012\r
2013Arguments:\r
2014\r
2015 Ptr - GC_TODO: add argument description\r
2016 SectionLength - GC_TODO: add argument description\r
2017\r
2018Returns:\r
2019\r
2020 EFI_SUCCESS - GC_TODO: Add description for return value\r
2021\r
2022--*/\r
2023{\r
2024 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
2025\r
2026 //\r
2027 // Need at least a section header + data\r
2028 //\r
2029 if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) {\r
2030 return EFI_SUCCESS;\r
2031 }\r
2032\r
e4ac870f
LG
2033 Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
2034 SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
f51461c8
LG
2035 while (SectionLength > 0) {\r
2036 printf (" ");\r
2037 switch (*Ptr) {\r
2038 case EFI_DEP_BEFORE:\r
2039 printf ("BEFORE\n");\r
2040 Ptr++;\r
2041 SectionLength--;\r
2042 break;\r
2043\r
2044 case EFI_DEP_AFTER:\r
2045 printf ("AFTER\n");\r
2046 Ptr++;\r
2047 SectionLength--;\r
2048 break;\r
2049\r
2050 case EFI_DEP_PUSH:\r
2051 printf ("PUSH\n ");\r
2052 PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE);\r
2053 printf ("%s ", GuidBuffer);\r
2054 PrintGuidName (GuidBuffer);\r
2055 printf ("\n");\r
2056 //\r
2057 // PrintGuid ((EFI_GUID *)(Ptr + 1));\r
2058 //\r
2059 Ptr += 17;\r
2060 SectionLength -= 17;\r
2061 break;\r
2062\r
2063 case EFI_DEP_AND:\r
2064 printf ("AND\n");\r
2065 Ptr++;\r
2066 SectionLength--;\r
2067 break;\r
2068\r
2069 case EFI_DEP_OR:\r
2070 printf ("OR\n");\r
2071 Ptr++;\r
2072 SectionLength--;\r
2073 break;\r
2074\r
2075 case EFI_DEP_NOT:\r
2076 printf ("NOT\n");\r
2077 Ptr++;\r
2078 SectionLength--;\r
2079 break;\r
2080\r
2081 case EFI_DEP_TRUE:\r
2082 printf ("TRUE\n");\r
2083 Ptr++;\r
2084 SectionLength--;\r
2085 break;\r
2086\r
2087 case EFI_DEP_FALSE:\r
2088 printf ("FALSE\n");\r
2089 Ptr++;\r
2090 SectionLength--;\r
2091 break;\r
2092\r
2093 case EFI_DEP_END:\r
2094 printf ("END DEPEX\n");\r
2095 Ptr++;\r
2096 SectionLength--;\r
2097 break;\r
2098\r
2099 case EFI_DEP_SOR:\r
2100 printf ("SOR\n");\r
2101 Ptr++;\r
2102 SectionLength--;\r
2103 break;\r
2104\r
2105 default:\r
2106 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr);\r
2107 return EFI_SUCCESS;\r
2108 }\r
2109 }\r
2110\r
2111 return EFI_SUCCESS;\r
2112}\r
2113\r
2114EFI_STATUS\r
2115PrintGuidName (\r
2116 IN UINT8 *GuidStr\r
2117 )\r
2118/*++\r
2119\r
2120Routine Description:\r
2121\r
2122 GC_TODO: Add function description\r
2123\r
2124Arguments:\r
2125\r
2126 GuidStr - GC_TODO: add argument description\r
2127\r
2128Returns:\r
2129\r
2130 EFI_SUCCESS - GC_TODO: Add description for return value\r
2131 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
2132\r
2133--*/\r
2134{\r
2135 GUID_TO_BASENAME *GPtr;\r
2136 //\r
2137 // If we have a list of guid-to-basenames, then go through the list to\r
2138 // look for a guid string match. If found, print the basename to stdout,\r
2139 // otherwise return a failure.\r
2140 //\r
2141 GPtr = mGuidBaseNameList;\r
2142 while (GPtr != NULL) {\r
2143 if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) {\r
2144 printf ("%s", GPtr->BaseName);\r
2145 return EFI_SUCCESS;\r
2146 }\r
2147\r
2148 GPtr = GPtr->Next;\r
2149 }\r
2150\r
2151 return EFI_INVALID_PARAMETER;\r
2152}\r
2153\r
2154EFI_STATUS\r
2155ParseGuidBaseNameFile (\r
2156 CHAR8 *FileName\r
2157 )\r
2158/*++\r
2159\r
2160Routine Description:\r
2161\r
2162 GC_TODO: Add function description\r
2163\r
2164Arguments:\r
2165\r
2166 FileName - GC_TODO: add argument description\r
2167\r
2168Returns:\r
2169\r
2170 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
2171 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value\r
2172 EFI_SUCCESS - GC_TODO: Add description for return value\r
2173\r
2174--*/\r
2175{\r
2176 FILE *Fptr;\r
2177 CHAR8 Line[MAX_LINE_LEN];\r
d6a1ce3b
HW
2178 CHAR8 *FormatString;\r
2179 INTN FormatLength;\r
f51461c8
LG
2180 GUID_TO_BASENAME *GPtr;\r
2181\r
97fa0ee9 2182 if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) {\r
f51461c8
LG
2183 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);\r
2184 return EFI_DEVICE_ERROR;\r
2185 }\r
2186\r
d6a1ce3b
HW
2187 //\r
2188 // Generate the format string for fscanf\r
2189 //\r
2190 FormatLength = snprintf (\r
2191 NULL,\r
2192 0,\r
2193 "%%%us %%%us",\r
2194 (unsigned) sizeof (GPtr->Guid) - 1,\r
2195 (unsigned) sizeof (GPtr->BaseName) - 1\r
2196 ) + 1;\r
2197\r
2198 FormatString = (CHAR8 *) malloc (FormatLength);\r
2199 if (FormatString == NULL) {\r
2200 fclose (Fptr);\r
2201 return EFI_OUT_OF_RESOURCES;\r
2202 }\r
2203\r
2204 snprintf (\r
2205 FormatString,\r
2206 FormatLength,\r
2207 "%%%us %%%us",\r
2208 (unsigned) sizeof (GPtr->Guid) - 1,\r
2209 (unsigned) sizeof (GPtr->BaseName) - 1\r
2210 );\r
2211\r
f51461c8
LG
2212 while (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
2213 //\r
2214 // Allocate space for another guid/basename element\r
2215 //\r
2216 GPtr = malloc (sizeof (GUID_TO_BASENAME));\r
2217 if (GPtr == NULL) {\r
d6a1ce3b 2218 free (FormatString);\r
2a9afe80 2219 fclose (Fptr);\r
f51461c8
LG
2220 return EFI_OUT_OF_RESOURCES;\r
2221 }\r
2222\r
2223 memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));\r
d6a1ce3b 2224 if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) {\r
f51461c8
LG
2225 GPtr->Next = mGuidBaseNameList;\r
2226 mGuidBaseNameList = GPtr;\r
2227 } else {\r
2228 //\r
2229 // Some sort of error. Just continue.\r
2230 //\r
2231 free (GPtr);\r
2232 }\r
2233 }\r
2234\r
d6a1ce3b 2235 free (FormatString);\r
f51461c8
LG
2236 fclose (Fptr);\r
2237 return EFI_SUCCESS;\r
2238}\r
2239\r
2240EFI_STATUS\r
2241FreeGuidBaseNameList (\r
2242 VOID\r
2243 )\r
2244/*++\r
2245\r
2246Routine Description:\r
2247\r
2248 GC_TODO: Add function description\r
2249\r
2250Arguments:\r
2251\r
2252 None\r
2253\r
2254Returns:\r
2255\r
2256 EFI_SUCCESS - GC_TODO: Add description for return value\r
2257\r
2258--*/\r
2259{\r
2260 GUID_TO_BASENAME *Next;\r
2261\r
2262 while (mGuidBaseNameList != NULL) {\r
2263 Next = mGuidBaseNameList->Next;\r
2264 free (mGuidBaseNameList);\r
2265 mGuidBaseNameList = Next;\r
2266 }\r
2267\r
2268 return EFI_SUCCESS;\r
2269}\r
2270\r
2271\r
2272static\r
2273VOID\r
2274LoadGuidedSectionToolsTxt (\r
2275 IN CHAR8* FirmwareVolumeFilename\r
2276 )\r
2277{\r
2278 CHAR8* PeerFilename;\r
2279 CHAR8* Places[] = {\r
2280 NULL,\r
2281 //NULL,\r
2282 };\r
2283 UINTN Index;\r
2284\r
2285 Places[0] = FirmwareVolumeFilename;\r
2286 //Places[1] = mUtilityFilename;\r
2287\r
2288 mParsedGuidedSectionTools = NULL;\r
2289\r
2290 for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) {\r
2291 PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt");\r
2292 //printf("Loading %s...\n", PeerFilename);\r
2293 if (OsPathExists (PeerFilename)) {\r
2294 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename);\r
2295 }\r
2296 free (PeerFilename);\r
2297 if (mParsedGuidedSectionTools != NULL) {\r
2298 return;\r
2299 }\r
2300 }\r
2301}\r
2302\r
2303\r
2304void\r
2305Usage (\r
2306 VOID\r
2307 )\r
2308/*++\r
2309\r
2310Routine Description:\r
2311\r
2312 GC_TODO: Add function description\r
2313\r
2314Arguments:\r
2315\r
2316 None\r
2317\r
2318Returns:\r
2319\r
2320 GC_TODO: add return values\r
2321\r
2322--*/\r
2323{\r
2324 //\r
2325 // Summary usage\r
2326 //\r
2327 fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME);\r
2328\r
2329 //\r
2330 // Copyright declaration\r
2331 // \r
45258285 2332 fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");\r
f4260465 2333 fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n");\r
f51461c8
LG
2334\r
2335 //\r
2336 // Details Option\r
2337 //\r
730ffca1 2338 fprintf (stdout, "optional arguments:\n");\r
f51461c8 2339 fprintf (stdout, " -h, --help\n\\r
730ffca1
YZ
2340 Show this help message and exit\n");\r
2341 fprintf (stdout, " --version\n\\r
2342 Show program's version number and exit\n");\r
2343 fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\\r
2344 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");\r
2345 fprintf (stdout, " -v, --verbose\n\\r
2346 Print informational statements\n");\r
2347 fprintf (stdout, " -q, --quiet\n\\r
2348 Returns the exit code, error messages will be displayed\n");\r
2349 fprintf (stdout, " -s, --silent\n\\r
2350 Returns only the exit code; informational and error\n\\r
2351 messages are not displayed\n");\r
2352 fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\\r
2353 Parse the basename to file-guid cross reference file(s)\n");\r
2354 fprintf (stdout, " -f OFFSET, --offset OFFSET\n\\r
2355 The offset from the start of the input file to start \n\\r
2356 processing an FV\n");\r
9947f576
YZ
2357 fprintf (stdout, " --hash\n\\r
2358 Generate HASH value of the entire PE image\n");\r
730ffca1
YZ
2359 fprintf (stdout, " --sfo\n\\r
2360 Reserved for future use\n");\r
f51461c8
LG
2361}\r
2362\r