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