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