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