Scrub BaseTools C Source to solve some gaps between EFI BaseTypes to POSIX types...
[efi/basetools/.git] / Source / C / VolInfo / VolInfo.c
1 /** @file
2
3 Copyright (c) 1999 - 2008, 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 (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 (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     "EFI_SECTION_ALL",
441     //
442     // 0X00
443     //
444     "EFI_SECTION_COMPRESSION",
445     //
446     // 0x01
447     //
448     "EFI_SECTION_GUID_DEFINED",
449     //
450     // 0x02
451     //
452     "Unknown section type - Reserved 0x03",
453     //
454     // 0x03
455     //
456     "Unknown section type - Reserved 0x04",
457     //
458     // 0x04
459     //
460     "Unknown section type - Reserved 0x05",
461     //
462     // 0x05
463     //
464     "Unknown section type - Reserved 0x06",
465     //
466     // 0x06
467     //
468     "Unknown section type - Reserved 0x07",
469     //
470     // 0x07
471     //
472     "Unknown section type - Reserved 0x08",
473     //
474     // 0x08
475     //
476     "Unknown section type - Reserved 0x09",
477     //
478     // 0x09
479     //
480     "Unknown section type - Reserved 0x0A",
481     //
482     // 0x0A
483     //
484     "Unknown section type - Reserved 0x0B",
485     //
486     // 0x0B
487     //
488     "Unknown section type - Reserved 0x0C",
489     //
490     // 0x0C
491     //
492     "Unknown section type - Reserved 0x0D",
493     //
494     // 0x0D
495     //
496     "Unknown section type - Reserved 0x0E",
497     //
498     // 0x0E
499     //
500     "Unknown section type - Reserved 0x0F",
501     //
502     // 0x0F
503     //
504     "EFI_SECTION_PE32",
505     //
506     // 0x10
507     //
508     "EFI_SECTION_PIC",
509     //
510     // 0x11
511     //
512     "EFI_SECTION_TE",
513     //
514     // 0x12
515     //
516     "EFI_SECTION_DXE_DEPEX",
517     //
518     // 0x13
519     //
520     "EFI_SECTION_VERSION",
521     //
522     // 0x14
523     //
524     "EFI_SECTION_USER_INTERFACE",
525     //
526     // 0x15
527     //
528     "EFI_SECTION_COMPATIBILITY16",
529     //
530     // 0x16
531     //
532     "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ",
533     //
534     // 0x17
535     //
536     "EFI_SECTION_FREEFORM_SUBTYPE_GUID ",
537     //
538     // 0x18
539     //
540     "EFI_SECTION_RAW",
541     //
542     // 0x19
543     //
544     "Unknown section type - 0x1A",
545     //
546     // 0x1A
547     //
548     "EFI_SECTION_PEI_DEPEX",
549     //
550     // 0x1B
551     //
552     "Unknown section type - Reserved - beyond last defined section"
553     //
554     // 0x1C+
555     //
556   };
557
558   if (Type > EFI_SECTION_LAST_SECTION_TYPE) {
559     Type = EFI_SECTION_LAST_SECTION_TYPE + 1;
560   }
561
562   SectionStr = malloc (100);
563   if (SectionStr == NULL) {
564     printf ("Error: Out of memory resources.\n");
565     return SectionStr;
566   }
567   strcpy (SectionStr, SectionTypeStringTable[Type]);
568   return SectionStr;
569 }
570
571 STATIC
572 EFI_STATUS
573 ReadHeader (
574   IN FILE       *InputFile,
575   OUT UINT32    *FvSize,
576   OUT BOOLEAN   *ErasePolarity
577   )
578 /*++
579
580 Routine Description:
581
582   This function determines the size of the FV and the erase polarity.  The 
583   erase polarity is the FALSE value for file state.
584
585 Arguments:
586
587   InputFile       The file that contains the FV image.
588   FvSize          The size of the FV.
589   ErasePolarity   The FV erase polarity.
590     
591 Returns:
592  
593   EFI_SUCCESS             Function completed successfully.
594   EFI_INVALID_PARAMETER   A required parameter was NULL or is out of range.
595   EFI_ABORTED             The function encountered an error.
596
597 --*/
598 {
599   EFI_FIRMWARE_VOLUME_HEADER  VolumeHeader;
600   EFI_FV_BLOCK_MAP_ENTRY      BlockMap;
601   UINTN                       Signature[2];
602   UINTN                       BytesRead;
603   UINT32                      Size;
604
605   BytesRead = 0;
606   Size      = 0;
607   //
608   // Check input parameters
609   //
610   if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) {
611     Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function");
612     return EFI_INVALID_PARAMETER;
613   }
614   //
615   // Read the header
616   //
617   fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
618   BytesRead     = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
619   Signature[0]  = VolumeHeader.Signature;
620   Signature[1]  = 0;
621
622   //
623   // Print FV header information
624   //
625   printf ("Signature:        %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature);
626   printf ("Attributes:       %X\n", VolumeHeader.Attributes);
627
628   if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) {
629     printf ("       EFI_FVB2_READ_DISABLED_CAP\n");
630   }
631
632   if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) {
633     printf ("       EFI_FVB2_READ_ENABLED_CAP\n");
634   }
635
636   if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) {
637     printf ("       EFI_FVB2_READ_STATUS\n");
638   }
639
640   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) {
641     printf ("       EFI_FVB2_WRITE_DISABLED_CAP\n");
642   }
643
644   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) {
645     printf ("       EFI_FVB2_WRITE_ENABLED_CAP\n");
646   }
647
648   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) {
649     printf ("       EFI_FVB2_WRITE_STATUS\n");
650   }
651
652   if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) {
653     printf ("       EFI_FVB2_LOCK_CAP\n");
654   }
655
656   if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) {
657     printf ("       EFI_FVB2_LOCK_STATUS\n");
658   }
659
660   if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) {
661     printf ("       EFI_FVB2_STICKY_WRITE\n");
662   }
663
664   if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) {
665     printf ("       EFI_FVB2_MEMORY_MAPPED\n");
666   }
667
668   if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) {
669     printf ("       EFI_FVB2_ERASE_POLARITY\n");
670     *ErasePolarity = TRUE;
671   }
672
673 #if (PI_SPECIFICATION_VERSION < 0x00010000)
674   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {
675     printf ("       EFI_FVB2_ALIGNMENT\n");
676   }
677
678   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {
679     printf ("       EFI_FVB2_ALIGNMENT_2\n");
680   }
681
682   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {
683     printf ("       EFI_FVB2_ALIGNMENT_4\n");
684   }
685
686   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {
687     printf ("       EFI_FVB2_ALIGNMENT_8\n");
688   }
689
690   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {
691     printf ("       EFI_FVB2_ALIGNMENT_16\n");
692   }
693
694   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {
695     printf ("       EFI_FVB2_ALIGNMENT_32\n");
696   }
697
698   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {
699     printf ("        EFI_FVB2_ALIGNMENT_64\n");
700   }
701
702   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {
703     printf ("        EFI_FVB2_ALIGNMENT_128\n");
704   }
705
706   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {
707     printf ("        EFI_FVB2_ALIGNMENT_256\n");
708   }
709
710   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {
711     printf ("        EFI_FVB2_ALIGNMENT_512\n");
712   }
713
714   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {
715     printf ("        EFI_FVB2_ALIGNMENT_1K\n");
716   }
717
718   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {
719     printf ("        EFI_FVB2_ALIGNMENT_2K\n");
720   }
721
722   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {
723     printf ("        EFI_FVB2_ALIGNMENT_4K\n");
724   }
725
726   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {
727     printf ("        EFI_FVB2_ALIGNMENT_8K\n");
728   }
729
730   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {
731     printf ("        EFI_FVB2_ALIGNMENT_16K\n");
732   }
733
734   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {
735     printf ("        EFI_FVB2_ALIGNMENT_32K\n");
736   }
737
738   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {
739     printf ("        EFI_FVB2_ALIGNMENT_64K\n");
740   }
741   
742 #else
743
744   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {
745     printf ("       EFI_FVB2_READ_LOCK_CAP\n");
746   }
747
748   if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) {
749     printf ("       EFI_FVB2_READ_LOCK_STATUS\n");
750   }
751
752   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) {
753     printf ("       EFI_FVB2_WRITE_LOCK_CAP\n");
754   }
755
756   if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) {
757     printf ("       EFI_FVB2_WRITE_LOCK_STATUS\n");
758   }
759
760   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) {
761     printf ("       EFI_FVB2_ALIGNMENT_1\n");
762   }
763
764   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {
765     printf ("        EFI_FVB2_ALIGNMENT_2\n");
766   }
767
768   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {
769     printf ("        EFI_FVB2_ALIGNMENT_4\n");
770   }
771
772   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {
773     printf ("        EFI_FVB2_ALIGNMENT_8\n");
774   }
775
776   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {
777     printf ("        EFI_FVB2_ALIGNMENT_16\n");
778   }
779
780   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {
781     printf ("        EFI_FVB2_ALIGNMENT_32\n");
782   }
783
784   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {
785     printf ("        EFI_FVB2_ALIGNMENT_64\n");
786   }
787
788   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {
789     printf ("        EFI_FVB2_ALIGNMENT_128\n");
790   }
791
792   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {
793     printf ("        EFI_FVB2_ALIGNMENT_256\n");
794   }
795
796   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {
797     printf ("        EFI_FVB2_ALIGNMENT_512\n");
798   }
799
800   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {
801     printf ("        EFI_FVB2_ALIGNMENT_1K\n");
802   }
803
804   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {
805     printf ("        EFI_FVB2_ALIGNMENT_2K\n");
806   }
807
808   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {
809     printf ("        EFI_FVB2_ALIGNMENT_4K\n");
810   }
811
812   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {
813     printf ("        EFI_FVB2_ALIGNMENT_8K\n");
814   }
815
816   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {
817     printf ("        EFI_FVB2_ALIGNMENT_16K\n");
818   }
819
820   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {
821     printf ("        EFI_FVB2_ALIGNMENT_32K\n");
822   }
823
824   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {
825     printf ("        EFI_FVB2_ALIGNMENT_64K\n");
826   }
827
828   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) {
829     printf ("        EFI_FVB2_ALIGNMENT_128K\n");
830   }
831
832   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) {
833     printf ("        EFI_FVB2_ALIGNMENT_256K\n");
834   }
835
836   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMNET_512K) {
837     printf ("        EFI_FVB2_ALIGNMNET_512K\n");
838   }
839
840   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) {
841     printf ("        EFI_FVB2_ALIGNMENT_1M\n");
842   }
843
844   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) {
845     printf ("        EFI_FVB2_ALIGNMENT_2M\n");
846   }
847
848   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) {
849     printf ("        EFI_FVB2_ALIGNMENT_4M\n");
850   }
851
852   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) {
853     printf ("        EFI_FVB2_ALIGNMENT_8M\n");
854   }
855
856   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) {
857     printf ("        EFI_FVB2_ALIGNMENT_16M\n");
858   }
859
860   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) {
861     printf ("        EFI_FVB2_ALIGNMENT_32M\n");
862   }
863
864   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {
865     printf ("        EFI_FVB2_ALIGNMENT_64M\n");
866   }
867
868   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {
869     printf ("        EFI_FVB2_ALIGNMENT_128M\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_256M) {
881     printf ("        EFI_FVB2_ALIGNMENT_256M\n");
882   }
883
884   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) {
885     printf ("        EFI_FVB2_ALIGNMENT_512M\n");
886   }
887
888   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) {
889     printf ("        EFI_FVB2_ALIGNMENT_1G\n");
890   }
891
892   if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) {
893     printf ("        EFI_FVB2_ALIGNMENT_2G\n");
894   }
895
896 #endif
897   printf ("Header Length:         0x%08X\n", VolumeHeader.HeaderLength);
898   printf ("File System ID:        ");
899   PrintGuid (&VolumeHeader.FileSystemGuid);
900   //
901   // printf ("\n");
902   //
903   printf ("Revision:              0x%04X\n", VolumeHeader.Revision);
904
905   do {
906     fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
907     BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
908
909     if (BlockMap.NumBlocks != 0) {
910       printf ("Number of Blocks:      0x%08X\n", (unsigned) BlockMap.NumBlocks);
911       printf ("Block Length:          0x%08X\n", (unsigned) BlockMap.Length);
912       Size += BlockMap.NumBlocks * BlockMap.Length;
913     }
914
915   } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));
916
917   if (BytesRead != VolumeHeader.HeaderLength) {
918     printf ("ERROR: Header length not consistent with Block Maps!\n");
919     return EFI_ABORTED;
920   }
921
922   if (VolumeHeader.FvLength != Size) {
923     printf ("ERROR: Volume Size not consistant with Block Maps!\n");
924     return EFI_ABORTED;
925   }
926
927   printf ("Total Volume Size:     0x%08X\n", (unsigned) Size);
928
929   *FvSize = Size;
930
931   //
932   // rewind (InputFile);
933   //
934   return EFI_SUCCESS;
935 }
936
937 STATIC
938 EFI_STATUS
939 PrintFileInfo (
940   EFI_FIRMWARE_VOLUME_HEADER  *FvImage,
941   EFI_FFS_FILE_HEADER         *FileHeader,
942   BOOLEAN                     ErasePolarity
943   )
944 /*++
945
946 Routine Description:
947
948   GC_TODO: Add function description
949
950 Arguments:
951
952   FvImage       - GC_TODO: add argument description
953   FileHeader    - GC_TODO: add argument description
954   ErasePolarity - GC_TODO: add argument description
955
956 Returns:
957
958   EFI_SUCCESS - GC_TODO: Add description for return value
959   EFI_ABORTED - GC_TODO: Add description for return value
960
961 --*/
962 {
963   UINT32              FileLength;
964   UINT8               FileState;
965   UINT8               Checksum;
966   EFI_FFS_FILE_HEADER BlankHeader;
967   EFI_STATUS          Status;
968   UINT8               GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
969 #if (PI_SPECIFICATION_VERSION < 0x00010000) 
970   UINT16              *Tail;
971 #endif
972   //
973   // Check if we have free space
974   //
975   if (ErasePolarity) {
976     memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER));
977   } else {
978     memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
979   }
980
981   if (memcmp (&BlankHeader, FileHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) {
982     return EFI_SUCCESS;
983   }
984   //
985   // Print file information.
986   //
987   printf ("============================================================\n");
988
989   printf ("File Name:        ");
990   PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE);
991   printf ("%s  ", GuidBuffer);
992   PrintGuidName (GuidBuffer);
993   printf ("\n");
994
995   //
996   //  PrintGuid (&FileHeader->Name);
997   //  printf ("\n");
998   //
999   FileLength = GetLength (FileHeader->Size);
1000   printf ("File Offset:      0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));
1001   printf ("File Length:      0x%08X\n", (unsigned) FileLength);
1002   printf ("File Attributes:  0x%02X\n", FileHeader->Attributes);
1003   printf ("File State:       0x%02X\n", FileHeader->State);
1004
1005   //
1006   // Print file state
1007   //
1008   FileState = GetFileState (ErasePolarity, FileHeader);
1009
1010   switch (FileState) {
1011
1012   case EFI_FILE_HEADER_CONSTRUCTION:
1013     printf ("        EFI_FILE_HEADER_CONSTRUCTION\n");
1014     return EFI_SUCCESS;
1015
1016   case EFI_FILE_HEADER_INVALID:
1017     printf ("        EFI_FILE_HEADER_INVALID\n");
1018     return EFI_SUCCESS;
1019
1020   case EFI_FILE_HEADER_VALID:
1021     printf ("        EFI_FILE_HEADER_VALID\n");
1022     Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
1023     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
1024     Checksum  = (UINT8) (Checksum - FileHeader->State);
1025     if (Checksum != 0) {
1026       printf ("ERROR: Header checksum invalid.\n");
1027       return EFI_ABORTED;
1028     }
1029
1030     return EFI_SUCCESS;
1031
1032   case EFI_FILE_DELETED:
1033     printf ("        EFI_FILE_DELETED\n");
1034
1035   case EFI_FILE_MARKED_FOR_UPDATE:
1036     printf ("        EFI_FILE_MARKED_FOR_UPDATE\n");
1037
1038   case EFI_FILE_DATA_VALID:
1039     printf ("        EFI_FILE_DATA_VALID\n");
1040
1041     //
1042     // Calculate header checksum
1043     //
1044     Checksum  = CalculateSum8 ((UINT8 *) FileHeader, sizeof (EFI_FFS_FILE_HEADER));
1045     Checksum  = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
1046     Checksum  = (UINT8) (Checksum - FileHeader->State);
1047     if (Checksum != 0) {
1048       Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);
1049       return EFI_ABORTED;
1050     }
1051
1052     FileLength = GetLength (FileHeader->Size);
1053
1054     if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
1055       //
1056       // Calculate file checksum
1057       //
1058       Checksum  = CalculateSum8 ((UINT8 *) FileHeader, FileLength);
1059       Checksum  = (UINT8) (Checksum - FileHeader->State);
1060       if (Checksum != 0) {
1061         Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);
1062         return EFI_ABORTED;
1063       }
1064     } else {
1065       if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
1066         Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0x5A", GuidBuffer);
1067         return EFI_ABORTED;
1068       }
1069     }
1070 #if (PI_SPECIFICATION_VERSION < 0x00010000)    
1071     //
1072     // Verify tail if present
1073     //
1074     if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1075       //
1076       // Verify tail is complement of integrity check field in the header.
1077       //
1078       Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK));
1079       if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) {
1080         Error (NULL, 0, 0003, "error parsing FFS file", \
1081         "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer);
1082         return EFI_ABORTED;
1083       }
1084     }
1085  #endif   
1086     break;
1087
1088   default:
1089     Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);
1090     return EFI_ABORTED;
1091   }
1092
1093   printf ("File Type:        0x%02X  ", FileHeader->Type);
1094
1095   switch (FileHeader->Type) {
1096
1097   case EFI_FV_FILETYPE_RAW:
1098     printf ("EFI_FV_FILETYPE_RAW\n");
1099     break;
1100
1101   case EFI_FV_FILETYPE_FREEFORM:
1102     printf ("EFI_FV_FILETYPE_FREEFORM\n");
1103     break;
1104
1105   case EFI_FV_FILETYPE_SECURITY_CORE:
1106     printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1107     break;
1108
1109   case EFI_FV_FILETYPE_PEI_CORE:
1110     printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1111     break;
1112
1113   case EFI_FV_FILETYPE_DXE_CORE:
1114     printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1115     break;
1116
1117   case EFI_FV_FILETYPE_PEIM:
1118     printf ("EFI_FV_FILETYPE_PEIM\n");
1119     break;
1120
1121   case EFI_FV_FILETYPE_DRIVER:
1122     printf ("EFI_FV_FILETYPE_DRIVER\n");
1123     break;
1124
1125   case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
1126     printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1127     break;
1128
1129   case EFI_FV_FILETYPE_APPLICATION:
1130     printf ("EFI_FV_FILETYPE_APPLICATION\n");
1131     break;
1132
1133   case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
1134     printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1135     break;
1136
1137   case EFI_FV_FILETYPE_FFS_PAD:
1138     printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1139     break;
1140
1141   default:
1142     printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type);
1143     return EFI_ABORTED;
1144     break;
1145   }
1146
1147   switch (FileHeader->Type) {
1148
1149   case EFI_FV_FILETYPE_ALL:
1150   case EFI_FV_FILETYPE_RAW:
1151   case EFI_FV_FILETYPE_FFS_PAD:
1152     break;
1153
1154   default:
1155     //
1156     // All other files have sections
1157     //
1158     Status = ParseSection (
1159               (UINT8 *) ((UINTN) FileHeader + sizeof (EFI_FFS_FILE_HEADER)),
1160               GetLength (FileHeader->Size) - sizeof (EFI_FFS_FILE_HEADER)
1161               );
1162     if (EFI_ERROR (Status)) {
1163       //
1164       // printf ("ERROR: Parsing the FFS file.\n");
1165       //
1166       return EFI_ABORTED;
1167     }
1168     break;
1169   }
1170
1171   return EFI_SUCCESS;
1172 }
1173
1174 EFI_STATUS
1175 ParseSection (
1176   IN UINT8  *SectionBuffer,
1177   IN UINT32 BufferLength
1178   )
1179 /*++
1180
1181 Routine Description:
1182
1183   Parses EFI Sections
1184
1185 Arguments:
1186
1187   SectionBuffer - Buffer containing the section to parse.
1188   BufferLength  - Length of SectionBuffer
1189
1190 Returns:
1191
1192   EFI_SECTION_ERROR - Problem with section parsing.
1193                       (a) compression errors
1194                       (b) unrecognized section 
1195   EFI_UNSUPPORTED - Do not know how to parse the section.
1196   EFI_SUCCESS - Section successfully parsed.
1197   EFI_OUT_OF_RESOURCES - Memory allocation failed.
1198
1199 --*/
1200 {
1201   EFI_SECTION_TYPE    Type;
1202   UINT8               *Ptr;
1203   UINT32              SectionLength;
1204   CHAR8               *SectionName;
1205   EFI_STATUS          Status;
1206   UINT32              ParsedLength;
1207   UINT8               *CompressedBuffer;
1208   UINT32              CompressedLength;
1209   UINT8               *UncompressedBuffer;
1210   UINT32              UncompressedLength;
1211   UINT8               *ToolOutputBuffer;
1212   UINT32              ToolOutputLength;
1213   UINT8               CompressionType;
1214   UINT32              DstSize;
1215   UINT32              ScratchSize;
1216   UINT8               *ScratchBuffer;
1217   DECOMPRESS_FUNCTION DecompressFunction;
1218   GETINFO_FUNCTION    GetInfoFunction;
1219   // CHAR16              *name;
1220   CHAR8               *ExtractionTool;
1221   CHAR8               *ToolInputFile;
1222   CHAR8               *ToolOutputFile;
1223   CHAR8               *SystemCommandFormatString;
1224   CHAR8               *SystemCommand;
1225
1226   ParsedLength = 0;
1227   while (ParsedLength < BufferLength) {
1228     Ptr           = SectionBuffer + ParsedLength;
1229
1230     SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);
1231     Type          = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;
1232
1233     //
1234     // This is sort of an odd check, but is necessary because FFS files are
1235     // padded to a QWORD boundary, meaning there is potentially a whole section
1236     // header worth of 0xFF bytes.
1237     //
1238     if (SectionLength == 0xffffff && Type == 0xff) {
1239       ParsedLength += 4;
1240       continue;
1241     }
1242
1243     SectionName = SectionNameToStr (Type);
1244     printf ("------------------------------------------------------------\n");
1245     printf ("  Type:  %s\n  Size:  0x%08X\n", SectionName, (unsigned) SectionLength);
1246     free (SectionName);
1247
1248     switch (Type) {
1249     case EFI_SECTION_RAW:
1250     case EFI_SECTION_PE32:
1251     case EFI_SECTION_PIC:
1252     case EFI_SECTION_TE:
1253       // default is no more information
1254       break;
1255
1256     case EFI_SECTION_USER_INTERFACE:
1257       // name = &((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString;
1258       // printf ("  String: %s\n", &name);
1259       break;
1260
1261     case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
1262       Status = PrintFvInfo (((EFI_FIRMWARE_VOLUME_IMAGE_SECTION*)Ptr) + 1);
1263       if (EFI_ERROR (Status)) {
1264         Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);
1265         return EFI_SECTION_ERROR;
1266       }
1267       break;
1268
1269     case EFI_SECTION_COMPATIBILITY16:
1270     case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
1271       //
1272       // Section does not contain any further header information.
1273       //
1274       break;
1275
1276     case EFI_SECTION_DXE_DEPEX:
1277     case EFI_SECTION_PEI_DEPEX:
1278       DumpDepexSection (Ptr, SectionLength);
1279       break;
1280
1281     case EFI_SECTION_VERSION:
1282       printf ("  Build Number:  0x%02X\n", ((EFI_VERSION_SECTION *) Ptr)->BuildNumber);
1283       printf ("  Version Strg:  %s\n", (char*) ((EFI_VERSION_SECTION *) Ptr)->VersionString);
1284       break;
1285
1286     case EFI_SECTION_COMPRESSION:
1287       UncompressedBuffer  = NULL;
1288       CompressedLength    = SectionLength - sizeof (EFI_COMPRESSION_SECTION);
1289       UncompressedLength  = ((EFI_COMPRESSION_SECTION *) Ptr)->UncompressedLength;
1290       CompressionType     = ((EFI_COMPRESSION_SECTION *) Ptr)->CompressionType;
1291       printf ("  Uncompressed Length:  0x%08X\n", (unsigned) UncompressedLength);
1292
1293       if (CompressionType == EFI_NOT_COMPRESSED) {
1294         printf ("  Compression Type:  EFI_NOT_COMPRESSED\n");
1295         if (CompressedLength != UncompressedLength) {
1296           Error (
1297             NULL,
1298             0,
1299             0,
1300             "file is not compressed, but the compressed length does not match the uncompressed length",
1301             NULL
1302             );
1303           return EFI_SECTION_ERROR;
1304         }
1305
1306         UncompressedBuffer = Ptr + sizeof (EFI_COMPRESSION_SECTION);
1307       } else if (CompressionType == EFI_STANDARD_COMPRESSION) {
1308         GetInfoFunction     = EfiGetInfo;
1309         DecompressFunction  = EfiDecompress;
1310         printf ("  Compression Type:  EFI_STANDARD_COMPRESSION\n");
1311
1312         CompressedBuffer  = Ptr + sizeof (EFI_COMPRESSION_SECTION);
1313
1314         Status            = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);
1315         if (EFI_ERROR (Status)) {
1316           Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);
1317           return EFI_SECTION_ERROR;
1318         }
1319
1320         if (DstSize != UncompressedLength) {
1321           Error (NULL, 0, 0003, "compression error in the compression section", NULL);
1322           return EFI_SECTION_ERROR;
1323         }
1324
1325         ScratchBuffer       = malloc (ScratchSize);
1326         UncompressedBuffer  = malloc (UncompressedLength);
1327         if ((ScratchBuffer == NULL) || (UncompressedBuffer == NULL)) {
1328           return EFI_OUT_OF_RESOURCES;
1329         }
1330         Status = DecompressFunction (
1331                   CompressedBuffer,
1332                   CompressedLength,
1333                   UncompressedBuffer,
1334                   UncompressedLength,
1335                   ScratchBuffer,
1336                   ScratchSize
1337                   );
1338         free (ScratchBuffer);
1339         if (EFI_ERROR (Status)) {
1340           Error (NULL, 0, 0003, "decompress failed", NULL);
1341           free (UncompressedBuffer);
1342           return EFI_SECTION_ERROR;
1343         }
1344       } else {
1345         Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);
1346         return EFI_SECTION_ERROR;
1347       }
1348
1349       Status = ParseSection (UncompressedBuffer, UncompressedLength);
1350
1351       if (CompressionType == EFI_STANDARD_COMPRESSION) {
1352         //
1353         // We need to deallocate Buffer
1354         //
1355         free (UncompressedBuffer);
1356       }
1357
1358       if (EFI_ERROR (Status)) {
1359         Error (NULL, 0, 0003, "failed to parse section", NULL);
1360         return EFI_SECTION_ERROR;
1361       }
1362       break;
1363
1364     case EFI_SECTION_GUID_DEFINED:
1365       printf ("  SectionDefinitionGuid:  ");
1366       PrintGuid (&((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid);
1367       printf ("\n");
1368       printf ("  DataOffset:             0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset);
1369       printf ("  Attributes:             0x%04X\n", (unsigned) ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes);
1370
1371       ExtractionTool =
1372         LookupGuidedSectionToolPath (
1373           mParsedGuidedSectionTools,
1374           &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid
1375           );
1376
1377       if (ExtractionTool != NULL) {
1378
1379         ToolInputFile = CloneString (tmpnam (NULL));
1380         ToolOutputFile = CloneString (tmpnam (NULL));
1381
1382         //
1383         // Construction 'system' command string
1384         //
1385         SystemCommandFormatString = "%s -d -o %s %s";
1386         SystemCommand = malloc (
1387           strlen (SystemCommandFormatString) +
1388           strlen (ExtractionTool) +
1389           strlen (ToolInputFile) +
1390           strlen (ToolOutputFile) +
1391           1
1392           );
1393         sprintf (
1394           SystemCommand,
1395           SystemCommandFormatString,
1396           ExtractionTool,
1397           ToolOutputFile,
1398           ToolInputFile
1399           );
1400         free (ExtractionTool);
1401
1402         Status =
1403           PutFileImage (
1404             ToolInputFile,
1405             (CHAR8*) SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,
1406             BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset
1407             );
1408
1409         system (SystemCommand);
1410         remove (ToolInputFile);
1411         free (ToolInputFile);
1412
1413         Status =
1414           GetFileImage (
1415             ToolOutputFile,
1416             (CHAR8 **)&ToolOutputBuffer,
1417             &ToolOutputLength
1418             );
1419         remove (ToolOutputFile);
1420         free (ToolOutputFile);
1421         if (EFI_ERROR (Status)) {
1422           Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);
1423           return EFI_SECTION_ERROR;
1424         }
1425
1426         Status = ParseSection (
1427                   ToolOutputBuffer,
1428                   ToolOutputLength
1429                   );
1430         if (EFI_ERROR (Status)) {
1431           Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
1432           return EFI_SECTION_ERROR;
1433         }
1434
1435       //
1436       // Check for CRC32 sections which we can handle internally if needed.
1437       //
1438       } else if (!CompareGuid (
1439                    &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid,
1440                    &gEfiCrc32GuidedSectionExtractionProtocolGuid
1441                    )
1442           ) {
1443         //
1444         // CRC32 guided section
1445         //
1446         Status = ParseSection (
1447                   SectionBuffer + ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset,
1448                   BufferLength - ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset
1449                   );
1450         if (EFI_ERROR (Status)) {
1451           Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);
1452           return EFI_SECTION_ERROR;
1453         }
1454       } else {
1455         //
1456         // We don't know how to parse it now.
1457         //
1458         Error (NULL, 0, 0003, "Error parsing section", \
1459         "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).");
1460         return EFI_UNSUPPORTED;
1461       }
1462       break;
1463
1464     default:
1465       //
1466       // Unknown section, return error
1467       //
1468       Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type);
1469       return EFI_SECTION_ERROR;
1470     }
1471
1472     ParsedLength += SectionLength;
1473     //
1474     // We make then next section begin on a 4-byte boundary
1475     //
1476     ParsedLength = GetOccupiedSize (ParsedLength, 4);
1477   }
1478
1479   if (ParsedLength < BufferLength) {
1480     Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);
1481     return EFI_SECTION_ERROR;
1482   }
1483
1484   return EFI_SUCCESS;
1485 }
1486
1487 EFI_STATUS
1488 DumpDepexSection (
1489   IN UINT8    *Ptr,
1490   IN UINT32   SectionLength
1491   )
1492 /*++
1493
1494 Routine Description:
1495
1496   GC_TODO: Add function description
1497
1498 Arguments:
1499
1500   Ptr           - GC_TODO: add argument description
1501   SectionLength - GC_TODO: add argument description
1502
1503 Returns:
1504
1505   EFI_SUCCESS - GC_TODO: Add description for return value
1506
1507 --*/
1508 {
1509   UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
1510
1511   //
1512   // Need at least a section header + data
1513   //
1514   if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) {
1515     return EFI_SUCCESS;
1516   }
1517
1518   Ptr += sizeof (EFI_COMMON_SECTION_HEADER);
1519   SectionLength -= sizeof (EFI_COMMON_SECTION_HEADER);
1520   while (SectionLength > 0) {
1521     printf ("        ");
1522     switch (*Ptr) {
1523     case EFI_DEP_BEFORE:
1524       printf ("BEFORE\n");
1525       Ptr++;
1526       SectionLength--;
1527       break;
1528
1529     case EFI_DEP_AFTER:
1530       printf ("AFTER\n");
1531       Ptr++;
1532       SectionLength--;
1533       break;
1534
1535     case EFI_DEP_PUSH:
1536       printf ("PUSH\n        ");
1537       PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE);
1538       printf ("%s  ", GuidBuffer);
1539       PrintGuidName (GuidBuffer);
1540       printf ("\n");
1541       //
1542       // PrintGuid ((EFI_GUID *)(Ptr + 1));
1543       //
1544       Ptr += 17;
1545       SectionLength -= 17;
1546       break;
1547
1548     case EFI_DEP_AND:
1549       printf ("AND\n");
1550       Ptr++;
1551       SectionLength--;
1552       break;
1553
1554     case EFI_DEP_OR:
1555       printf ("OR\n");
1556       Ptr++;
1557       SectionLength--;
1558       break;
1559
1560     case EFI_DEP_NOT:
1561       printf ("NOT\n");
1562       Ptr++;
1563       SectionLength--;
1564       break;
1565
1566     case EFI_DEP_TRUE:
1567       printf ("TRUE\n");
1568       Ptr++;
1569       SectionLength--;
1570       break;
1571
1572     case EFI_DEP_FALSE:
1573       printf ("FALSE\n");
1574       Ptr++;
1575       SectionLength--;
1576       break;
1577
1578     case EFI_DEP_END:
1579       printf ("END DEPEX\n");
1580       Ptr++;
1581       SectionLength--;
1582       break;
1583
1584     case EFI_DEP_SOR:
1585       printf ("SOR\n");
1586       Ptr++;
1587       SectionLength--;
1588       break;
1589
1590     default:
1591       printf ("Unrecognized byte in depex: 0x%X\n", *Ptr);
1592       return EFI_SUCCESS;
1593     }
1594   }
1595
1596   return EFI_SUCCESS;
1597 }
1598
1599 EFI_STATUS
1600 PrintGuidName (
1601   IN UINT8    *GuidStr
1602   )
1603 /*++
1604
1605 Routine Description:
1606
1607   GC_TODO: Add function description
1608
1609 Arguments:
1610
1611   GuidStr - GC_TODO: add argument description
1612
1613 Returns:
1614
1615   EFI_SUCCESS - GC_TODO: Add description for return value
1616   EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
1617
1618 --*/
1619 {
1620   GUID_TO_BASENAME  *GPtr;
1621   //
1622   // If we have a list of guid-to-basenames, then go through the list to
1623   // look for a guid string match. If found, print the basename to stdout,
1624   // otherwise return a failure.
1625   //
1626   GPtr = mGuidBaseNameList;
1627   while (GPtr != NULL) {
1628     if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) {
1629       printf ("%s", GPtr->BaseName);
1630       return EFI_SUCCESS;
1631     }
1632
1633     GPtr = GPtr->Next;
1634   }
1635
1636   return EFI_INVALID_PARAMETER;
1637 }
1638
1639 EFI_STATUS
1640 ParseGuidBaseNameFile (
1641   CHAR8    *FileName
1642   )
1643 /*++
1644
1645 Routine Description:
1646
1647   GC_TODO: Add function description
1648
1649 Arguments:
1650
1651   FileName  - GC_TODO: add argument description
1652
1653 Returns:
1654
1655   EFI_DEVICE_ERROR - GC_TODO: Add description for return value
1656   EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
1657   EFI_SUCCESS - GC_TODO: Add description for return value
1658
1659 --*/
1660 {
1661   FILE              *Fptr;
1662   CHAR8             Line[MAX_LINE_LEN];
1663   GUID_TO_BASENAME  *GPtr;
1664
1665   if ((Fptr = fopen (FileName, "r")) == NULL) {
1666     printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);
1667     return EFI_DEVICE_ERROR;
1668   }
1669
1670   while (fgets (Line, sizeof (Line), Fptr) != NULL) {
1671     //
1672     // Allocate space for another guid/basename element
1673     //
1674     GPtr = malloc (sizeof (GUID_TO_BASENAME));
1675     if (GPtr == NULL) {
1676       return EFI_OUT_OF_RESOURCES;
1677     }
1678
1679     memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));
1680     if (sscanf (Line, "%s %s", GPtr->Guid, GPtr->BaseName) == 2) {
1681       GPtr->Next        = mGuidBaseNameList;
1682       mGuidBaseNameList = GPtr;
1683     } else {
1684       //
1685       // Some sort of error. Just continue.
1686       //
1687       free (GPtr);
1688     }
1689   }
1690
1691   fclose (Fptr);
1692   return EFI_SUCCESS;
1693 }
1694
1695 EFI_STATUS
1696 FreeGuidBaseNameList (
1697   VOID
1698   )
1699 /*++
1700
1701 Routine Description:
1702
1703   GC_TODO: Add function description
1704
1705 Arguments:
1706
1707   None
1708
1709 Returns:
1710
1711   EFI_SUCCESS - GC_TODO: Add description for return value
1712
1713 --*/
1714 {
1715   GUID_TO_BASENAME  *Next;
1716
1717   while (mGuidBaseNameList != NULL) {
1718     Next = mGuidBaseNameList->Next;
1719     free (mGuidBaseNameList);
1720     mGuidBaseNameList = Next;
1721   }
1722
1723   return EFI_SUCCESS;
1724 }
1725
1726
1727 static
1728 VOID
1729 LoadGuidedSectionToolsTxt (
1730   IN CHAR8* FirmwareVolumeFilename
1731   )
1732 {
1733   CHAR8* PeerFilename;
1734   CHAR8* Places[] = {
1735     NULL,
1736     //NULL,
1737     };
1738   UINTN Index;
1739
1740   Places[0] = FirmwareVolumeFilename;
1741   //Places[1] = mUtilityFilename;
1742
1743   mParsedGuidedSectionTools = NULL;
1744
1745   for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) {
1746     PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt");
1747     //printf("Loading %s...\n", PeerFilename);
1748     if (OsPathExists (PeerFilename)) {
1749       mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename);
1750     }
1751     free (PeerFilename);
1752     if (mParsedGuidedSectionTools != NULL) {
1753       return;
1754     }
1755   }
1756 }
1757
1758
1759 void
1760 Usage (
1761   VOID
1762   )
1763 /*++
1764
1765 Routine Description:
1766
1767   GC_TODO: Add function description
1768
1769 Arguments:
1770
1771   None
1772
1773 Returns:
1774
1775   GC_TODO: add return values
1776
1777 --*/
1778 {
1779   //
1780   // Summary usage
1781   //
1782   fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME);
1783
1784   //
1785   // Copyright declaration
1786   // 
1787   fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
1788
1789   //
1790   // Details Option
1791   //
1792   fprintf (stdout, "Options:\n");
1793   fprintf (stdout, "  -x xref, --xref xref\n\
1794             Parse basename to file-guid cross reference file(s).\n");
1795   fprintf (stdout, "  --offset offset\n\
1796             Offset of file to start processing FV at.\n");
1797   fprintf (stdout, "  -h, --help\n\
1798             Show this help message and exit.\n");
1799
1800 }
1801