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