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