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