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