3 Copyright (c) 2004-2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file contains functions required to generate a Firmware File System
24 #include <ctype.h> // for isalpha()
26 // include file for _spawnv
34 #include <Common/UefiBaseTypes.h>
35 #include <Common/FirmwareVolumeImageFormat.h>
36 #include <Common/FirmwareFileSystem.h>
37 #include <Common/FirmwareVolumeHeader.h>
38 #include <Common/FirmwareVolumeImageFormat.h>
42 #include "EfiCustomizedCompress.h"
44 #include "GenFfsFile.h"
45 #include "CommonLib.h"
46 #include "EfiUtilityMsgs.h"
47 #include "SimpleFileParsing.h"
49 #define UTILITY_NAME "GenFfsFile"
50 #define UTILITY_MAJOR_VERSION 0
51 #define UTILITY_MINOR_VERSION 32
53 #define MAX_ARRAY_SIZE 100
58 OUT CHAR8
*Destination
,
60 IN OUT UINT32
*LineNumber
68 IN OUT UINT32
*LineNumber
73 FindSectionInPackage (
74 IN CHAR8
*BuildDirectory
,
75 IN
FILE *OverridePackage
,
76 IN OUT UINT32
*LineNumber
81 ProcessCommandLineArgs (
99 // Keep globals in this structure
102 UINT8 BuildDirectory
[_MAX_PATH
];
103 UINT8 PrimaryPackagePath
[_MAX_PATH
];
104 UINT8 OverridePackagePath
[_MAX_PATH
];
108 static EFI_GUID mZeroGuid
= { 0 };
119 Removes quotes and/or whitespace from around a string
123 String - String to remove quotes from
135 Index2
= strspn (String
, "\" \t\n");
136 StrLen
= strlen (String
);
138 for (Index
= Index2
; String
[Index
] != '\"', Index
< StrLen
; Index
++) {
139 String
[Index
- Index2
] = String
[Index
];
142 String
[Index
- Index2
] = 0;
154 Print out version information for this utility.
166 printf ("%s v%d.%d -EDK utility to generate a Firmware File System files.\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
);
167 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
179 Print Error / Help message.
193 printf ("\nUsage:\n");
194 printf (UTILITY_NAME
" -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
195 printf (" -b \"build directory\":\n ");
196 printf (" specifies the full path to the component build directory.\n");
197 printf (" -p1 \"P1_path\":\n");
198 printf (" specifies fully qualified file name to the primary package file.\n");
199 printf (" This file will normally exist in the same directory as the makefile\n");
200 printf (" for the component. Required.\n");
201 printf (" -p2 \"P2_path\":\n");
202 printf (" specifies fully qualified file name to the override package file.\n");
203 printf (" This file will normally exist in the build tip. Optional.\n");
216 Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment
220 String - String to test
222 In - Open file to move pointer within
226 -1 - End of file reached
235 if ((String
[0] == '/') && (String
[1] == '/')) {
236 while (CharBuffer
!= '\n') {
237 fscanf (In
, "%c", &CharBuffer
);
252 IN CONST CHAR8
*Source
,
253 OUT CHAR8
*Destination
,
260 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
264 Source - String to break
266 Destination - Buffer to place new string in
268 Direction - 0 to return all of source string before =
269 1 to return all of source string after =
283 if (strchr (Source
, '=') == NULL
) {
284 strcpy (Destination
, Source
);
289 if (Direction
== 0) {
291 // return part of string before =
293 while (Source
[Index
] != '=') {
294 Destination
[Index
] = Source
[Index
++];
297 Destination
[Index
] = 0;
300 // return part of string after =
302 strcpy (Destination
, strchr (Source
, '=') + 1);
309 OUT CHAR8
*Destination
,
311 IN OUT UINT32
*LineNumber
317 Gets the next non-commented line from the file
321 Destination - Where to put string
323 Package - Package to get string from
325 LineNumber - The actual line number.
329 -1 - End of file reached
334 CHAR8 String
[_MAX_PATH
];
335 fscanf (Package
, "%s", &String
);
336 if (feof (Package
)) {
340 while (TestComment (String
, Package
) == 1) {
341 fscanf (Package
, "%s", &String
);
342 if (feof (Package
)) {
347 strcpy (Destination
, String
);
354 IN OUT CHAR8
*String
,
356 IN OUT UINT32
*LineNumber
362 Checks to see if string is line continuation character, if so goes to next valid line
366 String - String to test
368 In - Open file to move pointer within
370 LineNumber - The line number.
384 while (String
[0] == '\\') {
385 while (ByteBuffer
!= '\n') {
386 fscanf (In
, "%c", &ByteBuffer
);
389 if (GetNextLine (String
, In
, LineNumber
) == -1) {
397 while (String
[0] == '\n') {
398 if (GetNextLine (String
, In
, LineNumber
) == -1) {
413 FindSectionInPackage (
414 IN CHAR8
*BuildDirectory
,
415 IN
FILE *OverridePackage
,
416 IN OUT UINT32
*LineNumber
422 Finds the matching section within the package
426 BuildDirectory - name of section to find
428 OverridePackage - Package file to search within
430 LineNumber - The line number.
434 -1 - End of file reached
439 CHAR8 String
[_MAX_PATH
];
440 CHAR8 NewString
[_MAX_PATH
];
443 while (strcmp (BuildDirectory
, String
) != 0) {
444 if (GetNextLine (NewString
, OverridePackage
, LineNumber
) != 0) {
448 if (NewString
[0] == '[') {
449 if (NewString
[strlen (NewString
) - 1] != ']') {
451 // have to construct string.
453 strcpy (String
, NewString
+ 1);
456 fscanf (OverridePackage
, "%s", &NewString
);
457 if (feof (OverridePackage
)) {
461 if (NewString
[0] != ']') {
462 if (strlen (String
) != 0) {
463 strcat (String
, " ");
466 strcat (String
, NewString
);
467 if (String
[strlen (String
) - 1] == ']') {
468 String
[strlen (String
) - 1] = 0;
476 NewString
[strlen (NewString
) - 1] = 0;
477 strcpy (String
, NewString
+ 1);
487 GenSimpleGuidSection (
488 IN OUT UINT8
*FileBuffer
,
489 IN OUT UINT32
*BufferSize
,
491 IN EFI_GUID SignGuid
,
492 IN UINT16 GuidedSectionAttributes
498 add GUIDed section header for the data buffer.
499 data stays in same location (overwrites source data).
503 FileBuffer - Buffer containing data to sign
505 BufferSize - On input, the size of FileBuffer. On output, the size of
506 actual section data (including added section header).
508 DataSize - Length of data to Sign
510 SignGuid - Guid to be add.
512 GuidedSectionAttributes - The section attribute.
516 EFI_SUCCESS - Successful
517 EFI_OUT_OF_RESOURCES - Not enough resource.
523 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
534 TotalSize
= DataSize
+ sizeof (EFI_GUID_DEFINED_SECTION
);
535 GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
536 GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
537 GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
538 GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
539 memcpy (&(GuidSectionHeader
.SectionDefinitionGuid
), &SignGuid
, sizeof (EFI_GUID
));
540 GuidSectionHeader
.Attributes
= GuidedSectionAttributes
;
541 GuidSectionHeader
.DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
);
543 SwapBuffer
= (UINT8
*) malloc (DataSize
);
544 if (SwapBuffer
== NULL
) {
545 return EFI_OUT_OF_RESOURCES
;
548 memcpy (SwapBuffer
, FileBuffer
, DataSize
);
549 memcpy (FileBuffer
, &GuidSectionHeader
, sizeof (EFI_GUID_DEFINED_SECTION
));
550 memcpy (FileBuffer
+ sizeof (EFI_GUID_DEFINED_SECTION
), SwapBuffer
, DataSize
);
553 // Make sure section ends on a DWORD boundary
555 while ((TotalSize
& 0x03) != 0) {
556 FileBuffer
[TotalSize
] = 0;
560 *BufferSize
= TotalSize
;
562 if (SwapBuffer
!= NULL
) {
581 Compress the data and add section header for the compressed data.
582 Compressed data (with section header) stays in same location as the source
583 (overwrites source data).
587 FileBuffer - Buffer containing data to Compress
589 BufferSize - On input, the size of FileBuffer. On output, the size of
590 actual compressed data (including added section header).
591 When buffer is too small, this value indicates the size needed.
593 DataSize - The size of data to compress
595 Type - The compression type (not used currently).
596 Assume EFI_HEAVY_COMPRESSION.
600 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
601 EFI_UNSUPPORTED - Compress type can not be supported.
602 EFI_SUCCESS - Successful
603 EFI_OUT_OF_RESOURCES - Not enough resource.
611 EFI_COMPRESSION_SECTION CompressionSet
;
612 UINT8 CompressionType
;
613 COMPRESS_FUNCTION CompressFunction
;
615 Status
= EFI_SUCCESS
;
619 CompressFunction
= NULL
;
622 // Get the compress type
624 if (strcmpi (Type
, "Dummy") == 0) {
626 // Added "Dummy" to keep backward compatibility.
628 CompressionType
= EFI_STANDARD_COMPRESSION
;
629 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
631 } else if (strcmpi (Type
, "LZH") == 0) {
633 // EFI stardard compression (LZH)
635 CompressionType
= EFI_STANDARD_COMPRESSION
;
636 CompressFunction
= (COMPRESS_FUNCTION
) EfiCompress
;
640 // Customized compression
642 Status
= SetCustomizedCompressionType (Type
);
643 if (EFI_ERROR (Status
)) {
647 CompressionType
= EFI_CUSTOMIZED_COMPRESSION
;
648 CompressFunction
= (COMPRESS_FUNCTION
) CustomizedCompress
;
651 // Compress the raw data
653 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
654 if (Status
== EFI_BUFFER_TOO_SMALL
) {
655 CompData
= malloc (CompSize
);
657 return EFI_OUT_OF_RESOURCES
;
660 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
663 if (EFI_ERROR (Status
)) {
664 if (CompData
!= NULL
) {
671 TotalSize
= CompSize
+ sizeof (EFI_COMPRESSION_SECTION
);
676 if (TotalSize
> *BufferSize
) {
677 *BufferSize
= TotalSize
;
678 if (CompData
!= NULL
) {
682 return EFI_BUFFER_TOO_SMALL
;
685 // Add the section header for the compressed data
687 CompressionSet
.CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
688 CompressionSet
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
689 CompressionSet
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
690 CompressionSet
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
691 CompressionSet
.CompressionType
= CompressionType
;
692 CompressionSet
.UncompressedLength
= DataSize
;
695 // Copy header and data to the buffer
697 memcpy (FileBuffer
, &CompressionSet
, sizeof (EFI_COMPRESSION_SECTION
));
698 memcpy (FileBuffer
+ sizeof (CompressionSet
), CompData
, CompSize
);
701 // Make sure section ends on a DWORD boundary
703 while ((TotalSize
& 0x03) != 0) {
704 FileBuffer
[TotalSize
] = 0;
708 *BufferSize
= TotalSize
;
710 if (CompData
!= NULL
) {
726 Removes Parenthesis from around a string
730 String - String to remove parens from
740 if (String
[0] != '(') {
744 for (Index
= 1; String
[Index
] != ')'; Index
++) {
745 String
[Index
- 1] = String
[Index
];
746 if (String
[Index
] == 0) {
751 String
[Index
- 1] = 0;
765 Removes Equal Mark from around a string
769 String - String to remove equal mark from
779 if (String
[0] != '=' && String
[strlen (String
) - 1] != '=') {
783 if (String
[0] == '=') {
785 for (Index
= 1; String
[Index
] != 0; Index
++) {
786 String
[Index
- 1] = String
[Index
];
789 String
[Index
- 1] = 0;
792 if (String
[strlen (String
) - 1] == '=') {
793 String
[strlen (String
) - 1] = 0;
801 ProcessEnvironmentVariable (
809 Converts environment variables to values
813 Buffer - Buffer containing Environment Variable String
815 NewBuffer - Buffer containing value of environment variable
820 Number of characters from Buffer used
826 CHAR8 VariableBuffer
[_MAX_PATH
];
831 while (Buffer
[Index
] != ')') {
832 VariableBuffer
[Index
- 2] = Buffer
[Index
++];
835 VariableBuffer
[Index
- 2] = 0;
838 if (getenv (VariableBuffer
) != NULL
) {
839 strcpy (NewBuffer
, getenv (VariableBuffer
));
841 printf ("Environment variable %s not found!\n", VariableBuffer
);
849 SplitAttributesField (
851 IN CHAR8
*AttributesArray
[],
852 IN OUT UINT32
*NumberOfAttributes
855 NumberOfAttributes: on input, it specifies the current number of attributes
856 stored in AttributeArray.
857 on output, it is updated to the latest number of attributes
858 stored in AttributesArray.
867 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
868 ZeroMem (CharBuffer
, _MAX_PATH
);
870 for (Index
= 0, z
= 0, Index2
= 0; Index
< strlen (Buffer
); Index
++) {
872 if (Buffer
[Index
] != '|') {
873 CharBuffer
[z
] = Buffer
[Index
];
878 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
882 // allocate new char buffer for the next attributes string
884 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
885 ZeroMem (CharBuffer
, _MAX_PATH
);
892 // record the last attributes string in the Buffer
894 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
897 *NumberOfAttributes
+= Index2
;
905 CHAR8
*ToolArgumentsArray
[],
907 CHAR8
**PtrInputFileName
,
908 CHAR8
**PtrOutputFileName
,
910 UINT16
*GuidedSectionAttributes
913 CHAR8 Buffer
[_MAX_PATH
];
914 BOOLEAN ArgumentsFlag
;
918 BOOLEAN AttributesFlag
;
927 CHAR8
*AttributesArray
[MAX_ARRAY_SIZE
];
928 UINT32 NumberOfAttributes
;
929 CHAR8
*InputFileName
;
930 CHAR8
*OutputFileName
;
934 ArgumentsFlag
= FALSE
;
938 AttributesFlag
= FALSE
;
940 // Start at 1, since ToolArgumentsArray[0]
941 // is the program name.
948 NumberOfAttributes
= 0;
949 InputFileName
= NULL
;
950 OutputFileName
= NULL
;
952 ZeroMem (Buffer
, _MAX_PATH
);
953 ZeroMem (AttributesArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
955 while (Buffer
[0] != ')') {
957 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
958 CheckSlash (Buffer
, Package
, &LineNumber
);
959 StripEqualMark (Buffer
);
961 Error (NULL
, 0, 0, "failed to get next line from package file", NULL
);
965 if (Buffer
[0] == ')') {
967 } else if (strcmpi (Buffer
, "ARGS") == 0) {
969 ArgumentsFlag
= TRUE
;
970 AttributesFlag
= FALSE
;
973 } else if (strcmpi (Buffer
, "INPUT") == 0) {
976 ArgumentsFlag
= FALSE
;
977 AttributesFlag
= FALSE
;
980 } else if (strcmpi (Buffer
, "OUTPUT") == 0) {
983 ArgumentsFlag
= FALSE
;
984 AttributesFlag
= FALSE
;
987 } else if (strcmpi (Buffer
, "GUID") == 0) {
990 ArgumentsFlag
= FALSE
;
991 AttributesFlag
= FALSE
;
993 // fetch the GUID for the section
997 } else if (strcmpi (Buffer
, "ATTRIBUTES") == 0) {
999 AttributesFlag
= TRUE
;
1000 ArgumentsFlag
= FALSE
;
1002 // fetch the GUIDed Section's Attributes
1006 } else if (strcmpi (Buffer
, "") == 0) {
1010 // get all command arguments into ToolArgumentsArray
1012 if (ArgumentsFlag
) {
1014 StripEqualMark (Buffer
);
1016 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
1017 if (CharBuffer
== NULL
) {
1021 ZeroMem (CharBuffer
, sizeof (_MAX_PATH
));
1023 ToolArgumentsArray
[argc
] = CharBuffer
;
1025 if (Buffer
[0] == '$') {
1026 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolArgumentsArray
[argc
]);
1028 // if there is string after the environment variable, cat it.
1030 if ((UINT32
) Index
< strlen (Buffer
)) {
1031 strcat (ToolArgumentsArray
[argc
], &Buffer
[Index
]);
1034 strcpy (ToolArgumentsArray
[argc
], Buffer
);
1038 ToolArgumentsArray
[argc
] = NULL
;
1044 StripEqualMark (Buffer
);
1046 InputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1047 if (InputFileName
== NULL
) {
1051 ZeroMem (InputFileName
, sizeof (_MAX_PATH
));
1053 if (Buffer
[0] == '$') {
1054 Index
= ProcessEnvironmentVariable (&Buffer
[0], InputFileName
);
1056 // if there is string after the environment variable, cat it.
1058 if ((UINT32
) Index
< strlen (Buffer
)) {
1059 strcat (InputFileName
, &Buffer
[Index
]);
1062 strcpy (InputFileName
, Buffer
);
1071 StripEqualMark (Buffer
);
1073 OutputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1074 if (OutputFileName
== NULL
) {
1078 ZeroMem (OutputFileName
, sizeof (_MAX_PATH
));
1080 if (Buffer
[0] == '$') {
1081 Index
= ProcessEnvironmentVariable (&Buffer
[0], OutputFileName
);
1083 // if there is string after the environment variable, cat it.
1085 if ((UINT32
) Index
< strlen (Buffer
)) {
1086 strcat (OutputFileName
, &Buffer
[Index
]);
1089 strcpy (OutputFileName
, Buffer
);
1098 StripEqualMark (Buffer
);
1100 Status
= StringToGuid (Buffer
, Guid
);
1101 if (EFI_ERROR (Status
)) {
1109 if (AttributesFlag
) {
1111 StripEqualMark (Buffer
);
1114 // there might be no space between each attribute in the statement,
1115 // split them aside and return each attribute string
1116 // in the AttributesArray
1118 SplitAttributesField (Buffer
, AttributesArray
, &NumberOfAttributes
);
1122 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1123 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1125 for (z
= 0; z
< NumberOfAttributes
; z
++) {
1126 if (strcmpi (AttributesArray
[z
], "PROCESSING_REQUIRED") == 0) {
1127 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1128 } else if (strcmpi (AttributesArray
[z
], "AUTH_STATUS_VALID") == 0) {
1129 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1135 for (Index2
= 0; Index2
< MAX_ARRAY_SIZE
; Index2
++) {
1136 if (AttributesArray
[Index2
] == NULL
) {
1140 free (AttributesArray
[Index2
]);
1143 *PtrInputFileName
= InputFileName
;
1144 *PtrOutputFileName
= OutputFileName
;
1152 IN OUT UINT8
*FileBuffer
,
1154 IN CHAR8
*BuildDirectory
,
1155 IN BOOLEAN ForceUncompress
1159 Routine Description:
1161 Signs the section, data stays in same location
1165 FileBuffer - Data Buffer
1167 Package - Points to curly brace in Image Script
1169 BuildDirectory - Name of the source directory parameter
1171 ForceUncompress - Whether to force uncompress.
1175 Number of bytes added to file buffer
1182 CHAR8 Buffer
[_MAX_PATH
];
1183 CHAR8 Type
[_MAX_PATH
];
1184 CHAR8 FileName
[_MAX_PATH
];
1185 CHAR8 NewBuffer
[_MAX_PATH
];
1191 UINT32 SourceDataSize
;
1192 CHAR8
*ToolArgumentsArray
[MAX_ARRAY_SIZE
];
1193 CHAR8
*OutputFileName
;
1194 CHAR8
*InputFileName
;
1195 CHAR8 ToolName
[_MAX_PATH
];
1204 UINT16 GuidedSectionAttributes
;
1205 UINT8
*TargetFileBuffer
;
1207 OutputFileName
= NULL
;
1208 InputFileName
= NULL
;
1212 GuidedSectionAttributes
= 0;
1213 TargetFileBuffer
= NULL
;
1218 for (Index3
= 0; Index3
< MAX_ARRAY_SIZE
; ++Index3
) {
1219 ToolArgumentsArray
[Index3
] = NULL
;
1222 while (Buffer
[0] != '}') {
1223 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1224 CheckSlash (Buffer
, Package
, &LineNumber
);
1226 printf ("ERROR in IMAGE SCRIPT!\n");
1231 if (strcmpi (Buffer
, "Compress") == 0) {
1236 // read compression type
1238 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1239 CheckSlash (Buffer
, Package
, &LineNumber
);
1242 StripParens (Buffer
);
1243 if (Buffer
[0] == '$') {
1244 ProcessEnvironmentVariable (&Buffer
[0], Type
);
1246 strcpy (Type
, Buffer
);
1251 while (Buffer
[0] != '{') {
1252 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1253 CheckSlash (Buffer
, Package
, &LineNumber
);
1257 ReturnValue
= ProcessScript (&FileBuffer
[Size
], Package
, BuildDirectory
, ForceUncompress
);
1258 if (ReturnValue
== -1) {
1263 // Call compress routine on buffer.
1264 // Occasionally, compressed data + section header would
1265 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1266 // returned from CompressSection()
1268 SourceDataSize
= ReturnValue
;
1270 if (!ForceUncompress
) {
1272 Status
= CompressSection (
1279 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1280 Status
= CompressSection (
1288 if (EFI_ERROR (Status
)) {
1294 Size
+= ReturnValue
;
1296 } else if (strcmpi (Buffer
, "Tool") == 0) {
1298 ZeroMem (ToolName
, _MAX_PATH
);
1299 ZeroMem (ToolArgumentsArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
1300 ZeroMem (&SignGuid
, sizeof (EFI_GUID
));
1303 // handle signing Tool
1305 while (Buffer
[0] != '(') {
1306 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1307 CheckSlash (Buffer
, Package
, &LineNumber
);
1311 if (strcmpi (Buffer
, "(") == 0) {
1312 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1313 CheckSlash (Buffer
, Package
, &LineNumber
);
1317 StripParens (Buffer
);
1319 if (Buffer
[0] == '$') {
1320 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolName
);
1322 // if there is string after the environment variable, cat it.
1324 if ((UINT32
) Index
< strlen (Buffer
)) {
1325 strcat (ToolName
, &Buffer
[Index
]);
1328 strcpy (ToolName
, Buffer
);
1331 ToolArgumentsArray
[0] = ToolName
;
1336 if (GetToolArguments (
1342 &GuidedSectionAttributes
1348 // if the tool need input file,
1349 // dump the file buffer to the specified input file.
1351 if (InputFileName
!= NULL
) {
1352 InputFile
= fopen (InputFileName
, "wb");
1353 if (InputFile
== NULL
) {
1354 Error (NULL
, 0, 0, InputFileName
, "failed to open output file for writing");
1359 fwrite (FileBuffer
, sizeof (UINT8
), Size
, InputFile
);
1362 free (InputFileName
);
1363 InputFileName
= NULL
;
1366 // dispatch signing tool
1370 char CommandLine
[1000];
1371 sprintf(CommandLine
, "%s %s", ToolName
, ToolArgumentsArray
);
1372 returnint
= system(CommandLine
);
1375 returnint
= _spawnv (_P_WAIT
, ToolName
, ToolArgumentsArray
);
1377 if (returnint
!= 0) {
1378 Error (NULL
, 0, 0, ToolName
, "external tool failed");
1383 // if the tool has output file,
1384 // dump the output file to the file buffer
1386 if (OutputFileName
!= NULL
) {
1388 OutputFile
= fopen (OutputFileName
, "rb");
1389 if (OutputFile
== NULL
) {
1390 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file for writing");
1395 TargetFileBuffer
= &FileBuffer
[Size
];
1396 SourceDataSize
= Size
;
1398 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1399 while (!feof (OutputFile
)) {
1400 FileBuffer
[Size
++] = Temp
;
1401 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1404 while ((Size
& 0x03) != 0) {
1405 FileBuffer
[Size
] = 0;
1409 SourceDataSize
= Size
- SourceDataSize
;
1411 fclose (OutputFile
);
1413 free (OutputFileName
);
1414 OutputFileName
= NULL
;
1416 if (CompareGuid (&SignGuid
, &mZeroGuid
) != 0) {
1417 ReturnValue
= SourceDataSize
;
1418 Status
= GenSimpleGuidSection (
1423 GuidedSectionAttributes
1425 if (EFI_ERROR (Status
)) {
1434 } else if (Buffer
[0] != '}') {
1436 // if we are here, we should see either a file name,
1442 // Prepend the build directory to the file name if the
1443 // file name does not already contain a full path.
1445 if (!isalpha (Buffer
[0]) || (Buffer
[1] != ':')) {
1446 sprintf (FileName
, "%s\\", BuildDirectory
);
1449 while (Buffer
[Index3
] != '\n') {
1450 if (Buffer
[Index3
] == '$') {
1451 Index3
+= ProcessEnvironmentVariable (&Buffer
[Index3
], NewBuffer
);
1452 strcat (FileName
, NewBuffer
);
1455 if (Buffer
[Index3
] == 0) {
1458 Index2
= strlen (FileName
);
1459 FileName
[Index2
++] = Buffer
[Index3
++];
1460 FileName
[Index2
] = 0;
1464 InFile
= fopen (FileName
, "rb");
1465 if (InFile
== NULL
) {
1466 Error (NULL
, 0, 0, FileName
, "failed to open file for reading");
1471 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1472 while (!feof (InFile
)) {
1473 FileBuffer
[Size
++] = ByteBuffer
;
1474 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1481 // Make sure section ends on a DWORD boundary
1483 while ((Size
& 0x03) != 0) {
1484 FileBuffer
[Size
] = 0;
1492 for (Index3
= 1; Index3
< MAX_ARRAY_SIZE
; Index3
++) {
1493 if (ToolArgumentsArray
[Index3
] == NULL
) {
1497 free (ToolArgumentsArray
[Index3
]);
1515 Routine Description:
1517 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1518 unrecognized file type was specified.
1522 String - File type string
1530 if (strcmpi (String
, "EFI_FV_FILETYPE_RAW") == 0) {
1531 return EFI_FV_FILETYPE_RAW
;
1534 if (strcmpi (String
, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1535 return EFI_FV_FILETYPE_FREEFORM
;
1538 if (strcmpi (String
, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1539 return EFI_FV_FILETYPE_SECURITY_CORE
;
1542 if (strcmpi (String
, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1543 return EFI_FV_FILETYPE_PEI_CORE
;
1546 if (strcmpi (String
, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1547 return EFI_FV_FILETYPE_DXE_CORE
;
1550 if (strcmpi (String
, "EFI_FV_FILETYPE_PEIM") == 0) {
1551 return EFI_FV_FILETYPE_PEIM
;
1554 if (strcmpi (String
, "EFI_FV_FILETYPE_DRIVER") == 0) {
1555 return EFI_FV_FILETYPE_DRIVER
;
1558 if (strcmpi (String
, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1559 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
1562 if (strcmpi (String
, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1563 return EFI_FV_FILETYPE_APPLICATION
;
1566 if (strcmpi (String
, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1567 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
1570 return EFI_FV_FILETYPE_ALL
;
1576 IN UINT8
*FileBuffer
,
1581 Routine Description:
1582 Adjusts file size to insure sectioned file is exactly the right length such
1583 that it ends on exactly the last byte of the last section. ProcessScript()
1584 may have padded beyond the end of the last section out to a 4 byte boundary.
1585 This padding is stripped.
1588 FileBuffer - Data Buffer - contains a section stream
1589 FileSize - Size of FileBuffer as returned from ProcessScript()
1592 Corrected size of file.
1597 UINT32 CurrentLength
;
1598 UINT32 SectionLength
;
1599 UINT32 SectionStreamLength
;
1600 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1601 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1605 SectionStreamLength
= FileSize
;
1607 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) FileBuffer
;
1609 while (TotalLength
< SectionStreamLength
) {
1610 SectionLength
= *((UINT32
*) SectionHeader
->Size
) & 0x00ffffff;
1611 TotalLength
+= SectionLength
;
1613 if (TotalLength
== SectionStreamLength
) {
1617 // Move to the next byte following the section...
1619 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1620 CurrentLength
= (UINTN
) SectionHeader
- (UINTN
) FileBuffer
;
1623 // Figure out where the next section begins
1625 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ 3);
1626 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
&~ (UINTN
) 3);
1627 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1628 SectionHeader
= NextSectionHeader
;
1631 return CurrentLength
;
1639 BOOLEAN ForceUncompress
1643 Routine Description:
1649 argc - Number of command line parameters.
1650 argv - Array of pointers to command line parameter strings.
1651 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1652 is specified in the script. Otherwise, FALSE.
1655 STATUS_SUCCESS - Function exits successfully.
1656 STATUS_ERROR - Some error occurred during execution.
1660 FILE *PrimaryPackage
;
1661 FILE *OverridePackage
;
1663 CHAR8 BaseName
[_MAX_PATH
];
1665 CHAR8 GuidString
[_MAX_PATH
];
1666 EFI_FFS_FILE_HEADER FileHeader
;
1667 CHAR8 FileType
[_MAX_PATH
];
1668 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
1669 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined
;
1670 UINT64 FfsAlignment
;
1671 UINT32 FfsAlignment32
;
1672 CHAR8 InputString
[_MAX_PATH
];
1673 BOOLEAN ImageScriptInOveride
;
1678 EFI_FFS_FILE_TAIL TailValue
;
1683 FfsAttribDefined
= 0;
1686 PrimaryPackage
= NULL
;
1688 OverridePackage
= NULL
;
1691 strcpy (GuidString
, "00000000-0000-0000-0000-000000000000");
1692 Status
= StringToGuid (GuidString
, &FfsGuid
);
1694 Error (NULL
, 0, 0, GuidString
, "error parsing GUID string");
1695 return STATUS_ERROR
;
1699 ImageScriptInOveride
= FALSE
;
1701 // Initialize the simple file parsing routines. Then open
1702 // the primary package file for parsing.
1705 if (SFPOpenFile (mGlobals
.PrimaryPackagePath
) != STATUS_SUCCESS
) {
1706 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
1710 // First token in the file must be "PACKAGE.INF"
1712 if (!SFPIsToken ("PACKAGE.INF")) {
1713 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL
);
1717 // Find the [.] section
1719 if (!SFPSkipToToken ("[.]")) {
1720 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "could not locate [.] section in package file", NULL
);
1724 // Start parsing the data. The algorithm is essentially the same for each keyword:
1725 // 1. Identify the keyword
1726 // 2. Verify that the keyword/value pair has not already been defined
1727 // 3. Set some flag indicating that the keyword/value pair has been defined
1728 // 4. Skip over the "="
1729 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1732 if (SFPIsToken ("BASE_NAME")) {
1734 // Found BASE_NAME, format:
1735 // BASE_NAME = MyBaseName
1737 if (BaseName
[0] != 0) {
1738 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL
);
1742 if (!SFPIsToken ("=")) {
1743 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1747 if (!SFPGetNextToken (BaseName
, sizeof (BaseName
))) {
1748 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid base name", NULL
);
1751 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1753 // Found IMAGE_SCRIPT. Break out and process below.
1756 } else if (SFPIsToken ("FFS_FILEGUID")) {
1758 // found FILEGUID, format:
1759 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1761 if (GuidString
[0] != 0) {
1762 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL
);
1766 if (!SFPIsToken ("=")) {
1767 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1771 if (SFPGetGuidToken (GuidString
, sizeof (GuidString
)) != TRUE
) {
1772 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected file GUID", NULL
);
1776 Status
= StringToGuid (GuidString
, &FfsGuid
);
1778 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid file GUID", NULL
);
1781 } else if (SFPIsToken ("FFS_FILETYPE")) {
1783 // ***********************************************************************
1785 // Found FFS_FILETYPE, format:
1786 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1788 if (FileType
[0] != 0) {
1789 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL
);
1793 if (!SFPIsToken ("=")) {
1794 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1798 if (!SFPGetNextToken (FileType
, sizeof (FileType
))) {
1799 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL
);
1802 } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1804 // ***********************************************************************
1806 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1807 // Spec says the bit is for future expansion, and must be false.
1809 if (FfsAttribDefined
& FFS_ATTRIB_HEADER_EXTENSION
) {
1811 mGlobals
.PrimaryPackagePath
,
1812 SFPGetLineNumber (),
1814 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1820 FfsAttribDefined
|= FFS_ATTRIB_HEADER_EXTENSION
;
1821 if (!SFPIsToken ("=")) {
1822 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1826 if (SFPIsToken ("TRUE")) {
1828 mGlobals
.PrimaryPackagePath
,
1829 SFPGetLineNumber (),
1831 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1835 } else if (SFPIsToken ("FALSE")) {
1840 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL
);
1843 } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1845 // ***********************************************************************
1847 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1849 if (FfsAttribDefined
& FFS_ATTRIB_TAIL_PRESENT
) {
1850 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL
);
1854 FfsAttribDefined
|= FFS_ATTRIB_TAIL_PRESENT
;
1855 if (!SFPIsToken ("=")) {
1856 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1860 if (SFPIsToken ("TRUE")) {
1861 FfsAttrib
|= FFS_ATTRIB_TAIL_PRESENT
;
1862 } else if (SFPIsToken ("FALSE")) {
1867 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1870 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1872 // ***********************************************************************
1874 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1876 if (FfsAttribDefined
& FFS_ATTRIB_RECOVERY
) {
1877 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL
);
1881 FfsAttribDefined
|= FFS_ATTRIB_RECOVERY
;
1882 if (!SFPIsToken ("=")) {
1883 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1887 if (SFPIsToken ("TRUE")) {
1888 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
1889 } else if (SFPIsToken ("FALSE")) {
1894 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1897 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1899 // ***********************************************************************
1901 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1903 if (FfsAttribDefined
& FFS_ATTRIB_CHECKSUM
) {
1904 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL
);
1908 FfsAttribDefined
|= FFS_ATTRIB_CHECKSUM
;
1909 if (!SFPIsToken ("=")) {
1910 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1914 if (SFPIsToken ("TRUE")) {
1915 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
1916 } else if (SFPIsToken ("FALSE")) {
1921 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1924 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1926 // ***********************************************************************
1928 // Found FFS_ALIGNMENT, formats:
1929 // FFS_ALIGNMENT = 0-7
1930 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1932 if (FfsAttribDefined
& FFS_ATTRIB_DATA_ALIGNMENT
) {
1934 mGlobals
.PrimaryPackagePath
,
1935 SFPGetLineNumber (),
1937 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1943 FfsAttribDefined
|= FFS_ATTRIB_DATA_ALIGNMENT
;
1944 if (!SFPIsToken ("=")) {
1945 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1949 if (!SFPGetNumber (&FfsAlignment32
)) {
1950 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL
);
1954 if (FfsAlignment32
> 7) {
1955 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL
);
1959 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment32
) << 3);
1961 SFPGetNextToken (InputString
, sizeof (InputString
));
1962 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, InputString
, "unrecognized/unexpected token");
1967 // Close the primary package file
1971 // TODO: replace code below with basically a copy of the code above. Don't
1972 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1973 // to somehow keep track of whether or not the basename is defined multiple
1974 // times in the override package. Ditto on the file GUID.
1976 if (mGlobals
.OverridePackagePath
[0] != 0) {
1977 OverridePackage
= fopen (mGlobals
.OverridePackagePath
, "r");
1979 // NOTE: For package override to work correctly, the code below must be modified to
1980 // SET or CLEAR bits properly. For example, if the primary package set
1981 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1982 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1983 // the override functionality is not being used, so should be made obsolete. If I'm
1984 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1985 // used, and we'll address it then. 4/10/2003
1987 Error (__FILE__
, __LINE__
, 0, "package override functionality is not implemented correctly", NULL
);
1990 OverridePackage
= NULL
;
1993 #ifdef OVERRIDE_SUPPORTED
1994 if (OverridePackage
!= NULL
) {
1996 // Parse override package file
1998 fscanf (OverridePackage
, "%s", &InputString
);
1999 if (strcmpi (InputString
, "PACKAGE.INF") != 0) {
2000 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
2004 // Match [dir] to Build Directory
2006 if (FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
) != 0) {
2007 Error (mGlobals
.OverridePackagePath
, 1, 0, mGlobals
.BuildDirectory
, "section not found in package file");
2012 while ((InputString
[0] != '[') && (!feof (OverridePackage
))) {
2013 if (GetNextLine (InputString
, OverridePackage
, &LineNumber
) != -1) {
2014 if (InputString
[0] != '[') {
2016 if (strcmpi (InputString
, "BASE_NAME") == 0) {
2018 // found BASE_NAME, next is = and string.
2020 fscanf (OverridePackage
, "%s", &InputString
);
2021 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2022 if (strlen (InputString
) == 1) {
2026 fscanf (OverridePackage
, "%s", &InputString
);
2027 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2028 strcpy (BaseName
, InputString
);
2030 BreakString (InputString
, InputString
, 1);
2031 strcpy (BaseName
, InputString
);
2033 } else if (strcmpi (InputString
, "IMAGE_SCRIPT") == 0) {
2035 // found IMAGE_SCRIPT, come back later to process it
2037 ImageScriptInOveride
= TRUE
;
2038 fscanf (OverridePackage
, "%s", &InputString
);
2039 } else if (strcmpi (InputString
, "FFS_FILEGUID") == 0) {
2041 // found FILEGUID, next is = and string.
2043 fscanf (OverridePackage
, "%s", &InputString
);
2044 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2045 if (strlen (InputString
) == 1) {
2049 fscanf (OverridePackage
, "%s", &InputString
);
2050 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2051 Status
= StringToGuid (InputString
, &FfsGuid
);
2053 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2057 BreakString (InputString
, InputString
, 1);
2058 Status
= StringToGuid (InputString
, &FfsGuid
);
2060 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2064 } else if (strcmpi (InputString
, "FFS_FILETYPE") == 0) {
2066 // found FILETYPE, next is = and string.
2068 fscanf (OverridePackage
, "%s", &InputString
);
2069 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2070 if (strlen (InputString
) == 1) {
2074 fscanf (OverridePackage
, "%s", &InputString
);
2075 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2076 strcpy (FileType
, InputString
);
2078 BreakString (InputString
, InputString
, 1);
2079 strcpy (FileType
, InputString
);
2082 } else if (strcmpi (InputString
, "FFS_ATTRIB_RECOVERY") == 0) {
2084 // found FFS_ATTRIB_RECOVERY, next is = and string.
2086 fscanf (OverridePackage
, "%s", &InputString
);
2087 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2088 if (strlen (InputString
) == 1) {
2092 fscanf (OverridePackage
, "%s", &InputString
);
2093 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2094 if (strcmpi (InputString
, "TRUE") == 0) {
2095 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2098 BreakString (InputString
, InputString
, 1);
2099 if (strcmpi (InputString
, "TRUE") == 0) {
2100 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2103 } else if (strcmpi (InputString
, "FFS_ATTRIB_CHECKSUM") == 0) {
2105 // found FFS_ATTRIB_CHECKSUM, next is = and string.
2107 fscanf (OverridePackage
, "%s", &InputString
);
2108 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2109 if (strlen (InputString
) == 1) {
2113 fscanf (OverridePackage
, "%s", &InputString
);
2114 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2115 if (strcmpi (InputString
, "TRUE") == 0) {
2116 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2119 BreakString (InputString
, InputString
, 1);
2120 if (strcmpi (InputString
, "TRUE") == 0) {
2121 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2124 } else if (strcmpi (InputString
, "FFS_ALIGNMENT") == 0) {
2126 // found FFS_ALIGNMENT, next is = and string.
2128 fscanf (OverridePackage
, "%s", &InputString
);
2129 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2130 if (strlen (InputString
) == 1) {
2134 fscanf (OverridePackage
, "%s", &InputString
);
2135 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2137 BreakString (InputString
, InputString
, 1);
2140 AsciiStringToUint64 (InputString
, FALSE
, &FfsAlignment
);
2141 if (FfsAlignment
> 7) {
2142 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "invalid FFS_ALIGNMENT value");
2146 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment
) << 3);
2147 } else if (strchr (InputString
, '=') != NULL
) {
2148 BreakString (InputString
, String
, 1);
2149 fseek (OverridePackage
, (-1 * (strlen (String
) + 1)), SEEK_CUR
);
2150 BreakString (InputString
, InputString
, 0);
2157 #endif // #ifdef OVERRIDE_SUPPORTED
2159 // Require that they specified a file GUID at least, since that's how we're
2162 if (GuidString
[0] == 0) {
2163 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "FFS_FILEGUID must be specified", NULL
);
2164 return STATUS_ERROR
;
2167 // Build Header and process image script
2169 FileBuffer
= (UINT8
*) malloc ((1024 * 1024 * 16) * sizeof (UINT8
));
2170 if (FileBuffer
== NULL
) {
2171 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
2176 if (ImageScriptInOveride
) {
2177 #ifdef OVERRIDE_SUPORTED
2178 rewind (OverridePackage
);
2180 FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
);
2181 while (strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2182 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2183 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2184 if (strchr (InputString
, '=') != NULL
) {
2185 BreakString (InputString
, InputString
, 0);
2189 while (InputString
[0] != '{') {
2190 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2191 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2194 // Found start of image script, process it
2196 FileSize
+= ProcessScript (FileBuffer
, OverridePackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2197 if (FileSize
== -1) {
2201 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2202 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2205 if (BaseName
[0] == '\"') {
2206 StripQuotes (BaseName
);
2209 if (BaseName
[0] != 0) {
2210 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2212 strcpy (InputString
, GuidString
);
2215 switch (StringToType (FileType
)) {
2217 case EFI_FV_FILETYPE_SECURITY_CORE
:
2218 strcat (InputString
, ".SEC");
2221 case EFI_FV_FILETYPE_PEIM
:
2222 case EFI_FV_FILETYPE_PEI_CORE
:
2223 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2224 strcat (InputString
, ".PEI");
2227 case EFI_FV_FILETYPE_DRIVER
:
2228 case EFI_FV_FILETYPE_DXE_CORE
:
2229 strcat (InputString
, ".DXE");
2232 case EFI_FV_FILETYPE_APPLICATION
:
2233 strcat (InputString
, ".APP");
2236 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2237 strcat (InputString
, ".FVI");
2240 case EFI_FV_FILETYPE_ALL
:
2241 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2245 strcat (InputString
, ".FFS");
2249 if (ForceUncompress
) {
2250 strcat (InputString
, ".ORG");
2253 Out
= fopen (InputString
, "wb");
2255 Error (NULL
, 0, 0, InputString
, "could not open output file for writing");
2259 // create ffs header
2261 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2262 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2263 FileHeader
.Type
= StringToType (FileType
);
2264 FileHeader
.Attributes
= FfsAttrib
;
2266 // Now FileSize includes the EFI_FFS_FILE_HEADER
2268 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2269 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2270 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2271 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2273 // Fill in checksums and state, these must be zero for checksumming
2275 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2276 // FileHeader.IntegrityCheck.Checksum.File = 0;
2277 // FileHeader.State = 0;
2279 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2280 (UINT8
*) &FileHeader
,
2281 sizeof (EFI_FFS_FILE_HEADER
)
2283 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2284 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) &FileHeader
, FileSize
);
2286 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2289 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2293 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2294 Error (NULL
, 0, 0, "failed to write file header to output file", NULL
);
2300 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2301 Error (NULL
, 0, 0, "failed to write all bytes to output file", NULL
);
2307 #endif // #ifdef OVERRIDE_SUPPORTED
2310 // Open primary package file and process the IMAGE_SCRIPT section
2312 PrimaryPackage
= fopen (mGlobals
.PrimaryPackagePath
, "r");
2313 if (PrimaryPackage
== NULL
) {
2314 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
2319 FindSectionInPackage (".", PrimaryPackage
, &LineNumber
);
2320 while (strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2321 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2322 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2323 if (strchr (InputString
, '=') != NULL
) {
2324 BreakString (InputString
, InputString
, 0);
2328 while (InputString
[0] != '{') {
2329 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2330 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2333 // Found start of image script, process it
2335 FileSize
+= ProcessScript (FileBuffer
, PrimaryPackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2336 if (FileSize
== -1) {
2340 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2341 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2344 if (BaseName
[0] == '\"') {
2345 StripQuotes (BaseName
);
2348 if (BaseName
[0] != 0) {
2349 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2351 strcpy (InputString
, GuidString
);
2354 switch (StringToType (FileType
)) {
2356 case EFI_FV_FILETYPE_SECURITY_CORE
:
2357 strcat (InputString
, ".SEC");
2360 case EFI_FV_FILETYPE_PEIM
:
2361 case EFI_FV_FILETYPE_PEI_CORE
:
2362 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2363 strcat (InputString
, ".PEI");
2366 case EFI_FV_FILETYPE_DRIVER
:
2367 case EFI_FV_FILETYPE_DXE_CORE
:
2368 strcat (InputString
, ".DXE");
2371 case EFI_FV_FILETYPE_APPLICATION
:
2372 strcat (InputString
, ".APP");
2375 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2376 strcat (InputString
, ".FVI");
2379 case EFI_FV_FILETYPE_ALL
:
2380 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2384 strcat (InputString
, ".FFS");
2388 if (ForceUncompress
) {
2389 strcat (InputString
, ".ORG");
2392 Out
= fopen (InputString
, "wb");
2394 Error (NULL
, 0, 0, InputString
, "failed to open output file for writing");
2398 // Initialize the FFS file header
2400 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2401 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2402 FileHeader
.Type
= StringToType (FileType
);
2403 FileHeader
.Attributes
= FfsAttrib
;
2405 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2407 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2409 // If using a tail, then it adds two bytes
2411 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2413 // Tail is not allowed for pad and 0-length files
2415 if ((FileHeader
.Type
== EFI_FV_FILETYPE_FFS_PAD
) || (FileSize
== sizeof (EFI_FFS_FILE_HEADER
))) {
2417 mGlobals
.PrimaryPackagePath
,
2420 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2426 FileSize
+= sizeof (EFI_FFS_FILE_TAIL
);
2429 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2430 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2431 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2433 // Fill in checksums and state, they must be 0 for checksumming.
2435 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2436 // FileHeader.IntegrityCheck.Checksum.File = 0;
2437 // FileHeader.State = 0;
2439 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2440 (UINT8
*) &FileHeader
,
2441 sizeof (EFI_FFS_FILE_HEADER
)
2443 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2445 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2446 // Checksum does not include the tail
2448 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2449 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2451 FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
)
2454 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2456 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2460 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2463 // Set the state now. Spec says the checksum assumes the state is 0
2465 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2467 // If there is a tail, then set it
2469 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2470 TailValue
= FileHeader
.IntegrityCheck
.TailReference
;
2471 TailValue
= (UINT16
) (~TailValue
);
2473 (UINT8
*) FileBuffer
+ FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
),
2479 // Write the FFS file header
2481 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2482 Error (NULL
, 0, 0, "failed to write file header contents", NULL
);
2488 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2489 Error (NULL
, 0, 0, "failed to write file contents", NULL
);
2500 if (PrimaryPackage
!= NULL
) {
2501 fclose (PrimaryPackage
);
2504 if (FileBuffer
!= NULL
) {
2508 if (OverridePackage
!= NULL
) {
2509 fclose (OverridePackage
);
2512 return GetUtilityStatus ();
2522 Routine Description:
2528 argc - Number of command line parameters.
2529 argv - Array of pointers to parameter strings.
2532 STATUS_SUCCESS - Utility exits successfully.
2533 STATUS_ERROR - Some error occurred during execution.
2539 // Set the name of our utility for error reporting purposes.
2541 SetUtilityName (UTILITY_NAME
);
2542 Status
= ProcessCommandLineArgs (argc
, argv
);
2543 if (Status
!= STATUS_SUCCESS
) {
2547 Status
= MainEntry (argc
, argv
, TRUE
);
2548 if (Status
== STATUS_SUCCESS
) {
2549 MainEntry (argc
, argv
, FALSE
);
2552 // If any errors were reported via the standard error reporting
2553 // routines, then the status has been saved. Get the value and
2554 // return it to the caller.
2556 return GetUtilityStatus ();
2561 ProcessCommandLineArgs (
2567 Routine Description:
2568 Process the command line arguments.
2571 Argc - as passed in to main()
2572 Argv - as passed in to main()
2575 STATUS_SUCCESS - arguments all ok
2576 STATUS_ERROR - problem with args, so caller should exit
2581 // If no args, then print usage instructions and return an error
2588 return STATUS_ERROR
;
2591 if ((strcmp(Argv
[0], "-h") == 0) || (strcmp(Argv
[0], "--help") == 0) ||
2592 (strcmp(Argv
[0], "-?") == 0) || (strcmp(Argv
[0], "/?") == 0)) {
2594 return STATUS_ERROR
;
2597 if ((strcmp(Argv
[0], "-V") == 0) || (strcmp(Argv
[0], "--version") == 0)) {
2599 return STATUS_ERROR
;
2602 memset (&mGlobals
, 0, sizeof (mGlobals
));
2605 if (strcmpi (Argv
[0], "-b") == 0) {
2607 // OPTION: -b BuildDirectory
2608 // Make sure there is another argument, then save it to our globals.
2611 Error (NULL
, 0, 0, "-b option requires the build directory name", NULL
);
2612 return STATUS_ERROR
;
2615 if (mGlobals
.BuildDirectory
[0]) {
2616 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2617 return STATUS_ERROR
;
2620 strcpy (mGlobals
.BuildDirectory
, Argv
[1]);
2623 } else if (strcmpi (Argv
[0], "-p1") == 0) {
2625 // OPTION: -p1 PrimaryPackageFile
2626 // Make sure there is another argument, then save it to our globals.
2629 Error (NULL
, 0, 0, Argv
[0], "option requires the primary package file name");
2630 return STATUS_ERROR
;
2633 if (mGlobals
.PrimaryPackagePath
[0]) {
2634 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2635 return STATUS_ERROR
;
2638 strcpy (mGlobals
.PrimaryPackagePath
, Argv
[1]);
2641 } else if (strcmpi (Argv
[0], "-p2") == 0) {
2643 // OPTION: -p2 OverridePackageFile
2644 // Make sure there is another argument, then save it to our globals.
2647 Error (NULL
, 0, 0, Argv
[0], "option requires the override package file name");
2648 return STATUS_ERROR
;
2651 if (mGlobals
.OverridePackagePath
[0]) {
2652 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2653 return STATUS_ERROR
;
2656 strcpy (mGlobals
.OverridePackagePath
, Argv
[1]);
2659 } else if (strcmpi (Argv
[0], "-v") == 0) {
2661 // OPTION: -v verbose
2663 mGlobals
.Verbose
= TRUE
;
2664 } else if (strcmpi (Argv
[0], "-h") == 0) {
2669 return STATUS_ERROR
;
2670 } else if (strcmpi (Argv
[0], "-?") == 0) {
2675 return STATUS_ERROR
;
2677 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
2679 return STATUS_ERROR
;
2686 // Must have at least specified the package file name
2688 if (mGlobals
.PrimaryPackagePath
[0] == 0) {
2689 Error (NULL
, 0, 0, "must specify primary package file", NULL
);
2690 return STATUS_ERROR
;
2693 return STATUS_SUCCESS
;