]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools/VolInfo: Fix VS2010/VS2012 build failure
[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
8994d2f9
HW
1593 UINT64 Index;\r
1594\r
9947f576
YZ
1595 DefaultPathLen = strlen(DefaultPath);\r
1596 strcpy(NewPath, DefaultPath);\r
8994d2f9 1597 Index = 0;\r
9947f576
YZ
1598 for (; Index < DefaultPathLen; Index ++) {\r
1599 if (NewPath[Index] == '\\' || NewPath[Index] == '/') {\r
1600 if (NewPath[Index + 1] != '\0') {\r
1601 NewPath[Index] = '/';\r
1602 }\r
1603 }\r
1604 }\r
1605 if (NewPath[Index -1] != '/') {\r
1606 NewPath[Index] = '/';\r
1607 NewPath[Index + 1] = '\0';\r
1608 }\r
1609 strcat(NewPath, AppendPath);\r
1610 return EFI_SUCCESS;\r
1611}\r
1612\r
f51461c8
LG
1613EFI_STATUS\r
1614ParseSection (\r
1615 IN UINT8 *SectionBuffer,\r
1616 IN UINT32 BufferLength\r
1617 )\r
1618/*++\r
1619\r
1620Routine Description:\r
1621\r
1622 Parses EFI Sections\r
1623\r
1624Arguments:\r
1625\r
1626 SectionBuffer - Buffer containing the section to parse.\r
1627 BufferLength - Length of SectionBuffer\r
1628\r
1629Returns:\r
1630\r
1631 EFI_SECTION_ERROR - Problem with section parsing.\r
1632 (a) compression errors\r
1633 (b) unrecognized section \r
1634 EFI_UNSUPPORTED - Do not know how to parse the section.\r
1635 EFI_SUCCESS - Section successfully parsed.\r
1636 EFI_OUT_OF_RESOURCES - Memory allocation failed.\r
1637\r
1638--*/\r
1639{\r
1640 EFI_SECTION_TYPE Type;\r
1641 UINT8 *Ptr;\r
1642 UINT32 SectionLength;\r
e4ac870f 1643 UINT32 SectionHeaderLen;\r
f51461c8
LG
1644 CHAR8 *SectionName;\r
1645 EFI_STATUS Status;\r
1646 UINT32 ParsedLength;\r
1647 UINT8 *CompressedBuffer;\r
1648 UINT32 CompressedLength;\r
1649 UINT8 *UncompressedBuffer;\r
1650 UINT32 UncompressedLength;\r
1651 UINT8 *ToolOutputBuffer;\r
1652 UINT32 ToolOutputLength;\r
1653 UINT8 CompressionType;\r
1654 UINT32 DstSize;\r
1655 UINT32 ScratchSize;\r
1656 UINT8 *ScratchBuffer;\r
1657 DECOMPRESS_FUNCTION DecompressFunction;\r
1658 GETINFO_FUNCTION GetInfoFunction;\r
1659 // CHAR16 *name;\r
1660 CHAR8 *ExtractionTool;\r
1661 CHAR8 *ToolInputFile;\r
1662 CHAR8 *ToolOutputFile;\r
f51461c8 1663 CHAR8 *SystemCommand;\r
e4ac870f
LG
1664 EFI_GUID *EfiGuid;\r
1665 UINT16 DataOffset;\r
1666 UINT16 Attributes;\r
1667 UINT32 RealHdrLen;\r
9947f576
YZ
1668 CHAR8 *ToolInputFileName;\r
1669 CHAR8 *ToolOutputFileName;\r
3883e2cb 1670 CHAR8 *UIFileName;\r
f51461c8
LG
1671\r
1672 ParsedLength = 0;\r
9947f576
YZ
1673 ToolInputFileName = NULL;\r
1674 ToolOutputFileName = NULL;\r
1675\r
f51461c8
LG
1676 while (ParsedLength < BufferLength) {\r
1677 Ptr = SectionBuffer + ParsedLength;\r
1678\r
1679 SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);\r
1680 Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;\r
1681\r
1682 //\r
1683 // This is sort of an odd check, but is necessary because FFS files are\r
1684 // padded to a QWORD boundary, meaning there is potentially a whole section\r
1685 // header worth of 0xFF bytes.\r
1686 //\r
1687 if (SectionLength == 0xffffff && Type == 0xff) {\r
1688 ParsedLength += 4;\r
1689 continue;\r
1690 }\r
1691\r
e4ac870f
LG
1692 //\r
1693 // Get real section file size\r
1694 //\r
1695 SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr);\r
1696 SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
1697\r
f51461c8 1698 SectionName = SectionNameToStr (Type);\r
9dd00cb6
HW
1699 if (SectionName != NULL) {\r
1700 printf ("------------------------------------------------------------\n");\r
1701 printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength);\r
1702 free (SectionName);\r
1703 }\r
f51461c8
LG
1704\r
1705 switch (Type) {\r
1706 case EFI_SECTION_RAW:\r
f51461c8
LG
1707 case EFI_SECTION_PIC:\r
1708 case EFI_SECTION_TE:\r
1709 // default is no more information\r
1710 break;\r
1711\r
9947f576
YZ
1712 case EFI_SECTION_PE32:\r
1713 if (EnableHash) {\r
1714 ToolInputFileName = "edk2Temp_InputEfi.tmp";\r
1715 ToolOutputFileName = "edk2Temp_OutputHash.tmp";\r
1716 RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);\r
1717 PutFileImage (\r
1718 ToolInputFileName,\r
1719 (CHAR8*)Ptr + SectionHeaderLen,\r
1720 SectionLength - SectionHeaderLen\r
1721 );\r
1722\r
9947f576 1723 SystemCommand = malloc (\r
aeadb1c4 1724 strlen (OPENSSL_COMMAND_FORMAT_STRING) +\r
9947f576
YZ
1725 strlen (OpenSslPath) +\r
1726 strlen (ToolInputFileName) +\r
1727 strlen (ToolOutputFileName) +\r
1728 1\r
1729 );\r
9dd00cb6
HW
1730 if (SystemCommand == NULL) {\r
1731 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1732 return EFI_OUT_OF_RESOURCES;\r
1733 }\r
9947f576
YZ
1734 sprintf (\r
1735 SystemCommand,\r
aeadb1c4 1736 OPENSSL_COMMAND_FORMAT_STRING,\r
9947f576
YZ
1737 OpenSslPath,\r
1738 ToolOutputFileName,\r
1739 ToolInputFileName\r
1740 );\r
1741\r
1742 if (system (SystemCommand) != EFI_SUCCESS) {\r
1743 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);\r
1744 }\r
1745 else {\r
1746 FILE *fp;\r
1747 CHAR8 *StrLine;\r
1748 CHAR8 *NewStr;\r
1749 UINT32 nFileLen;\r
1750 if((fp = fopen(ToolOutputFileName,"r")) == NULL) {\r
1751 Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);\r
1752 }\r
1753 else {\r
1754 fseek(fp,0,SEEK_SET);\r
1755 fseek(fp,0,SEEK_END);\r
1756 nFileLen = ftell(fp);\r
1757 fseek(fp,0,SEEK_SET);\r
1758 StrLine = malloc(nFileLen);\r
9dd00cb6
HW
1759 if (StrLine == NULL) {\r
1760 fclose(fp);\r
1761 free (SystemCommand);\r
1762 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1763 return EFI_OUT_OF_RESOURCES;\r
1764 }\r
9947f576
YZ
1765 fgets(StrLine, nFileLen, fp);\r
1766 NewStr = strrchr (StrLine, '=');\r
1767 printf (" SHA1: %s\n", NewStr + 1);\r
1768 free (StrLine);\r
9dd00cb6 1769 fclose(fp);\r
9947f576 1770 }\r
9947f576
YZ
1771 }\r
1772 remove(ToolInputFileName);\r
1773 remove(ToolOutputFileName);\r
1774 free (SystemCommand);\r
1775 }\r
1776 break;\r
1777\r
f51461c8 1778 case EFI_SECTION_USER_INTERFACE:\r
3883e2cb
HW
1779 UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1);\r
1780 if (UIFileName == NULL) {\r
1781 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1782 return EFI_OUT_OF_RESOURCES;\r
1783 }\r
1784 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName);\r
1785 printf (" String: %s\n", UIFileName);\r
1786 free (UIFileName);\r
f51461c8
LG
1787 break;\r
1788\r
1789 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:\r
e4ac870f 1790 Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE);\r
f51461c8
LG
1791 if (EFI_ERROR (Status)) {\r
1792 Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);\r
1793 return EFI_SECTION_ERROR;\r
1794 }\r
1795 break;\r
1796\r
1797 case EFI_SECTION_COMPATIBILITY16:\r
1798 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:\r
1799 //\r
1800 // Section does not contain any further header information.\r
1801 //\r
1802 break;\r
1803\r
1804 case EFI_SECTION_PEI_DEPEX:\r
1805 case EFI_SECTION_DXE_DEPEX:\r
1806 case EFI_SECTION_SMM_DEPEX:\r
1807 DumpDepexSection (Ptr, SectionLength);\r
1808 break;\r
1809\r
1810 case EFI_SECTION_VERSION:\r
e4ac870f
LG
1811 printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen));\r
1812 printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16)));\r
f51461c8
LG
1813 break;\r
1814\r
1815 case EFI_SECTION_COMPRESSION:\r
1816 UncompressedBuffer = NULL;\r
e4ac870f
LG
1817 if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) {\r
1818 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION);\r
1819 UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength;\r
1820 CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType;\r
1821 } else {\r
1822 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2);\r
1823 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength;\r
1824 CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType;\r
1825 }\r
1826 CompressedLength = SectionLength - RealHdrLen;\r
f51461c8
LG
1827 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength);\r
1828\r
1829 if (CompressionType == EFI_NOT_COMPRESSED) {\r
1830 printf (" Compression Type: EFI_NOT_COMPRESSED\n");\r
1831 if (CompressedLength != UncompressedLength) {\r
1832 Error (\r
1833 NULL,\r
1834 0,\r
1835 0,\r
1836 "file is not compressed, but the compressed length does not match the uncompressed length",\r
1837 NULL\r
1838 );\r
1839 return EFI_SECTION_ERROR;\r
1840 }\r
1841\r
e4ac870f 1842 UncompressedBuffer = Ptr + RealHdrLen;\r
f51461c8
LG
1843 } else if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
1844 GetInfoFunction = EfiGetInfo;\r
1845 DecompressFunction = EfiDecompress;\r
1846 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");\r
1847\r
e4ac870f 1848 CompressedBuffer = Ptr + RealHdrLen;\r
f51461c8
LG
1849\r
1850 Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);\r
1851 if (EFI_ERROR (Status)) {\r
1852 Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);\r
1853 return EFI_SECTION_ERROR;\r
1854 }\r
1855\r
1856 if (DstSize != UncompressedLength) {\r
1857 Error (NULL, 0, 0003, "compression error in the compression section", NULL);\r
1858 return EFI_SECTION_ERROR;\r
1859 }\r
1860\r
1861 ScratchBuffer = malloc (ScratchSize);\r
85006654
HW
1862 if (ScratchBuffer == NULL) {\r
1863 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1864 return EFI_OUT_OF_RESOURCES;\r
1865 }\r
f51461c8 1866 UncompressedBuffer = malloc (UncompressedLength);\r
85006654
HW
1867 if (UncompressedBuffer == NULL) {\r
1868 free (ScratchBuffer);\r
1869 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
f51461c8
LG
1870 return EFI_OUT_OF_RESOURCES;\r
1871 }\r
1872 Status = DecompressFunction (\r
1873 CompressedBuffer,\r
1874 CompressedLength,\r
1875 UncompressedBuffer,\r
1876 UncompressedLength,\r
1877 ScratchBuffer,\r
1878 ScratchSize\r
1879 );\r
1880 free (ScratchBuffer);\r
1881 if (EFI_ERROR (Status)) {\r
1882 Error (NULL, 0, 0003, "decompress failed", NULL);\r
1883 free (UncompressedBuffer);\r
1884 return EFI_SECTION_ERROR;\r
1885 }\r
1886 } else {\r
1887 Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);\r
1888 return EFI_SECTION_ERROR;\r
1889 }\r
1890\r
1891 Status = ParseSection (UncompressedBuffer, UncompressedLength);\r
1892\r
1893 if (CompressionType == EFI_STANDARD_COMPRESSION) {\r
1894 //\r
1895 // We need to deallocate Buffer\r
1896 //\r
1897 free (UncompressedBuffer);\r
1898 }\r
1899\r
1900 if (EFI_ERROR (Status)) {\r
1901 Error (NULL, 0, 0003, "failed to parse section", NULL);\r
1902 return EFI_SECTION_ERROR;\r
1903 }\r
1904 break;\r
1905\r
1906 case EFI_SECTION_GUID_DEFINED:\r
e4ac870f
LG
1907 if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) {\r
1908 EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid;\r
1909 DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset;\r
1910 Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes;\r
1911 } else {\r
1912 EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid;\r
1913 DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset;\r
1914 Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes;\r
1915 }\r
f51461c8 1916 printf (" SectionDefinitionGuid: ");\r
e4ac870f 1917 PrintGuid (EfiGuid);\r
f51461c8 1918 printf ("\n");\r
e4ac870f
LG
1919 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset);\r
1920 printf (" Attributes: 0x%04X\n", (unsigned) Attributes);\r
f51461c8
LG
1921\r
1922 ExtractionTool =\r
1923 LookupGuidedSectionToolPath (\r
1924 mParsedGuidedSectionTools,\r
e4ac870f 1925 EfiGuid\r
f51461c8
LG
1926 );\r
1927\r
1928 if (ExtractionTool != NULL) {\r
868c9c35 1929 #ifndef __GNUC__\r
f51461c8
LG
1930 ToolInputFile = CloneString (tmpnam (NULL));\r
1931 ToolOutputFile = CloneString (tmpnam (NULL));\r
868c9c35
YZ
1932 #else\r
1933 char tmp1[] = "/tmp/fileXXXXXX";\r
1934 char tmp2[] = "/tmp/fileXXXXXX";\r
1935 int fd1;\r
1936 int fd2;\r
1937 fd1 = mkstemp(tmp1);\r
1938 fd2 = mkstemp(tmp2);\r
1939 ToolInputFile = CloneString(tmp1);\r
1940 ToolOutputFile = CloneString(tmp2);\r
1941 close(fd1);\r
1942 close(fd2);\r
1943 #endif\r
f51461c8 1944\r
9dd00cb6
HW
1945 if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) {\r
1946 if (ToolInputFile != NULL) {\r
1947 free (ToolInputFile);\r
1948 }\r
1949 if (ToolOutputFile != NULL) {\r
1950 free (ToolOutputFile);\r
1951 }\r
1952 free (ExtractionTool);\r
1953\r
1954 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1955 return EFI_OUT_OF_RESOURCES;\r
1956 }\r
1957\r
f51461c8
LG
1958 //\r
1959 // Construction 'system' command string\r
1960 //\r
f51461c8 1961 SystemCommand = malloc (\r
aeadb1c4 1962 strlen (EXTRACT_COMMAND_FORMAT_STRING) +\r
f51461c8
LG
1963 strlen (ExtractionTool) +\r
1964 strlen (ToolInputFile) +\r
1965 strlen (ToolOutputFile) +\r
1966 1\r
1967 );\r
9dd00cb6
HW
1968 if (SystemCommand == NULL) {\r
1969 free (ToolInputFile);\r
1970 free (ToolOutputFile);\r
1971 free (ExtractionTool);\r
1972\r
1973 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
1974 return EFI_OUT_OF_RESOURCES;\r
1975 }\r
f51461c8
LG
1976 sprintf (\r
1977 SystemCommand,\r
aeadb1c4 1978 EXTRACT_COMMAND_FORMAT_STRING,\r
f51461c8
LG
1979 ExtractionTool,\r
1980 ToolOutputFile,\r
1981 ToolInputFile\r
1982 );\r
1983 free (ExtractionTool);\r
1984\r
1985 Status =\r
1986 PutFileImage (\r
1987 ToolInputFile,\r
e4ac870f
LG
1988 (CHAR8*) SectionBuffer + DataOffset,\r
1989 BufferLength - DataOffset\r
f51461c8
LG
1990 );\r
1991\r
1992 system (SystemCommand);\r
1993 remove (ToolInputFile);\r
1994 free (ToolInputFile);\r
1995\r
1996 Status =\r
1997 GetFileImage (\r
1998 ToolOutputFile,\r
1999 (CHAR8 **)&ToolOutputBuffer,\r
2000 &ToolOutputLength\r
2001 );\r
2002 remove (ToolOutputFile);\r
2003 free (ToolOutputFile);\r
9dd00cb6 2004 free (SystemCommand);\r
f51461c8
LG
2005 if (EFI_ERROR (Status)) {\r
2006 Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);\r
2007 return EFI_SECTION_ERROR;\r
2008 }\r
2009\r
2010 Status = ParseSection (\r
2011 ToolOutputBuffer,\r
2012 ToolOutputLength\r
2013 );\r
2014 if (EFI_ERROR (Status)) {\r
2015 Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);\r
2016 return EFI_SECTION_ERROR;\r
2017 }\r
2018\r
2019 //\r
2020 // Check for CRC32 sections which we can handle internally if needed.\r
2021 //\r
2022 } else if (!CompareGuid (\r
e4ac870f 2023 EfiGuid,\r
f51461c8
LG
2024 &gEfiCrc32GuidedSectionExtractionProtocolGuid\r
2025 )\r
2026 ) {\r
2027 //\r
2028 // CRC32 guided section\r
2029 //\r
2030 Status = ParseSection (\r
e4ac870f
LG
2031 SectionBuffer + DataOffset,\r
2032 BufferLength - DataOffset\r
f51461c8
LG
2033 );\r
2034 if (EFI_ERROR (Status)) {\r
2035 Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);\r
2036 return EFI_SECTION_ERROR;\r
2037 }\r
2038 } else {\r
2039 //\r
2040 // We don't know how to parse it now.\r
2041 //\r
2042 Error (NULL, 0, 0003, "Error parsing section", \\r
2043 "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
2044 return EFI_UNSUPPORTED;\r
2045 }\r
2046 break;\r
2047\r
2048 default:\r
2049 //\r
2050 // Unknown section, return error\r
2051 //\r
2052 Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type);\r
2053 return EFI_SECTION_ERROR;\r
2054 }\r
2055\r
2056 ParsedLength += SectionLength;\r
2057 //\r
2058 // We make then next section begin on a 4-byte boundary\r
2059 //\r
2060 ParsedLength = GetOccupiedSize (ParsedLength, 4);\r
2061 }\r
2062\r
2063 if (ParsedLength < BufferLength) {\r
2064 Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);\r
2065 return EFI_SECTION_ERROR;\r
2066 }\r
2067\r
2068 return EFI_SUCCESS;\r
2069}\r
2070\r
2071EFI_STATUS\r
2072DumpDepexSection (\r
2073 IN UINT8 *Ptr,\r
2074 IN UINT32 SectionLength\r
2075 )\r
2076/*++\r
2077\r
2078Routine Description:\r
2079\r
2080 GC_TODO: Add function description\r
2081\r
2082Arguments:\r
2083\r
2084 Ptr - GC_TODO: add argument description\r
2085 SectionLength - GC_TODO: add argument description\r
2086\r
2087Returns:\r
2088\r
2089 EFI_SUCCESS - GC_TODO: Add description for return value\r
2090\r
2091--*/\r
2092{\r
2093 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];\r
2094\r
2095 //\r
2096 // Need at least a section header + data\r
2097 //\r
2098 if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) {\r
2099 return EFI_SUCCESS;\r
2100 }\r
2101\r
e4ac870f
LG
2102 Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
2103 SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);\r
f51461c8
LG
2104 while (SectionLength > 0) {\r
2105 printf (" ");\r
2106 switch (*Ptr) {\r
2107 case EFI_DEP_BEFORE:\r
2108 printf ("BEFORE\n");\r
2109 Ptr++;\r
2110 SectionLength--;\r
2111 break;\r
2112\r
2113 case EFI_DEP_AFTER:\r
2114 printf ("AFTER\n");\r
2115 Ptr++;\r
2116 SectionLength--;\r
2117 break;\r
2118\r
2119 case EFI_DEP_PUSH:\r
2120 printf ("PUSH\n ");\r
2121 PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE);\r
2122 printf ("%s ", GuidBuffer);\r
2123 PrintGuidName (GuidBuffer);\r
2124 printf ("\n");\r
2125 //\r
2126 // PrintGuid ((EFI_GUID *)(Ptr + 1));\r
2127 //\r
2128 Ptr += 17;\r
2129 SectionLength -= 17;\r
2130 break;\r
2131\r
2132 case EFI_DEP_AND:\r
2133 printf ("AND\n");\r
2134 Ptr++;\r
2135 SectionLength--;\r
2136 break;\r
2137\r
2138 case EFI_DEP_OR:\r
2139 printf ("OR\n");\r
2140 Ptr++;\r
2141 SectionLength--;\r
2142 break;\r
2143\r
2144 case EFI_DEP_NOT:\r
2145 printf ("NOT\n");\r
2146 Ptr++;\r
2147 SectionLength--;\r
2148 break;\r
2149\r
2150 case EFI_DEP_TRUE:\r
2151 printf ("TRUE\n");\r
2152 Ptr++;\r
2153 SectionLength--;\r
2154 break;\r
2155\r
2156 case EFI_DEP_FALSE:\r
2157 printf ("FALSE\n");\r
2158 Ptr++;\r
2159 SectionLength--;\r
2160 break;\r
2161\r
2162 case EFI_DEP_END:\r
2163 printf ("END DEPEX\n");\r
2164 Ptr++;\r
2165 SectionLength--;\r
2166 break;\r
2167\r
2168 case EFI_DEP_SOR:\r
2169 printf ("SOR\n");\r
2170 Ptr++;\r
2171 SectionLength--;\r
2172 break;\r
2173\r
2174 default:\r
2175 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr);\r
2176 return EFI_SUCCESS;\r
2177 }\r
2178 }\r
2179\r
2180 return EFI_SUCCESS;\r
2181}\r
2182\r
2183EFI_STATUS\r
2184PrintGuidName (\r
2185 IN UINT8 *GuidStr\r
2186 )\r
2187/*++\r
2188\r
2189Routine Description:\r
2190\r
2191 GC_TODO: Add function description\r
2192\r
2193Arguments:\r
2194\r
2195 GuidStr - GC_TODO: add argument description\r
2196\r
2197Returns:\r
2198\r
2199 EFI_SUCCESS - GC_TODO: Add description for return value\r
2200 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value\r
2201\r
2202--*/\r
2203{\r
2204 GUID_TO_BASENAME *GPtr;\r
2205 //\r
2206 // If we have a list of guid-to-basenames, then go through the list to\r
2207 // look for a guid string match. If found, print the basename to stdout,\r
2208 // otherwise return a failure.\r
2209 //\r
2210 GPtr = mGuidBaseNameList;\r
2211 while (GPtr != NULL) {\r
2212 if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) {\r
2213 printf ("%s", GPtr->BaseName);\r
2214 return EFI_SUCCESS;\r
2215 }\r
2216\r
2217 GPtr = GPtr->Next;\r
2218 }\r
2219\r
2220 return EFI_INVALID_PARAMETER;\r
2221}\r
2222\r
2223EFI_STATUS\r
2224ParseGuidBaseNameFile (\r
2225 CHAR8 *FileName\r
2226 )\r
2227/*++\r
2228\r
2229Routine Description:\r
2230\r
2231 GC_TODO: Add function description\r
2232\r
2233Arguments:\r
2234\r
2235 FileName - GC_TODO: add argument description\r
2236\r
2237Returns:\r
2238\r
2239 EFI_DEVICE_ERROR - GC_TODO: Add description for return value\r
2240 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value\r
2241 EFI_SUCCESS - GC_TODO: Add description for return value\r
2242\r
2243--*/\r
2244{\r
2245 FILE *Fptr;\r
2246 CHAR8 Line[MAX_LINE_LEN];\r
a9b4ee43 2247 CHAR8 FormatString[MAX_LINE_LEN];\r
f51461c8
LG
2248 GUID_TO_BASENAME *GPtr;\r
2249\r
97fa0ee9 2250 if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) {\r
f51461c8
LG
2251 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);\r
2252 return EFI_DEVICE_ERROR;\r
2253 }\r
2254\r
d6a1ce3b
HW
2255 //\r
2256 // Generate the format string for fscanf\r
2257 //\r
a9b4ee43 2258 sprintf (\r
d6a1ce3b 2259 FormatString,\r
d6a1ce3b
HW
2260 "%%%us %%%us",\r
2261 (unsigned) sizeof (GPtr->Guid) - 1,\r
2262 (unsigned) sizeof (GPtr->BaseName) - 1\r
2263 );\r
2264\r
f51461c8
LG
2265 while (fgets (Line, sizeof (Line), Fptr) != NULL) {\r
2266 //\r
2267 // Allocate space for another guid/basename element\r
2268 //\r
2269 GPtr = malloc (sizeof (GUID_TO_BASENAME));\r
2270 if (GPtr == NULL) {\r
2a9afe80 2271 fclose (Fptr);\r
f51461c8
LG
2272 return EFI_OUT_OF_RESOURCES;\r
2273 }\r
2274\r
2275 memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));\r
d6a1ce3b 2276 if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) {\r
f51461c8
LG
2277 GPtr->Next = mGuidBaseNameList;\r
2278 mGuidBaseNameList = GPtr;\r
2279 } else {\r
2280 //\r
2281 // Some sort of error. Just continue.\r
2282 //\r
2283 free (GPtr);\r
2284 }\r
2285 }\r
2286\r
2287 fclose (Fptr);\r
2288 return EFI_SUCCESS;\r
2289}\r
2290\r
2291EFI_STATUS\r
2292FreeGuidBaseNameList (\r
2293 VOID\r
2294 )\r
2295/*++\r
2296\r
2297Routine Description:\r
2298\r
2299 GC_TODO: Add function description\r
2300\r
2301Arguments:\r
2302\r
2303 None\r
2304\r
2305Returns:\r
2306\r
2307 EFI_SUCCESS - GC_TODO: Add description for return value\r
2308\r
2309--*/\r
2310{\r
2311 GUID_TO_BASENAME *Next;\r
2312\r
2313 while (mGuidBaseNameList != NULL) {\r
2314 Next = mGuidBaseNameList->Next;\r
2315 free (mGuidBaseNameList);\r
2316 mGuidBaseNameList = Next;\r
2317 }\r
2318\r
2319 return EFI_SUCCESS;\r
2320}\r
2321\r
2322\r
2323static\r
2324VOID\r
2325LoadGuidedSectionToolsTxt (\r
2326 IN CHAR8* FirmwareVolumeFilename\r
2327 )\r
2328{\r
2329 CHAR8* PeerFilename;\r
2330 CHAR8* Places[] = {\r
2331 NULL,\r
2332 //NULL,\r
2333 };\r
2334 UINTN Index;\r
2335\r
2336 Places[0] = FirmwareVolumeFilename;\r
2337 //Places[1] = mUtilityFilename;\r
2338\r
2339 mParsedGuidedSectionTools = NULL;\r
2340\r
2341 for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) {\r
2342 PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt");\r
2343 //printf("Loading %s...\n", PeerFilename);\r
2344 if (OsPathExists (PeerFilename)) {\r
2345 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename);\r
2346 }\r
2347 free (PeerFilename);\r
2348 if (mParsedGuidedSectionTools != NULL) {\r
2349 return;\r
2350 }\r
2351 }\r
2352}\r
2353\r
2354\r
2355void\r
2356Usage (\r
2357 VOID\r
2358 )\r
2359/*++\r
2360\r
2361Routine Description:\r
2362\r
2363 GC_TODO: Add function description\r
2364\r
2365Arguments:\r
2366\r
2367 None\r
2368\r
2369Returns:\r
2370\r
2371 GC_TODO: add return values\r
2372\r
2373--*/\r
2374{\r
2375 //\r
2376 // Summary usage\r
2377 //\r
2378 fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME);\r
2379\r
2380 //\r
2381 // Copyright declaration\r
2382 // \r
45258285 2383 fprintf (stdout, "Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.\n\n");\r
f4260465 2384 fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n");\r
f51461c8
LG
2385\r
2386 //\r
2387 // Details Option\r
2388 //\r
730ffca1 2389 fprintf (stdout, "optional arguments:\n");\r
f51461c8 2390 fprintf (stdout, " -h, --help\n\\r
730ffca1
YZ
2391 Show this help message and exit\n");\r
2392 fprintf (stdout, " --version\n\\r
2393 Show program's version number and exit\n");\r
2394 fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\\r
2395 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");\r
2396 fprintf (stdout, " -v, --verbose\n\\r
2397 Print informational statements\n");\r
2398 fprintf (stdout, " -q, --quiet\n\\r
2399 Returns the exit code, error messages will be displayed\n");\r
2400 fprintf (stdout, " -s, --silent\n\\r
2401 Returns only the exit code; informational and error\n\\r
2402 messages are not displayed\n");\r
2403 fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\\r
2404 Parse the basename to file-guid cross reference file(s)\n");\r
2405 fprintf (stdout, " -f OFFSET, --offset OFFSET\n\\r
2406 The offset from the start of the input file to start \n\\r
2407 processing an FV\n");\r
9947f576
YZ
2408 fprintf (stdout, " --hash\n\\r
2409 Generate HASH value of the entire PE image\n");\r
730ffca1
YZ
2410 fprintf (stdout, " --sfo\n\\r
2411 Reserved for future use\n");\r
f51461c8
LG
2412}\r
2413\r