]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/VolInfo/VolInfo.c
BaseTools: Clean up source files
[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 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <assert.h>
20 #ifdef __GNUC__
21 #include <unistd.h>
22 #else
23 #include <direct.h>
24 #endif
25
26 #include <FvLib.h>
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/UefiCapsule.h>
29 #include <Common/PiFirmwareFile.h>
30 #include <Common/PiFirmwareVolume.h>
31 #include <Guid/PiFirmwareFileSystem.h>
32 #include <IndustryStandard/PeImage.h>
33 #include <Protocol/GuidedSectionExtraction.h>
34
35 #include "Compress.h"
36 #include "Decompress.h"
37 #include "VolInfo.h"
38 #include "CommonLib.h"
39 #include "EfiUtilityMsgs.h"
40 #include "FirmwareVolumeBufferLib.h"
41 #include "OsPath.h"
42 #include "ParseGuidedSectionTools.h"
43 #include "StringFuncs.h"
44 #include "ParseInf.h"
45 #include "PeCoffLib.h"
46
47 //
48 // Utility global variables
49 //
50
51 EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
52
53 #define UTILITY_MAJOR_VERSION 1
54 #define UTILITY_MINOR_VERSION 0
55
56 #define UTILITY_NAME "VolInfo"
57
58 #define EFI_SECTION_ERROR EFIERR (100)
59
60 #define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable
61
62 //
63 // Structure to keep a list of guid-to-basenames
64 //
65 typedef struct _GUID_TO_BASENAME {
66 struct _GUID_TO_BASENAME *Next;
67 INT8 Guid[PRINTED_GUID_BUFFER_SIZE];
68 INT8 BaseName[MAX_BASENAME_LEN];
69 } GUID_TO_BASENAME;
70
71 static GUID_TO_BASENAME *mGuidBaseNameList = NULL;
72
73 //
74 // Store GUIDed Section guid->tool mapping
75 //
76 EFI_HANDLE mParsedGuidedSectionTools = NULL;
77
78 CHAR8* mUtilityFilename = NULL;
79
80 BOOLEAN EnableHash = FALSE;
81 CHAR8 *OpenSslPath = NULL;
82
83 EFI_STATUS
84 ParseGuidBaseNameFile (
85 CHAR8 *FileName
86 );
87
88 EFI_STATUS
89 FreeGuidBaseNameList (
90 VOID
91 );
92
93 EFI_STATUS
94 PrintGuidName (
95 IN UINT8 *GuidStr
96 );
97
98 EFI_STATUS
99 ParseSection (
100 IN UINT8 *SectionBuffer,
101 IN UINT32 BufferLength
102 );
103
104 EFI_STATUS
105 DumpDepexSection (
106 IN UINT8 *Ptr,
107 IN UINT32 SectionLength
108 );
109
110 STATIC
111 EFI_STATUS
112 ReadHeader (
113 IN FILE *InputFile,
114 OUT UINT32 *FvSize,
115 OUT BOOLEAN *ErasePolarity
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
761 BytesRead = 0;
762 Size = 0;
763 //
764 // Check input parameters
765 //
766 if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) {
767 Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function");
768 return EFI_INVALID_PARAMETER;
769 }
770 //
771 // Read the header
772 //
773 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
774 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
775 Signature[0] = VolumeHeader.Signature;
776 Signature[1] = 0;
777
778 //
779 // Print FV header information
780 //
781 printf ("Signature: %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature);
782 printf ("Attributes: %X\n", (unsigned) VolumeHeader.Attributes);
783
784 if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) {
785 printf (" EFI_FVB2_READ_DISABLED_CAP\n");
786 }
787
788 if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) {
789 printf (" EFI_FVB2_READ_ENABLED_CAP\n");
790 }
791
792 if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) {
793 printf (" EFI_FVB2_READ_STATUS\n");
794 }
795
796 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) {
797 printf (" EFI_FVB2_WRITE_DISABLED_CAP\n");
798 }
799
800 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) {
801 printf (" EFI_FVB2_WRITE_ENABLED_CAP\n");
802 }
803
804 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) {
805 printf (" EFI_FVB2_WRITE_STATUS\n");
806 }
807
808 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) {
809 printf (" EFI_FVB2_LOCK_CAP\n");
810 }
811
812 if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) {
813 printf (" EFI_FVB2_LOCK_STATUS\n");
814 }
815
816 if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) {
817 printf (" EFI_FVB2_STICKY_WRITE\n");
818 }
819
820 if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) {
821 printf (" EFI_FVB2_MEMORY_MAPPED\n");
822 }
823
824 if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) {
825 printf (" EFI_FVB2_ERASE_POLARITY\n");
826 *ErasePolarity = TRUE;
827 }
828
829 #if (PI_SPECIFICATION_VERSION < 0x00010000)
830 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) {
831 printf (" EFI_FVB2_ALIGNMENT\n");
832 }
833
834 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {
835 printf (" EFI_FVB2_ALIGNMENT_2\n");
836 }
837
838 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {
839 printf (" EFI_FVB2_ALIGNMENT_4\n");
840 }
841
842 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {
843 printf (" EFI_FVB2_ALIGNMENT_8\n");
844 }
845
846 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {
847 printf (" EFI_FVB2_ALIGNMENT_16\n");
848 }
849
850 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {
851 printf (" EFI_FVB2_ALIGNMENT_32\n");
852 }
853
854 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {
855 printf (" EFI_FVB2_ALIGNMENT_64\n");
856 }
857
858 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {
859 printf (" EFI_FVB2_ALIGNMENT_128\n");
860 }
861
862 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {
863 printf (" EFI_FVB2_ALIGNMENT_256\n");
864 }
865
866 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {
867 printf (" EFI_FVB2_ALIGNMENT_512\n");
868 }
869
870 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {
871 printf (" EFI_FVB2_ALIGNMENT_1K\n");
872 }
873
874 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {
875 printf (" EFI_FVB2_ALIGNMENT_2K\n");
876 }
877
878 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {
879 printf (" EFI_FVB2_ALIGNMENT_4K\n");
880 }
881
882 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {
883 printf (" EFI_FVB2_ALIGNMENT_8K\n");
884 }
885
886 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {
887 printf (" EFI_FVB2_ALIGNMENT_16K\n");
888 }
889
890 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {
891 printf (" EFI_FVB2_ALIGNMENT_32K\n");
892 }
893
894 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {
895 printf (" EFI_FVB2_ALIGNMENT_64K\n");
896 }
897
898 #else
899
900 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) {
901 printf (" EFI_FVB2_READ_LOCK_CAP\n");
902 }
903
904 if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) {
905 printf (" EFI_FVB2_READ_LOCK_STATUS\n");
906 }
907
908 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) {
909 printf (" EFI_FVB2_WRITE_LOCK_CAP\n");
910 }
911
912 if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) {
913 printf (" EFI_FVB2_WRITE_LOCK_STATUS\n");
914 }
915
916 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) {
917 printf (" EFI_FVB2_ALIGNMENT_1\n");
918 }
919
920 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) {
921 printf (" EFI_FVB2_ALIGNMENT_2\n");
922 }
923
924 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) {
925 printf (" EFI_FVB2_ALIGNMENT_4\n");
926 }
927
928 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) {
929 printf (" EFI_FVB2_ALIGNMENT_8\n");
930 }
931
932 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) {
933 printf (" EFI_FVB2_ALIGNMENT_16\n");
934 }
935
936 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) {
937 printf (" EFI_FVB2_ALIGNMENT_32\n");
938 }
939
940 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) {
941 printf (" EFI_FVB2_ALIGNMENT_64\n");
942 }
943
944 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) {
945 printf (" EFI_FVB2_ALIGNMENT_128\n");
946 }
947
948 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) {
949 printf (" EFI_FVB2_ALIGNMENT_256\n");
950 }
951
952 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) {
953 printf (" EFI_FVB2_ALIGNMENT_512\n");
954 }
955
956 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) {
957 printf (" EFI_FVB2_ALIGNMENT_1K\n");
958 }
959
960 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) {
961 printf (" EFI_FVB2_ALIGNMENT_2K\n");
962 }
963
964 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) {
965 printf (" EFI_FVB2_ALIGNMENT_4K\n");
966 }
967
968 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) {
969 printf (" EFI_FVB2_ALIGNMENT_8K\n");
970 }
971
972 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) {
973 printf (" EFI_FVB2_ALIGNMENT_16K\n");
974 }
975
976 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) {
977 printf (" EFI_FVB2_ALIGNMENT_32K\n");
978 }
979
980 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) {
981 printf (" EFI_FVB2_ALIGNMENT_64K\n");
982 }
983
984 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) {
985 printf (" EFI_FVB2_ALIGNMENT_128K\n");
986 }
987
988 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) {
989 printf (" EFI_FVB2_ALIGNMENT_256K\n");
990 }
991
992 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) {
993 printf (" EFI_FVB2_ALIGNMENT_512K\n");
994 }
995
996 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) {
997 printf (" EFI_FVB2_ALIGNMENT_1M\n");
998 }
999
1000 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) {
1001 printf (" EFI_FVB2_ALIGNMENT_2M\n");
1002 }
1003
1004 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) {
1005 printf (" EFI_FVB2_ALIGNMENT_4M\n");
1006 }
1007
1008 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) {
1009 printf (" EFI_FVB2_ALIGNMENT_8M\n");
1010 }
1011
1012 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) {
1013 printf (" EFI_FVB2_ALIGNMENT_16M\n");
1014 }
1015
1016 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) {
1017 printf (" EFI_FVB2_ALIGNMENT_32M\n");
1018 }
1019
1020 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {
1021 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1022 }
1023
1024 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {
1025 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1026 }
1027
1028 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) {
1029 printf (" EFI_FVB2_ALIGNMENT_64M\n");
1030 }
1031
1032 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) {
1033 printf (" EFI_FVB2_ALIGNMENT_128M\n");
1034 }
1035
1036 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) {
1037 printf (" EFI_FVB2_ALIGNMENT_256M\n");
1038 }
1039
1040 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) {
1041 printf (" EFI_FVB2_ALIGNMENT_512M\n");
1042 }
1043
1044 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) {
1045 printf (" EFI_FVB2_ALIGNMENT_1G\n");
1046 }
1047
1048 if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) {
1049 printf (" EFI_FVB2_ALIGNMENT_2G\n");
1050 }
1051
1052 #endif
1053 printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength);
1054 printf ("File System ID: ");
1055 PrintGuid (&VolumeHeader.FileSystemGuid);
1056 //
1057 // printf ("\n");
1058 //
1059 printf ("Revision: 0x%04X\n", VolumeHeader.Revision);
1060
1061 do {
1062 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
1063 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
1064
1065 if (BlockMap.NumBlocks != 0) {
1066 printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap.NumBlocks);
1067 printf ("Block Length: 0x%08X\n", (unsigned) BlockMap.Length);
1068 Size += BlockMap.NumBlocks * BlockMap.Length;
1069 }
1070
1071 } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0));
1072
1073 if (BytesRead != VolumeHeader.HeaderLength) {
1074 printf ("ERROR: Header length not consistent with Block Maps!\n");
1075 return EFI_ABORTED;
1076 }
1077
1078 if (VolumeHeader.FvLength != Size) {
1079 printf ("ERROR: Volume Size not consistant with Block Maps!\n");
1080 return EFI_ABORTED;
1081 }
1082
1083 printf ("Total Volume Size: 0x%08X\n", (unsigned) Size);
1084
1085 *FvSize = Size;
1086
1087 //
1088 // rewind (InputFile);
1089 //
1090 return EFI_SUCCESS;
1091 }
1092
1093 STATIC
1094 EFI_STATUS
1095 PrintFileInfo (
1096 EFI_FIRMWARE_VOLUME_HEADER *FvImage,
1097 EFI_FFS_FILE_HEADER *FileHeader,
1098 BOOLEAN ErasePolarity
1099 )
1100 /*++
1101
1102 Routine Description:
1103
1104 GC_TODO: Add function description
1105
1106 Arguments:
1107
1108 FvImage - GC_TODO: add argument description
1109 FileHeader - GC_TODO: add argument description
1110 ErasePolarity - GC_TODO: add argument description
1111
1112 Returns:
1113
1114 EFI_SUCCESS - GC_TODO: Add description for return value
1115 EFI_ABORTED - GC_TODO: Add description for return value
1116
1117 --*/
1118 {
1119 UINT32 FileLength;
1120 UINT8 FileState;
1121 UINT8 Checksum;
1122 EFI_FFS_FILE_HEADER2 BlankHeader;
1123 EFI_STATUS Status;
1124 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
1125 UINT32 HeaderSize;
1126 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1127 UINT16 *Tail;
1128 #endif
1129 //
1130 // Check if we have free space
1131 //
1132 HeaderSize = FvBufGetFfsHeaderSize(FileHeader);
1133 if (ErasePolarity) {
1134 memset (&BlankHeader, -1, HeaderSize);
1135 } else {
1136 memset (&BlankHeader, 0, HeaderSize);
1137 }
1138
1139 if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) {
1140 return EFI_SUCCESS;
1141 }
1142 //
1143 // Print file information.
1144 //
1145 printf ("============================================================\n");
1146
1147 printf ("File Name: ");
1148 PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE);
1149 printf ("%s ", GuidBuffer);
1150 PrintGuidName (GuidBuffer);
1151 printf ("\n");
1152
1153 //
1154 // PrintGuid (&FileHeader->Name);
1155 // printf ("\n");
1156 //
1157 FileLength = FvBufGetFfsFileSize (FileHeader);
1158 printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage));
1159 printf ("File Length: 0x%08X\n", (unsigned) FileLength);
1160 printf ("File Attributes: 0x%02X\n", FileHeader->Attributes);
1161 printf ("File State: 0x%02X\n", FileHeader->State);
1162
1163 //
1164 // Print file state
1165 //
1166 FileState = GetFileState (ErasePolarity, FileHeader);
1167
1168 switch (FileState) {
1169
1170 case EFI_FILE_HEADER_CONSTRUCTION:
1171 printf (" EFI_FILE_HEADER_CONSTRUCTION\n");
1172 return EFI_SUCCESS;
1173
1174 case EFI_FILE_HEADER_INVALID:
1175 printf (" EFI_FILE_HEADER_INVALID\n");
1176 return EFI_SUCCESS;
1177
1178 case EFI_FILE_HEADER_VALID:
1179 printf (" EFI_FILE_HEADER_VALID\n");
1180 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);
1181 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
1182 Checksum = (UINT8) (Checksum - FileHeader->State);
1183 if (Checksum != 0) {
1184 printf ("ERROR: Header checksum invalid.\n");
1185 return EFI_ABORTED;
1186 }
1187
1188 return EFI_SUCCESS;
1189
1190 case EFI_FILE_DELETED:
1191 printf (" EFI_FILE_DELETED\n");
1192
1193 case EFI_FILE_MARKED_FOR_UPDATE:
1194 printf (" EFI_FILE_MARKED_FOR_UPDATE\n");
1195
1196 case EFI_FILE_DATA_VALID:
1197 printf (" EFI_FILE_DATA_VALID\n");
1198
1199 //
1200 // Calculate header checksum
1201 //
1202 Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize);
1203 Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File);
1204 Checksum = (UINT8) (Checksum - FileHeader->State);
1205 if (Checksum != 0) {
1206 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer);
1207 return EFI_ABORTED;
1208 }
1209
1210 FileLength = FvBufGetFfsFileSize (FileHeader);
1211
1212 if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) {
1213 //
1214 // Calculate file checksum
1215 //
1216 Checksum = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize);
1217 Checksum = Checksum + FileHeader->IntegrityCheck.Checksum.File;
1218 if (Checksum != 0) {
1219 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer);
1220 return EFI_ABORTED;
1221 }
1222 } else {
1223 if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) {
1224 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);
1225 return EFI_ABORTED;
1226 }
1227 }
1228 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1229 //
1230 // Verify tail if present
1231 //
1232 if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1233 //
1234 // Verify tail is complement of integrity check field in the header.
1235 //
1236 Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK));
1237 if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) {
1238 Error (NULL, 0, 0003, "error parsing FFS file", \
1239 "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer);
1240 return EFI_ABORTED;
1241 }
1242 }
1243 #endif
1244 break;
1245
1246 default:
1247 Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer);
1248 return EFI_ABORTED;
1249 }
1250
1251 printf ("File Type: 0x%02X ", FileHeader->Type);
1252
1253 switch (FileHeader->Type) {
1254
1255 case EFI_FV_FILETYPE_RAW:
1256 printf ("EFI_FV_FILETYPE_RAW\n");
1257 break;
1258
1259 case EFI_FV_FILETYPE_FREEFORM:
1260 printf ("EFI_FV_FILETYPE_FREEFORM\n");
1261 break;
1262
1263 case EFI_FV_FILETYPE_SECURITY_CORE:
1264 printf ("EFI_FV_FILETYPE_SECURITY_CORE\n");
1265 break;
1266
1267 case EFI_FV_FILETYPE_PEI_CORE:
1268 printf ("EFI_FV_FILETYPE_PEI_CORE\n");
1269 break;
1270
1271 case EFI_FV_FILETYPE_DXE_CORE:
1272 printf ("EFI_FV_FILETYPE_DXE_CORE\n");
1273 break;
1274
1275 case EFI_FV_FILETYPE_PEIM:
1276 printf ("EFI_FV_FILETYPE_PEIM\n");
1277 break;
1278
1279 case EFI_FV_FILETYPE_DRIVER:
1280 printf ("EFI_FV_FILETYPE_DRIVER\n");
1281 break;
1282
1283 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
1284 printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n");
1285 break;
1286
1287 case EFI_FV_FILETYPE_APPLICATION:
1288 printf ("EFI_FV_FILETYPE_APPLICATION\n");
1289 break;
1290
1291 case EFI_FV_FILETYPE_SMM:
1292 printf ("EFI_FV_FILETYPE_SMM\n");
1293 break;
1294
1295 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
1296 printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n");
1297 break;
1298
1299 case EFI_FV_FILETYPE_COMBINED_SMM_DXE:
1300 printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n");
1301 break;
1302
1303 case EFI_FV_FILETYPE_SMM_CORE:
1304 printf ("EFI_FV_FILETYPE_SMM_CORE\n");
1305 break;
1306
1307 case EFI_FV_FILETYPE_MM_STANDALONE:
1308 printf ("EFI_FV_FILETYPE_MM_STANDALONE\n");
1309 break;
1310
1311 case EFI_FV_FILETYPE_MM_CORE_STANDALONE:
1312 printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n");
1313 break;
1314
1315 case EFI_FV_FILETYPE_FFS_PAD:
1316 printf ("EFI_FV_FILETYPE_FFS_PAD\n");
1317 break;
1318
1319 default:
1320 printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type);
1321 return EFI_ABORTED;
1322 break;
1323 }
1324
1325 switch (FileHeader->Type) {
1326
1327 case EFI_FV_FILETYPE_ALL:
1328 case EFI_FV_FILETYPE_RAW:
1329 case EFI_FV_FILETYPE_FFS_PAD:
1330 break;
1331
1332 default:
1333 //
1334 // All other files have sections
1335 //
1336 Status = ParseSection (
1337 (UINT8 *) ((UINTN) FileHeader + HeaderSize),
1338 FvBufGetFfsFileSize (FileHeader) - HeaderSize
1339 );
1340 if (EFI_ERROR (Status)) {
1341 //
1342 // printf ("ERROR: Parsing the FFS file.\n");
1343 //
1344 return EFI_ABORTED;
1345 }
1346 break;
1347 }
1348
1349 return EFI_SUCCESS;
1350 }
1351
1352 EFI_STATUS
1353 RebaseImageRead (
1354 IN VOID *FileHandle,
1355 IN UINTN FileOffset,
1356 IN OUT UINT32 *ReadSize,
1357 OUT VOID *Buffer
1358 )
1359 /*++
1360
1361 Routine Description:
1362
1363 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1364
1365 Arguments:
1366
1367 FileHandle - The handle to the PE/COFF file
1368
1369 FileOffset - The offset, in bytes, into the file to read
1370
1371 ReadSize - The number of bytes to read from the file starting at FileOffset
1372
1373 Buffer - A pointer to the buffer to read the data into.
1374
1375 Returns:
1376
1377 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1378
1379 --*/
1380 {
1381 CHAR8 *Destination8;
1382 CHAR8 *Source8;
1383 UINT32 Length;
1384
1385 Destination8 = Buffer;
1386 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1387 Length = *ReadSize;
1388 while (Length--) {
1389 *(Destination8++) = *(Source8++);
1390 }
1391
1392 return EFI_SUCCESS;
1393 }
1394
1395 EFI_STATUS
1396 SetAddressToSectionHeader (
1397 IN CHAR8 *FileName,
1398 IN OUT UINT8 *FileBuffer,
1399 IN UINT64 NewPe32BaseAddress
1400 )
1401 /*++
1402
1403 Routine Description:
1404
1405 Set new base address into the section header of PeImage
1406
1407 Arguments:
1408
1409 FileName - Name of file
1410 FileBuffer - Pointer to PeImage.
1411 NewPe32BaseAddress - New Base Address for PE image.
1412
1413 Returns:
1414
1415 EFI_SUCCESS Set new base address into this image successfully.
1416
1417 --*/
1418 {
1419 EFI_STATUS Status;
1420 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1421 UINTN Index;
1422 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
1423 EFI_IMAGE_SECTION_HEADER *SectionHeader;
1424
1425 //
1426 // Initialize context
1427 //
1428 memset (&ImageContext, 0, sizeof (ImageContext));
1429 ImageContext.Handle = (VOID *) FileBuffer;
1430 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
1431 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1432 if (EFI_ERROR (Status)) {
1433 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
1434 return Status;
1435 }
1436
1437 if (ImageContext.RelocationsStripped) {
1438 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
1439 return Status;
1440 }
1441
1442 //
1443 // Get PeHeader pointer
1444 //
1445 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
1446
1447 //
1448 // Get section header list
1449 //
1450 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
1451 (UINTN) ImgHdr +
1452 sizeof (UINT32) +
1453 sizeof (EFI_IMAGE_FILE_HEADER) +
1454 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
1455 );
1456
1457 //
1458 // Set base address into the first section header that doesn't point to code section.
1459 //
1460 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
1461 if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
1462 *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
1463 break;
1464 }
1465 }
1466
1467 //
1468 // BaseAddress is set to section header.
1469 //
1470 return EFI_SUCCESS;
1471 }
1472
1473 EFI_STATUS
1474 RebaseImage (
1475 IN CHAR8 *FileName,
1476 IN OUT UINT8 *FileBuffer,
1477 IN UINT64 NewPe32BaseAddress
1478 )
1479 /*++
1480
1481 Routine Description:
1482
1483 Set new base address into PeImage, and fix up PeImage based on new address.
1484
1485 Arguments:
1486
1487 FileName - Name of file
1488 FileBuffer - Pointer to PeImage.
1489 NewPe32BaseAddress - New Base Address for PE image.
1490
1491 Returns:
1492
1493 EFI_INVALID_PARAMETER - BaseAddress is not valid.
1494 EFI_SUCCESS - Update PeImage is correctly.
1495
1496 --*/
1497 {
1498 EFI_STATUS Status;
1499 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
1500 UINTN Index;
1501 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
1502 UINT8 *MemoryImagePointer;
1503 EFI_IMAGE_SECTION_HEADER *SectionHeader;
1504
1505 //
1506 // Initialize context
1507 //
1508 memset (&ImageContext, 0, sizeof (ImageContext));
1509 ImageContext.Handle = (VOID *) FileBuffer;
1510 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
1511 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1512 if (EFI_ERROR (Status)) {
1513 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
1514 return Status;
1515 }
1516
1517 if (ImageContext.RelocationsStripped) {
1518 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
1519 return Status;
1520 }
1521
1522 //
1523 // Get PeHeader pointer
1524 //
1525 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
1526
1527 //
1528 // Load and Relocate Image Data
1529 //
1530 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
1531 if (MemoryImagePointer == NULL) {
1532 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
1533 return EFI_OUT_OF_RESOURCES;
1534 }
1535 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
1536 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
1537
1538 Status = PeCoffLoaderLoadImage (&ImageContext);
1539 if (EFI_ERROR (Status)) {
1540 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
1541 free ((VOID *) MemoryImagePointer);
1542 return Status;
1543 }
1544
1545 ImageContext.DestinationAddress = NewPe32BaseAddress;
1546 Status = PeCoffLoaderRelocateImage (&ImageContext);
1547 if (EFI_ERROR (Status)) {
1548 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
1549 free ((VOID *) MemoryImagePointer);
1550 return Status;
1551 }
1552
1553 //
1554 // Copy Relocated data to raw image file.
1555 //
1556 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
1557 (UINTN) ImgHdr +
1558 sizeof (UINT32) +
1559 sizeof (EFI_IMAGE_FILE_HEADER) +
1560 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
1561 );
1562
1563 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
1564 CopyMem (
1565 FileBuffer + SectionHeader->PointerToRawData,
1566 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
1567 SectionHeader->SizeOfRawData
1568 );
1569 }
1570
1571 free ((VOID *) MemoryImagePointer);
1572
1573 //
1574 // Update Image Base Address
1575 //
1576 if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {
1577 ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
1578 } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
1579 ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
1580 } else {
1581 Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
1582 ImgHdr->Pe32.OptionalHeader.Magic,
1583 FileName
1584 );
1585 return EFI_ABORTED;
1586 }
1587
1588 //
1589 // Set new base address into section header
1590 //
1591 Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
1592
1593 return Status;
1594 }
1595
1596 EFI_STATUS
1597 CombinePath (
1598 IN CHAR8* DefaultPath,
1599 IN CHAR8* AppendPath,
1600 OUT CHAR8* NewPath
1601 )
1602 {
1603 UINT32 DefaultPathLen;
1604 UINT64 Index;
1605 CHAR8 QuotesStr[] = "\"";
1606 strcpy(NewPath, QuotesStr);
1607 DefaultPathLen = strlen(DefaultPath);
1608 strcat(NewPath, DefaultPath);
1609 Index = 0;
1610 for (; Index < DefaultPathLen + 1; Index ++) {
1611 if (NewPath[Index] == '\\' || NewPath[Index] == '/') {
1612 if (NewPath[Index + 1] != '\0') {
1613 NewPath[Index] = '/';
1614 }
1615 }
1616 }
1617 if (NewPath[Index -1] != '/') {
1618 NewPath[Index] = '/';
1619 NewPath[Index + 1] = '\0';
1620 }
1621 strcat(NewPath, AppendPath);
1622 strcat(NewPath, QuotesStr);
1623 return EFI_SUCCESS;
1624 }
1625
1626 EFI_STATUS
1627 ParseSection (
1628 IN UINT8 *SectionBuffer,
1629 IN UINT32 BufferLength
1630 )
1631 /*++
1632
1633 Routine Description:
1634
1635 Parses EFI Sections
1636
1637 Arguments:
1638
1639 SectionBuffer - Buffer containing the section to parse.
1640 BufferLength - Length of SectionBuffer
1641
1642 Returns:
1643
1644 EFI_SECTION_ERROR - Problem with section parsing.
1645 (a) compression errors
1646 (b) unrecognized section
1647 EFI_UNSUPPORTED - Do not know how to parse the section.
1648 EFI_SUCCESS - Section successfully parsed.
1649 EFI_OUT_OF_RESOURCES - Memory allocation failed.
1650
1651 --*/
1652 {
1653 EFI_SECTION_TYPE Type;
1654 UINT8 *Ptr;
1655 UINT32 SectionLength;
1656 UINT32 SectionHeaderLen;
1657 CHAR8 *SectionName;
1658 EFI_STATUS Status;
1659 UINT32 ParsedLength;
1660 UINT8 *CompressedBuffer;
1661 UINT32 CompressedLength;
1662 UINT8 *UncompressedBuffer;
1663 UINT32 UncompressedLength;
1664 UINT8 *ToolOutputBuffer;
1665 UINT32 ToolOutputLength;
1666 UINT8 CompressionType;
1667 UINT32 DstSize;
1668 UINT32 ScratchSize;
1669 UINT8 *ScratchBuffer;
1670 DECOMPRESS_FUNCTION DecompressFunction;
1671 GETINFO_FUNCTION GetInfoFunction;
1672 // CHAR16 *name;
1673 CHAR8 *ExtractionTool;
1674 CHAR8 *ToolInputFile;
1675 CHAR8 *ToolOutputFile;
1676 CHAR8 *SystemCommand;
1677 EFI_GUID *EfiGuid;
1678 UINT16 DataOffset;
1679 UINT16 Attributes;
1680 UINT32 RealHdrLen;
1681 CHAR8 *ToolInputFileName;
1682 CHAR8 *ToolOutputFileName;
1683 CHAR8 *UIFileName;
1684
1685 ParsedLength = 0;
1686 ToolInputFileName = NULL;
1687 ToolOutputFileName = NULL;
1688
1689 while (ParsedLength < BufferLength) {
1690 Ptr = SectionBuffer + ParsedLength;
1691
1692 SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size);
1693 Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type;
1694
1695 //
1696 // This is sort of an odd check, but is necessary because FFS files are
1697 // padded to a QWORD boundary, meaning there is potentially a whole section
1698 // header worth of 0xFF bytes.
1699 //
1700 if (SectionLength == 0xffffff && Type == 0xff) {
1701 ParsedLength += 4;
1702 continue;
1703 }
1704
1705 //
1706 // Get real section file size
1707 //
1708 SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr);
1709 SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
1710
1711 SectionName = SectionNameToStr (Type);
1712 if (SectionName != NULL) {
1713 printf ("------------------------------------------------------------\n");
1714 printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength);
1715 free (SectionName);
1716 }
1717
1718 switch (Type) {
1719 case EFI_SECTION_RAW:
1720 case EFI_SECTION_PIC:
1721 case EFI_SECTION_TE:
1722 // default is no more information
1723 break;
1724
1725 case EFI_SECTION_PE32:
1726 if (EnableHash) {
1727 ToolInputFileName = "edk2Temp_InputEfi.tmp";
1728 ToolOutputFileName = "edk2Temp_OutputHash.tmp";
1729 RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0);
1730 PutFileImage (
1731 ToolInputFileName,
1732 (CHAR8*)Ptr + SectionHeaderLen,
1733 SectionLength - SectionHeaderLen
1734 );
1735
1736 SystemCommand = malloc (
1737 strlen (OPENSSL_COMMAND_FORMAT_STRING) +
1738 strlen (OpenSslPath) +
1739 strlen (ToolInputFileName) +
1740 strlen (ToolOutputFileName) +
1741 1
1742 );
1743 if (SystemCommand == NULL) {
1744 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1745 return EFI_OUT_OF_RESOURCES;
1746 }
1747 sprintf (
1748 SystemCommand,
1749 OPENSSL_COMMAND_FORMAT_STRING,
1750 OpenSslPath,
1751 ToolOutputFileName,
1752 ToolInputFileName
1753 );
1754
1755 if (system (SystemCommand) != EFI_SUCCESS) {
1756 Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL);
1757 }
1758 else {
1759 FILE *fp;
1760 CHAR8 *StrLine;
1761 CHAR8 *NewStr;
1762 UINT32 nFileLen;
1763 if((fp = fopen(ToolOutputFileName,"r")) == NULL) {
1764 Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL);
1765 }
1766 else {
1767 fseek(fp,0,SEEK_SET);
1768 fseek(fp,0,SEEK_END);
1769 nFileLen = ftell(fp);
1770 fseek(fp,0,SEEK_SET);
1771 StrLine = malloc(nFileLen);
1772 if (StrLine == NULL) {
1773 fclose(fp);
1774 free (SystemCommand);
1775 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1776 return EFI_OUT_OF_RESOURCES;
1777 }
1778 fgets(StrLine, nFileLen, fp);
1779 NewStr = strrchr (StrLine, '=');
1780 printf (" SHA1: %s\n", NewStr + 1);
1781 free (StrLine);
1782 fclose(fp);
1783 }
1784 }
1785 remove(ToolInputFileName);
1786 remove(ToolOutputFileName);
1787 free (SystemCommand);
1788 }
1789 break;
1790
1791 case EFI_SECTION_USER_INTERFACE:
1792 UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1);
1793 if (UIFileName == NULL) {
1794 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1795 return EFI_OUT_OF_RESOURCES;
1796 }
1797 Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName);
1798 printf (" String: %s\n", UIFileName);
1799 free (UIFileName);
1800 break;
1801
1802 case EFI_SECTION_FIRMWARE_VOLUME_IMAGE:
1803 Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE);
1804 if (EFI_ERROR (Status)) {
1805 Error (NULL, 0, 0003, "printing of FV section contents failed", NULL);
1806 return EFI_SECTION_ERROR;
1807 }
1808 break;
1809
1810 case EFI_SECTION_COMPATIBILITY16:
1811 case EFI_SECTION_FREEFORM_SUBTYPE_GUID:
1812 //
1813 // Section does not contain any further header information.
1814 //
1815 break;
1816
1817 case EFI_SECTION_PEI_DEPEX:
1818 case EFI_SECTION_DXE_DEPEX:
1819 case EFI_SECTION_SMM_DEPEX:
1820 DumpDepexSection (Ptr, SectionLength);
1821 break;
1822
1823 case EFI_SECTION_VERSION:
1824 printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen));
1825 printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16)));
1826 break;
1827
1828 case EFI_SECTION_COMPRESSION:
1829 UncompressedBuffer = NULL;
1830 if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) {
1831 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION);
1832 UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength;
1833 CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType;
1834 } else {
1835 RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2);
1836 UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength;
1837 CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType;
1838 }
1839 CompressedLength = SectionLength - RealHdrLen;
1840 printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength);
1841
1842 if (CompressionType == EFI_NOT_COMPRESSED) {
1843 printf (" Compression Type: EFI_NOT_COMPRESSED\n");
1844 if (CompressedLength != UncompressedLength) {
1845 Error (
1846 NULL,
1847 0,
1848 0,
1849 "file is not compressed, but the compressed length does not match the uncompressed length",
1850 NULL
1851 );
1852 return EFI_SECTION_ERROR;
1853 }
1854
1855 UncompressedBuffer = Ptr + RealHdrLen;
1856 } else if (CompressionType == EFI_STANDARD_COMPRESSION) {
1857 GetInfoFunction = EfiGetInfo;
1858 DecompressFunction = EfiDecompress;
1859 printf (" Compression Type: EFI_STANDARD_COMPRESSION\n");
1860
1861 CompressedBuffer = Ptr + RealHdrLen;
1862
1863 Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize);
1864 if (EFI_ERROR (Status)) {
1865 Error (NULL, 0, 0003, "error getting compression info from compression section", NULL);
1866 return EFI_SECTION_ERROR;
1867 }
1868
1869 if (DstSize != UncompressedLength) {
1870 Error (NULL, 0, 0003, "compression error in the compression section", NULL);
1871 return EFI_SECTION_ERROR;
1872 }
1873
1874 ScratchBuffer = malloc (ScratchSize);
1875 if (ScratchBuffer == NULL) {
1876 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1877 return EFI_OUT_OF_RESOURCES;
1878 }
1879 UncompressedBuffer = malloc (UncompressedLength);
1880 if (UncompressedBuffer == NULL) {
1881 free (ScratchBuffer);
1882 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1883 return EFI_OUT_OF_RESOURCES;
1884 }
1885 Status = DecompressFunction (
1886 CompressedBuffer,
1887 CompressedLength,
1888 UncompressedBuffer,
1889 UncompressedLength,
1890 ScratchBuffer,
1891 ScratchSize
1892 );
1893 free (ScratchBuffer);
1894 if (EFI_ERROR (Status)) {
1895 Error (NULL, 0, 0003, "decompress failed", NULL);
1896 free (UncompressedBuffer);
1897 return EFI_SECTION_ERROR;
1898 }
1899 } else {
1900 Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType);
1901 return EFI_SECTION_ERROR;
1902 }
1903
1904 Status = ParseSection (UncompressedBuffer, UncompressedLength);
1905
1906 if (CompressionType == EFI_STANDARD_COMPRESSION) {
1907 //
1908 // We need to deallocate Buffer
1909 //
1910 free (UncompressedBuffer);
1911 }
1912
1913 if (EFI_ERROR (Status)) {
1914 Error (NULL, 0, 0003, "failed to parse section", NULL);
1915 return EFI_SECTION_ERROR;
1916 }
1917 break;
1918
1919 case EFI_SECTION_GUID_DEFINED:
1920 if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) {
1921 EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid;
1922 DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset;
1923 Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes;
1924 } else {
1925 EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid;
1926 DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset;
1927 Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes;
1928 }
1929 printf (" SectionDefinitionGuid: ");
1930 PrintGuid (EfiGuid);
1931 printf ("\n");
1932 printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset);
1933 printf (" Attributes: 0x%04X\n", (unsigned) Attributes);
1934
1935 ExtractionTool =
1936 LookupGuidedSectionToolPath (
1937 mParsedGuidedSectionTools,
1938 EfiGuid
1939 );
1940
1941 if (ExtractionTool != NULL) {
1942 #ifndef __GNUC__
1943 ToolInputFile = CloneString (tmpnam (NULL));
1944 ToolOutputFile = CloneString (tmpnam (NULL));
1945 #else
1946 char tmp1[] = "/tmp/fileXXXXXX";
1947 char tmp2[] = "/tmp/fileXXXXXX";
1948 int fd1;
1949 int fd2;
1950 fd1 = mkstemp(tmp1);
1951 fd2 = mkstemp(tmp2);
1952 ToolInputFile = CloneString(tmp1);
1953 ToolOutputFile = CloneString(tmp2);
1954 close(fd1);
1955 close(fd2);
1956 #endif
1957
1958 if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) {
1959 if (ToolInputFile != NULL) {
1960 free (ToolInputFile);
1961 }
1962 if (ToolOutputFile != NULL) {
1963 free (ToolOutputFile);
1964 }
1965 free (ExtractionTool);
1966
1967 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1968 return EFI_OUT_OF_RESOURCES;
1969 }
1970
1971 //
1972 // Construction 'system' command string
1973 //
1974 SystemCommand = malloc (
1975 strlen (EXTRACT_COMMAND_FORMAT_STRING) +
1976 strlen (ExtractionTool) +
1977 strlen (ToolInputFile) +
1978 strlen (ToolOutputFile) +
1979 1
1980 );
1981 if (SystemCommand == NULL) {
1982 free (ToolInputFile);
1983 free (ToolOutputFile);
1984 free (ExtractionTool);
1985
1986 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1987 return EFI_OUT_OF_RESOURCES;
1988 }
1989 sprintf (
1990 SystemCommand,
1991 EXTRACT_COMMAND_FORMAT_STRING,
1992 ExtractionTool,
1993 ToolOutputFile,
1994 ToolInputFile
1995 );
1996 free (ExtractionTool);
1997
1998 Status =
1999 PutFileImage (
2000 ToolInputFile,
2001 (CHAR8*) SectionBuffer + DataOffset,
2002 BufferLength - DataOffset
2003 );
2004
2005 system (SystemCommand);
2006 remove (ToolInputFile);
2007 free (ToolInputFile);
2008
2009 Status =
2010 GetFileImage (
2011 ToolOutputFile,
2012 (CHAR8 **)&ToolOutputBuffer,
2013 &ToolOutputLength
2014 );
2015 remove (ToolOutputFile);
2016 free (ToolOutputFile);
2017 free (SystemCommand);
2018 if (EFI_ERROR (Status)) {
2019 Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL);
2020 return EFI_SECTION_ERROR;
2021 }
2022
2023 Status = ParseSection (
2024 ToolOutputBuffer,
2025 ToolOutputLength
2026 );
2027 if (EFI_ERROR (Status)) {
2028 Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL);
2029 return EFI_SECTION_ERROR;
2030 }
2031
2032 //
2033 // Check for CRC32 sections which we can handle internally if needed.
2034 //
2035 } else if (!CompareGuid (
2036 EfiGuid,
2037 &gEfiCrc32GuidedSectionExtractionProtocolGuid
2038 )
2039 ) {
2040 //
2041 // CRC32 guided section
2042 //
2043 Status = ParseSection (
2044 SectionBuffer + DataOffset,
2045 BufferLength - DataOffset
2046 );
2047 if (EFI_ERROR (Status)) {
2048 Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL);
2049 return EFI_SECTION_ERROR;
2050 }
2051 } else {
2052 //
2053 // We don't know how to parse it now.
2054 //
2055 Error (NULL, 0, 0003, "Error parsing section", \
2056 "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).");
2057 return EFI_UNSUPPORTED;
2058 }
2059 break;
2060
2061 default:
2062 //
2063 // Unknown section, return error
2064 //
2065 Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type);
2066 return EFI_SECTION_ERROR;
2067 }
2068
2069 ParsedLength += SectionLength;
2070 //
2071 // We make then next section begin on a 4-byte boundary
2072 //
2073 ParsedLength = GetOccupiedSize (ParsedLength, 4);
2074 }
2075
2076 if (ParsedLength < BufferLength) {
2077 Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL);
2078 return EFI_SECTION_ERROR;
2079 }
2080
2081 return EFI_SUCCESS;
2082 }
2083
2084 EFI_STATUS
2085 DumpDepexSection (
2086 IN UINT8 *Ptr,
2087 IN UINT32 SectionLength
2088 )
2089 /*++
2090
2091 Routine Description:
2092
2093 GC_TODO: Add function description
2094
2095 Arguments:
2096
2097 Ptr - GC_TODO: add argument description
2098 SectionLength - GC_TODO: add argument description
2099
2100 Returns:
2101
2102 EFI_SUCCESS - GC_TODO: Add description for return value
2103
2104 --*/
2105 {
2106 UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE];
2107
2108 //
2109 // Need at least a section header + data
2110 //
2111 if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) {
2112 return EFI_SUCCESS;
2113 }
2114
2115 Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
2116 SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr);
2117 while (SectionLength > 0) {
2118 printf (" ");
2119 switch (*Ptr) {
2120 case EFI_DEP_BEFORE:
2121 printf ("BEFORE\n");
2122 Ptr++;
2123 SectionLength--;
2124 break;
2125
2126 case EFI_DEP_AFTER:
2127 printf ("AFTER\n");
2128 Ptr++;
2129 SectionLength--;
2130 break;
2131
2132 case EFI_DEP_PUSH:
2133 printf ("PUSH\n ");
2134 PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE);
2135 printf ("%s ", GuidBuffer);
2136 PrintGuidName (GuidBuffer);
2137 printf ("\n");
2138 //
2139 // PrintGuid ((EFI_GUID *)(Ptr + 1));
2140 //
2141 Ptr += 17;
2142 SectionLength -= 17;
2143 break;
2144
2145 case EFI_DEP_AND:
2146 printf ("AND\n");
2147 Ptr++;
2148 SectionLength--;
2149 break;
2150
2151 case EFI_DEP_OR:
2152 printf ("OR\n");
2153 Ptr++;
2154 SectionLength--;
2155 break;
2156
2157 case EFI_DEP_NOT:
2158 printf ("NOT\n");
2159 Ptr++;
2160 SectionLength--;
2161 break;
2162
2163 case EFI_DEP_TRUE:
2164 printf ("TRUE\n");
2165 Ptr++;
2166 SectionLength--;
2167 break;
2168
2169 case EFI_DEP_FALSE:
2170 printf ("FALSE\n");
2171 Ptr++;
2172 SectionLength--;
2173 break;
2174
2175 case EFI_DEP_END:
2176 printf ("END DEPEX\n");
2177 Ptr++;
2178 SectionLength--;
2179 break;
2180
2181 case EFI_DEP_SOR:
2182 printf ("SOR\n");
2183 Ptr++;
2184 SectionLength--;
2185 break;
2186
2187 default:
2188 printf ("Unrecognized byte in depex: 0x%X\n", *Ptr);
2189 return EFI_SUCCESS;
2190 }
2191 }
2192
2193 return EFI_SUCCESS;
2194 }
2195
2196 EFI_STATUS
2197 PrintGuidName (
2198 IN UINT8 *GuidStr
2199 )
2200 /*++
2201
2202 Routine Description:
2203
2204 GC_TODO: Add function description
2205
2206 Arguments:
2207
2208 GuidStr - GC_TODO: add argument description
2209
2210 Returns:
2211
2212 EFI_SUCCESS - GC_TODO: Add description for return value
2213 EFI_INVALID_PARAMETER - GC_TODO: Add description for return value
2214
2215 --*/
2216 {
2217 GUID_TO_BASENAME *GPtr;
2218 //
2219 // If we have a list of guid-to-basenames, then go through the list to
2220 // look for a guid string match. If found, print the basename to stdout,
2221 // otherwise return a failure.
2222 //
2223 GPtr = mGuidBaseNameList;
2224 while (GPtr != NULL) {
2225 if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) {
2226 printf ("%s", GPtr->BaseName);
2227 return EFI_SUCCESS;
2228 }
2229
2230 GPtr = GPtr->Next;
2231 }
2232
2233 return EFI_INVALID_PARAMETER;
2234 }
2235
2236 EFI_STATUS
2237 ParseGuidBaseNameFile (
2238 CHAR8 *FileName
2239 )
2240 /*++
2241
2242 Routine Description:
2243
2244 GC_TODO: Add function description
2245
2246 Arguments:
2247
2248 FileName - GC_TODO: add argument description
2249
2250 Returns:
2251
2252 EFI_DEVICE_ERROR - GC_TODO: Add description for return value
2253 EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value
2254 EFI_SUCCESS - GC_TODO: Add description for return value
2255
2256 --*/
2257 {
2258 FILE *Fptr;
2259 CHAR8 Line[MAX_LINE_LEN];
2260 CHAR8 FormatString[MAX_LINE_LEN];
2261 GUID_TO_BASENAME *GPtr;
2262
2263 if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) {
2264 printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName);
2265 return EFI_DEVICE_ERROR;
2266 }
2267
2268 //
2269 // Generate the format string for fscanf
2270 //
2271 sprintf (
2272 FormatString,
2273 "%%%us %%%us",
2274 (unsigned) sizeof (GPtr->Guid) - 1,
2275 (unsigned) sizeof (GPtr->BaseName) - 1
2276 );
2277
2278 while (fgets (Line, sizeof (Line), Fptr) != NULL) {
2279 //
2280 // Allocate space for another guid/basename element
2281 //
2282 GPtr = malloc (sizeof (GUID_TO_BASENAME));
2283 if (GPtr == NULL) {
2284 fclose (Fptr);
2285 return EFI_OUT_OF_RESOURCES;
2286 }
2287
2288 memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME));
2289 if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) {
2290 GPtr->Next = mGuidBaseNameList;
2291 mGuidBaseNameList = GPtr;
2292 } else {
2293 //
2294 // Some sort of error. Just continue.
2295 //
2296 free (GPtr);
2297 }
2298 }
2299
2300 fclose (Fptr);
2301 return EFI_SUCCESS;
2302 }
2303
2304 EFI_STATUS
2305 FreeGuidBaseNameList (
2306 VOID
2307 )
2308 /*++
2309
2310 Routine Description:
2311
2312 GC_TODO: Add function description
2313
2314 Arguments:
2315
2316 None
2317
2318 Returns:
2319
2320 EFI_SUCCESS - GC_TODO: Add description for return value
2321
2322 --*/
2323 {
2324 GUID_TO_BASENAME *Next;
2325
2326 while (mGuidBaseNameList != NULL) {
2327 Next = mGuidBaseNameList->Next;
2328 free (mGuidBaseNameList);
2329 mGuidBaseNameList = Next;
2330 }
2331
2332 return EFI_SUCCESS;
2333 }
2334
2335
2336 static
2337 VOID
2338 LoadGuidedSectionToolsTxt (
2339 IN CHAR8* FirmwareVolumeFilename
2340 )
2341 {
2342 CHAR8* PeerFilename;
2343 CHAR8* Places[] = {
2344 NULL,
2345 //NULL,
2346 };
2347 UINTN Index;
2348
2349 Places[0] = FirmwareVolumeFilename;
2350 //Places[1] = mUtilityFilename;
2351
2352 mParsedGuidedSectionTools = NULL;
2353
2354 for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) {
2355 PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt");
2356 //printf("Loading %s...\n", PeerFilename);
2357 if (OsPathExists (PeerFilename)) {
2358 mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename);
2359 }
2360 free (PeerFilename);
2361 if (mParsedGuidedSectionTools != NULL) {
2362 return;
2363 }
2364 }
2365 }
2366
2367
2368 void
2369 Usage (
2370 VOID
2371 )
2372 /*++
2373
2374 Routine Description:
2375
2376 GC_TODO: Add function description
2377
2378 Arguments:
2379
2380 None
2381
2382 Returns:
2383
2384 GC_TODO: add return values
2385
2386 --*/
2387 {
2388 //
2389 // Summary usage
2390 //
2391 fprintf (stdout, "Usage: %s [options] <input_file>\n\n", UTILITY_NAME);
2392
2393 //
2394 // Copyright declaration
2395 //
2396 fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
2397 fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n");
2398
2399 //
2400 // Details Option
2401 //
2402 fprintf (stdout, "optional arguments:\n");
2403 fprintf (stdout, " -h, --help\n\
2404 Show this help message and exit\n");
2405 fprintf (stdout, " --version\n\
2406 Show program's version number and exit\n");
2407 fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\
2408 Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n");
2409 fprintf (stdout, " -v, --verbose\n\
2410 Print informational statements\n");
2411 fprintf (stdout, " -q, --quiet\n\
2412 Returns the exit code, error messages will be displayed\n");
2413 fprintf (stdout, " -s, --silent\n\
2414 Returns only the exit code; informational and error\n\
2415 messages are not displayed\n");
2416 fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\
2417 Parse the basename to file-guid cross reference file(s)\n");
2418 fprintf (stdout, " -f OFFSET, --offset OFFSET\n\
2419 The offset from the start of the input file to start \n\
2420 processing an FV\n");
2421 fprintf (stdout, " --hash\n\
2422 Generate HASH value of the entire PE image\n");
2423 fprintf (stdout, " --sfo\n\
2424 Reserved for future use\n");
2425 }
2426