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