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