3 Copyright (c) 2004, 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 "UefiBaseTypes.h"
25 #include "FirmwareVolumeImageFormat.h"
26 #include "FirmwareFileSystem.h"
27 #include "FirmwareVolumeHeader.h"
28 #include "FirmwareVolumeImageFormat.h"
30 #include "EfiCompress.h"
31 #include "EfiCustomizedCompress.h"
33 #include "GenFfsFile.h"
35 #include <ctype.h> // for isalpha()
37 // include file for _spawnv
44 #include "CommonLib.h"
45 #include "EfiUtilityMsgs.h"
46 #include "SimpleFileParsing.h"
48 #define UTILITY_NAME "GenFfsFile"
49 #define TOOLVERSION "0.32"
50 #define MAX_ARRAY_SIZE 100
55 OUT CHAR8
*Destination
,
57 IN OUT UINT32
*LineNumber
65 IN OUT UINT32
*LineNumber
70 FindSectionInPackage (
71 IN CHAR8
*BuildDirectory
,
72 IN
FILE *OverridePackage
,
73 IN OUT UINT32
*LineNumber
78 ProcessCommandLineArgs (
90 // Keep globals in this structure
93 UINT8 BuildDirectory
[_MAX_PATH
];
94 UINT8 PrimaryPackagePath
[_MAX_PATH
];
95 UINT8 OverridePackagePath
[_MAX_PATH
];
99 static EFI_GUID mZeroGuid
= { 0 };
110 Removes quotes and/or whitespace from around a string
114 String - String to remove quotes from
126 Index2
= strspn (String
, "\" \t\n");
127 StrLen
= strlen (String
);
129 for (Index
= Index2
; String
[Index
] != '\"', Index
< StrLen
; Index
++) {
130 String
[Index
- Index2
] = String
[Index
];
133 String
[Index
- Index2
] = 0;
145 Print Error / Help message.
158 printf (UTILITY_NAME
" -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
159 printf (" -b \"build directory\":\n ");
160 printf (" specifies the full path to the component build directory.\n");
161 printf (" -p1 \"P1_path\":\n");
162 printf (" specifies fully qualified file name to the primary package file.\n");
163 printf (" This file will normally exist in the same directory as the makefile\n");
164 printf (" for the component. Required.\n");
165 printf (" -p2 \"P2_path\":\n");
166 printf (" specifies fully qualified file name to the override package file.\n");
167 printf (" This file will normally exist in the build tip. Optional.\n");
180 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
184 String - String to test
186 In - Open file to move pointer within
190 -1 - End of file reached
199 if ((String
[0] == '/') && (String
[1] == '/')) {
200 while (CharBuffer
!= '\n') {
201 fscanf (In
, "%c", &CharBuffer
);
216 IN CONST CHAR8
*Source
,
217 OUT CHAR8
*Destination
,
224 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
228 Source - String to break
230 Destination - Buffer to place new string in
232 Direction - 0 to return all of source string before =
233 1 to return all of source string after =
247 if (strchr (Source
, '=') == NULL
) {
248 strcpy (Destination
, Source
);
253 if (Direction
== 0) {
255 // return part of string before =
257 while (Source
[Index
] != '=') {
258 Destination
[Index
] = Source
[Index
++];
261 Destination
[Index
] = 0;
264 // return part of string after =
266 strcpy (Destination
, strchr (Source
, '=') + 1);
273 OUT CHAR8
*Destination
,
275 IN OUT UINT32
*LineNumber
281 Gets the next non-commented line from the file
285 Destination - Where to put string
287 Package - Package to get string from
289 LineNumber - The actual line number.
293 -1 - End of file reached
298 CHAR8 String
[_MAX_PATH
];
299 fscanf (Package
, "%s", &String
);
300 if (feof (Package
)) {
304 while (TestComment (String
, Package
) == 1) {
305 fscanf (Package
, "%s", &String
);
306 if (feof (Package
)) {
311 strcpy (Destination
, String
);
318 IN OUT CHAR8
*String
,
320 IN OUT UINT32
*LineNumber
326 Checks to see if string is line continuation character, if so goes to next valid line
330 String - String to test
332 In - Open file to move pointer within
334 LineNumber - The line number.
348 while (String
[0] == '\\') {
349 while (ByteBuffer
!= '\n') {
350 fscanf (In
, "%c", &ByteBuffer
);
353 if (GetNextLine (String
, In
, LineNumber
) == -1) {
361 while (String
[0] == '\n') {
362 if (GetNextLine (String
, In
, LineNumber
) == -1) {
377 FindSectionInPackage (
378 IN CHAR8
*BuildDirectory
,
379 IN
FILE *OverridePackage
,
380 IN OUT UINT32
*LineNumber
386 Finds the matching section within the package
390 BuildDirectory - name of section to find
392 OverridePackage - Package file to search within
394 LineNumber - The line number.
398 -1 - End of file reached
403 CHAR8 String
[_MAX_PATH
];
404 CHAR8 NewString
[_MAX_PATH
];
407 while (strcmp (BuildDirectory
, String
) != 0) {
408 if (GetNextLine (NewString
, OverridePackage
, LineNumber
) != 0) {
412 if (NewString
[0] == '[') {
413 if (NewString
[strlen (NewString
) - 1] != ']') {
415 // have to construct string.
417 strcpy (String
, NewString
+ 1);
420 fscanf (OverridePackage
, "%s", &NewString
);
421 if (feof (OverridePackage
)) {
425 if (NewString
[0] != ']') {
426 if (strlen (String
) != 0) {
427 strcat (String
, " ");
430 strcat (String
, NewString
);
431 if (String
[strlen (String
) - 1] == ']') {
432 String
[strlen (String
) - 1] = 0;
440 NewString
[strlen (NewString
) - 1] = 0;
441 strcpy (String
, NewString
+ 1);
451 GenSimpleGuidSection (
452 IN OUT UINT8
*FileBuffer
,
453 IN OUT UINT32
*BufferSize
,
455 IN EFI_GUID SignGuid
,
456 IN UINT16 GuidedSectionAttributes
462 add GUIDed section header for the data buffer.
463 data stays in same location (overwrites source data).
467 FileBuffer - Buffer containing data to sign
469 BufferSize - On input, the size of FileBuffer. On output, the size of
470 actual section data (including added section header).
472 DataSize - Length of data to Sign
474 SignGuid - Guid to be add.
476 GuidedSectionAttributes - The section attribute.
480 EFI_SUCCESS - Successful
481 EFI_OUT_OF_RESOURCES - Not enough resource.
487 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
498 TotalSize
= DataSize
+ sizeof (EFI_GUID_DEFINED_SECTION
);
499 GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
500 GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
501 GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
502 GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
503 memcpy (&(GuidSectionHeader
.SectionDefinitionGuid
), &SignGuid
, sizeof (EFI_GUID
));
504 GuidSectionHeader
.Attributes
= GuidedSectionAttributes
;
505 GuidSectionHeader
.DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
);
507 SwapBuffer
= (UINT8
*) malloc (DataSize
);
508 if (SwapBuffer
== NULL
) {
509 return EFI_OUT_OF_RESOURCES
;
512 memcpy (SwapBuffer
, FileBuffer
, DataSize
);
513 memcpy (FileBuffer
, &GuidSectionHeader
, sizeof (EFI_GUID_DEFINED_SECTION
));
514 memcpy (FileBuffer
+ sizeof (EFI_GUID_DEFINED_SECTION
), SwapBuffer
, DataSize
);
517 // Make sure section ends on a DWORD boundary
519 while ((TotalSize
& 0x03) != 0) {
520 FileBuffer
[TotalSize
] = 0;
524 *BufferSize
= TotalSize
;
526 if (SwapBuffer
!= NULL
) {
545 Compress the data and add section header for the compressed data.
546 Compressed data (with section header) stays in same location as the source
547 (overwrites source data).
551 FileBuffer - Buffer containing data to Compress
553 BufferSize - On input, the size of FileBuffer. On output, the size of
554 actual compressed data (including added section header).
555 When buffer is too small, this value indicates the size needed.
557 DataSize - The size of data to compress
559 Type - The compression type (not used currently).
560 Assume EFI_HEAVY_COMPRESSION.
564 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
565 EFI_UNSUPPORTED - Compress type can not be supported.
566 EFI_SUCCESS - Successful
567 EFI_OUT_OF_RESOURCES - Not enough resource.
575 EFI_COMPRESSION_SECTION CompressionSet
;
576 UINT8 CompressionType
;
577 COMPRESS_FUNCTION CompressFunction
;
579 Status
= EFI_SUCCESS
;
583 CompressFunction
= NULL
;
586 // Get the compress type
588 if (strcmpi (Type
, "Dummy") == 0) {
590 // Added "Dummy" to keep backward compatibility.
592 CompressionType
= EFI_STANDARD_COMPRESSION
;
593 CompressFunction
= (COMPRESS_FUNCTION
) Compress
;
595 } else if (strcmpi (Type
, "LZH") == 0) {
597 // EFI stardard compression (LZH)
599 CompressionType
= EFI_STANDARD_COMPRESSION
;
600 CompressFunction
= (COMPRESS_FUNCTION
) Compress
;
604 // Customized compression
606 Status
= SetCustomizedCompressionType (Type
);
607 if (EFI_ERROR (Status
)) {
611 CompressionType
= EFI_CUSTOMIZED_COMPRESSION
;
612 CompressFunction
= (COMPRESS_FUNCTION
) CustomizedCompress
;
615 // Compress the raw data
617 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
618 if (Status
== EFI_BUFFER_TOO_SMALL
) {
619 CompData
= malloc (CompSize
);
621 return EFI_OUT_OF_RESOURCES
;
624 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
627 if (EFI_ERROR (Status
)) {
628 if (CompData
!= NULL
) {
635 TotalSize
= CompSize
+ sizeof (EFI_COMPRESSION_SECTION
);
640 if (TotalSize
> *BufferSize
) {
641 *BufferSize
= TotalSize
;
642 if (CompData
!= NULL
) {
646 return EFI_BUFFER_TOO_SMALL
;
649 // Add the section header for the compressed data
651 CompressionSet
.CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
652 CompressionSet
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
653 CompressionSet
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
654 CompressionSet
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
655 CompressionSet
.CompressionType
= CompressionType
;
656 CompressionSet
.UncompressedLength
= DataSize
;
659 // Copy header and data to the buffer
661 memcpy (FileBuffer
, &CompressionSet
, sizeof (EFI_COMPRESSION_SECTION
));
662 memcpy (FileBuffer
+ sizeof (CompressionSet
), CompData
, CompSize
);
665 // Make sure section ends on a DWORD boundary
667 while ((TotalSize
& 0x03) != 0) {
668 FileBuffer
[TotalSize
] = 0;
672 *BufferSize
= TotalSize
;
674 if (CompData
!= NULL
) {
690 Removes Parenthesis from around a string
694 String - String to remove parens from
704 if (String
[0] != '(') {
708 for (Index
= 1; String
[Index
] != ')'; Index
++) {
709 String
[Index
- 1] = String
[Index
];
710 if (String
[Index
] == 0) {
715 String
[Index
- 1] = 0;
729 Removes Equal Mark from around a string
733 String - String to remove equal mark from
743 if (String
[0] != '=' && String
[strlen (String
) - 1] != '=') {
747 if (String
[0] == '=') {
749 for (Index
= 1; String
[Index
] != 0; Index
++) {
750 String
[Index
- 1] = String
[Index
];
753 String
[Index
- 1] = 0;
756 if (String
[strlen (String
) - 1] == '=') {
757 String
[strlen (String
) - 1] = 0;
765 ProcessEnvironmentVariable (
773 Converts environment variables to values
777 Buffer - Buffer containing Environment Variable String
779 NewBuffer - Buffer containing value of environment variable
784 Number of characters from Buffer used
790 CHAR8 VariableBuffer
[_MAX_PATH
];
795 while (Buffer
[Index
] != ')') {
796 VariableBuffer
[Index
- 2] = Buffer
[Index
++];
799 VariableBuffer
[Index
- 2] = 0;
802 if (getenv (VariableBuffer
) != NULL
) {
803 strcpy (NewBuffer
, getenv (VariableBuffer
));
805 printf ("Environment variable %s not found!\n", VariableBuffer
);
813 SplitAttributesField (
815 IN CHAR8
*AttributesArray
[],
816 IN OUT UINT32
*NumberOfAttributes
819 NumberOfAttributes: on input, it specifies the current number of attributes
820 stored in AttributeArray.
821 on output, it is updated to the latest number of attributes
822 stored in AttributesArray.
831 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
832 ZeroMem (CharBuffer
, _MAX_PATH
);
834 for (Index
= 0, z
= 0, Index2
= 0; Index
< strlen (Buffer
); Index
++) {
836 if (Buffer
[Index
] != '|') {
837 CharBuffer
[z
] = Buffer
[Index
];
842 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
846 // allocate new char buffer for the next attributes string
848 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
849 ZeroMem (CharBuffer
, _MAX_PATH
);
856 // record the last attributes string in the Buffer
858 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
861 *NumberOfAttributes
+= Index2
;
869 CHAR8
*ToolArgumentsArray
[],
871 CHAR8
**PtrInputFileName
,
872 CHAR8
**PtrOutputFileName
,
874 UINT16
*GuidedSectionAttributes
877 CHAR8 Buffer
[_MAX_PATH
];
878 BOOLEAN ArgumentsFlag
;
882 BOOLEAN AttributesFlag
;
891 CHAR8
*AttributesArray
[MAX_ARRAY_SIZE
];
892 UINT32 NumberOfAttributes
;
893 CHAR8
*InputFileName
;
894 CHAR8
*OutputFileName
;
898 ArgumentsFlag
= FALSE
;
902 AttributesFlag
= FALSE
;
904 // Start at 1, since ToolArgumentsArray[0]
905 // is the program name.
912 NumberOfAttributes
= 0;
913 InputFileName
= NULL
;
914 OutputFileName
= NULL
;
916 ZeroMem (Buffer
, _MAX_PATH
);
917 ZeroMem (AttributesArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
919 while (Buffer
[0] != ')') {
921 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
922 CheckSlash (Buffer
, Package
, &LineNumber
);
923 StripEqualMark (Buffer
);
925 Error (NULL
, 0, 0, "failed to get next line from package file", NULL
);
929 if (Buffer
[0] == ')') {
931 } else if (strcmpi (Buffer
, "ARGS") == 0) {
933 ArgumentsFlag
= TRUE
;
934 AttributesFlag
= FALSE
;
937 } else if (strcmpi (Buffer
, "INPUT") == 0) {
940 ArgumentsFlag
= FALSE
;
941 AttributesFlag
= FALSE
;
944 } else if (strcmpi (Buffer
, "OUTPUT") == 0) {
947 ArgumentsFlag
= FALSE
;
948 AttributesFlag
= FALSE
;
951 } else if (strcmpi (Buffer
, "GUID") == 0) {
954 ArgumentsFlag
= FALSE
;
955 AttributesFlag
= FALSE
;
957 // fetch the GUID for the section
961 } else if (strcmpi (Buffer
, "ATTRIBUTES") == 0) {
963 AttributesFlag
= TRUE
;
964 ArgumentsFlag
= FALSE
;
966 // fetch the GUIDed Section's Attributes
970 } else if (strcmpi (Buffer
, "") == 0) {
974 // get all command arguments into ToolArgumentsArray
978 StripEqualMark (Buffer
);
980 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
981 if (CharBuffer
== NULL
) {
985 ZeroMem (CharBuffer
, sizeof (_MAX_PATH
));
987 ToolArgumentsArray
[argc
] = CharBuffer
;
989 if (Buffer
[0] == '$') {
990 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolArgumentsArray
[argc
]);
992 // if there is string after the environment variable, cat it.
994 if ((UINT32
) Index
< strlen (Buffer
)) {
995 strcat (ToolArgumentsArray
[argc
], &Buffer
[Index
]);
998 strcpy (ToolArgumentsArray
[argc
], Buffer
);
1002 ToolArgumentsArray
[argc
] = NULL
;
1008 StripEqualMark (Buffer
);
1010 InputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1011 if (InputFileName
== NULL
) {
1015 ZeroMem (InputFileName
, sizeof (_MAX_PATH
));
1017 if (Buffer
[0] == '$') {
1018 Index
= ProcessEnvironmentVariable (&Buffer
[0], InputFileName
);
1020 // if there is string after the environment variable, cat it.
1022 if ((UINT32
) Index
< strlen (Buffer
)) {
1023 strcat (InputFileName
, &Buffer
[Index
]);
1026 strcpy (InputFileName
, Buffer
);
1035 StripEqualMark (Buffer
);
1037 OutputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1038 if (OutputFileName
== NULL
) {
1042 ZeroMem (OutputFileName
, sizeof (_MAX_PATH
));
1044 if (Buffer
[0] == '$') {
1045 Index
= ProcessEnvironmentVariable (&Buffer
[0], OutputFileName
);
1047 // if there is string after the environment variable, cat it.
1049 if ((UINT32
) Index
< strlen (Buffer
)) {
1050 strcat (OutputFileName
, &Buffer
[Index
]);
1053 strcpy (OutputFileName
, Buffer
);
1062 StripEqualMark (Buffer
);
1064 Status
= StringToGuid (Buffer
, Guid
);
1065 if (EFI_ERROR (Status
)) {
1073 if (AttributesFlag
) {
1075 StripEqualMark (Buffer
);
1078 // there might be no space between each attribute in the statement,
1079 // split them aside and return each attribute string
1080 // in the AttributesArray
1082 SplitAttributesField (Buffer
, AttributesArray
, &NumberOfAttributes
);
1086 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1087 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1089 for (z
= 0; z
< NumberOfAttributes
; z
++) {
1090 if (strcmpi (AttributesArray
[z
], "PROCESSING_REQUIRED") == 0) {
1091 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1092 } else if (strcmpi (AttributesArray
[z
], "AUTH_STATUS_VALID") == 0) {
1093 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1099 for (Index2
= 0; Index2
< MAX_ARRAY_SIZE
; Index2
++) {
1100 if (AttributesArray
[Index2
] == NULL
) {
1104 free (AttributesArray
[Index2
]);
1107 *PtrInputFileName
= InputFileName
;
1108 *PtrOutputFileName
= OutputFileName
;
1116 IN OUT UINT8
*FileBuffer
,
1118 IN CHAR8
*BuildDirectory
,
1119 IN BOOLEAN ForceUncompress
1123 Routine Description:
1125 Signs the section, data stays in same location
1129 FileBuffer - Data Buffer
1131 Package - Points to curly brace in Image Script
1133 BuildDirectory - Name of the source directory parameter
1135 ForceUncompress - Whether to force uncompress.
1139 Number of bytes added to file buffer
1146 CHAR8 Buffer
[_MAX_PATH
];
1147 CHAR8 Type
[_MAX_PATH
];
1148 CHAR8 FileName
[_MAX_PATH
];
1149 CHAR8 NewBuffer
[_MAX_PATH
];
1155 UINT32 SourceDataSize
;
1156 CHAR8
*ToolArgumentsArray
[MAX_ARRAY_SIZE
];
1157 CHAR8
*OutputFileName
;
1158 CHAR8
*InputFileName
;
1159 CHAR8 ToolName
[_MAX_PATH
];
1168 UINT16 GuidedSectionAttributes
;
1169 UINT8
*TargetFileBuffer
;
1171 OutputFileName
= NULL
;
1172 InputFileName
= NULL
;
1176 GuidedSectionAttributes
= 0;
1177 TargetFileBuffer
= NULL
;
1182 for (Index3
= 0; Index3
< MAX_ARRAY_SIZE
; ++Index3
) {
1183 ToolArgumentsArray
[Index3
] = NULL
;
1186 while (Buffer
[0] != '}') {
1187 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1188 CheckSlash (Buffer
, Package
, &LineNumber
);
1190 printf ("ERROR in IMAGE SCRIPT!\n");
1195 if (strcmpi (Buffer
, "Compress") == 0) {
1200 // read compression type
1202 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1203 CheckSlash (Buffer
, Package
, &LineNumber
);
1206 StripParens (Buffer
);
1207 if (Buffer
[0] == '$') {
1208 ProcessEnvironmentVariable (&Buffer
[0], Type
);
1210 strcpy (Type
, Buffer
);
1215 while (Buffer
[0] != '{') {
1216 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1217 CheckSlash (Buffer
, Package
, &LineNumber
);
1221 ReturnValue
= ProcessScript (&FileBuffer
[Size
], Package
, BuildDirectory
, ForceUncompress
);
1222 if (ReturnValue
== -1) {
1227 // Call compress routine on buffer.
1228 // Occasionally, compressed data + section header would
1229 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1230 // returned from CompressSection()
1232 SourceDataSize
= ReturnValue
;
1234 if (!ForceUncompress
) {
1236 Status
= CompressSection (
1243 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1244 Status
= CompressSection (
1252 if (EFI_ERROR (Status
)) {
1258 Size
+= ReturnValue
;
1260 } else if (strcmpi (Buffer
, "Tool") == 0) {
1262 ZeroMem (ToolName
, _MAX_PATH
);
1263 ZeroMem (ToolArgumentsArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
1264 ZeroMem (&SignGuid
, sizeof (EFI_GUID
));
1267 // handle signing Tool
1269 while (Buffer
[0] != '(') {
1270 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1271 CheckSlash (Buffer
, Package
, &LineNumber
);
1275 if (strcmpi (Buffer
, "(") == 0) {
1276 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1277 CheckSlash (Buffer
, Package
, &LineNumber
);
1281 StripParens (Buffer
);
1283 if (Buffer
[0] == '$') {
1284 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolName
);
1286 // if there is string after the environment variable, cat it.
1288 if ((UINT32
) Index
< strlen (Buffer
)) {
1289 strcat (ToolName
, &Buffer
[Index
]);
1292 strcpy (ToolName
, Buffer
);
1295 ToolArgumentsArray
[0] = ToolName
;
1300 if (GetToolArguments (
1306 &GuidedSectionAttributes
1312 // if the tool need input file,
1313 // dump the file buffer to the specified input file.
1315 if (InputFileName
!= NULL
) {
1316 InputFile
= fopen (InputFileName
, "wb");
1317 if (InputFile
== NULL
) {
1318 Error (NULL
, 0, 0, InputFileName
, "failed to open output file for writing");
1323 fwrite (FileBuffer
, sizeof (UINT8
), Size
, InputFile
);
1326 free (InputFileName
);
1327 InputFileName
= NULL
;
1330 // dispatch signing tool
1334 char CommandLine
[1000];
1335 sprintf(CommandLine
, "%s %s", ToolName
, ToolArgumentsArray
);
1336 returnint
= system(CommandLine
);
1339 returnint
= _spawnv (_P_WAIT
, ToolName
, ToolArgumentsArray
);
1341 if (returnint
!= 0) {
1342 Error (NULL
, 0, 0, ToolName
, "external tool failed");
1347 // if the tool has output file,
1348 // dump the output file to the file buffer
1350 if (OutputFileName
!= NULL
) {
1352 OutputFile
= fopen (OutputFileName
, "rb");
1353 if (OutputFile
== NULL
) {
1354 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file for writing");
1359 TargetFileBuffer
= &FileBuffer
[Size
];
1360 SourceDataSize
= Size
;
1362 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1363 while (!feof (OutputFile
)) {
1364 FileBuffer
[Size
++] = Temp
;
1365 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1368 while ((Size
& 0x03) != 0) {
1369 FileBuffer
[Size
] = 0;
1373 SourceDataSize
= Size
- SourceDataSize
;
1375 fclose (OutputFile
);
1377 free (OutputFileName
);
1378 OutputFileName
= NULL
;
1380 if (CompareGuid (&SignGuid
, &mZeroGuid
) != 0) {
1381 ReturnValue
= SourceDataSize
;
1382 Status
= GenSimpleGuidSection (
1387 GuidedSectionAttributes
1389 if (EFI_ERROR (Status
)) {
1398 } else if (Buffer
[0] != '}') {
1400 // if we are here, we should see either a file name,
1406 // Prepend the build directory to the file name if the
1407 // file name does not already contain a full path.
1409 if (!isalpha (Buffer
[0]) || (Buffer
[1] != ':')) {
1410 sprintf (FileName
, "%s\\", BuildDirectory
);
1413 while (Buffer
[Index3
] != '\n') {
1414 if (Buffer
[Index3
] == '$') {
1415 Index3
+= ProcessEnvironmentVariable (&Buffer
[Index3
], NewBuffer
);
1416 strcat (FileName
, NewBuffer
);
1419 if (Buffer
[Index3
] == 0) {
1422 Index2
= strlen (FileName
);
1423 FileName
[Index2
++] = Buffer
[Index3
++];
1424 FileName
[Index2
] = 0;
1428 InFile
= fopen (FileName
, "rb");
1429 if (InFile
== NULL
) {
1430 Error (NULL
, 0, 0, FileName
, "failed to open file for reading");
1435 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1436 while (!feof (InFile
)) {
1437 FileBuffer
[Size
++] = ByteBuffer
;
1438 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1445 // Make sure section ends on a DWORD boundary
1447 while ((Size
& 0x03) != 0) {
1448 FileBuffer
[Size
] = 0;
1456 for (Index3
= 1; Index3
< MAX_ARRAY_SIZE
; Index3
++) {
1457 if (ToolArgumentsArray
[Index3
] == NULL
) {
1461 free (ToolArgumentsArray
[Index3
]);
1479 Routine Description:
1481 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1482 unrecognized file type was specified.
1486 String - File type string
1494 if (strcmpi (String
, "EFI_FV_FILETYPE_RAW") == 0) {
1495 return EFI_FV_FILETYPE_RAW
;
1498 if (strcmpi (String
, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1499 return EFI_FV_FILETYPE_FREEFORM
;
1502 if (strcmpi (String
, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1503 return EFI_FV_FILETYPE_SECURITY_CORE
;
1506 if (strcmpi (String
, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1507 return EFI_FV_FILETYPE_PEI_CORE
;
1510 if (strcmpi (String
, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1511 return EFI_FV_FILETYPE_DXE_CORE
;
1514 if (strcmpi (String
, "EFI_FV_FILETYPE_PEIM") == 0) {
1515 return EFI_FV_FILETYPE_PEIM
;
1518 if (strcmpi (String
, "EFI_FV_FILETYPE_DRIVER") == 0) {
1519 return EFI_FV_FILETYPE_DRIVER
;
1522 if (strcmpi (String
, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1523 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
1526 if (strcmpi (String
, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1527 return EFI_FV_FILETYPE_APPLICATION
;
1530 if (strcmpi (String
, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1531 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
1534 return EFI_FV_FILETYPE_ALL
;
1540 IN UINT8
*FileBuffer
,
1545 Routine Description:
1546 Adjusts file size to insure sectioned file is exactly the right length such
1547 that it ends on exactly the last byte of the last section. ProcessScript()
1548 may have padded beyond the end of the last section out to a 4 byte boundary.
1549 This padding is stripped.
1552 FileBuffer - Data Buffer - contains a section stream
1553 FileSize - Size of FileBuffer as returned from ProcessScript()
1556 Corrected size of file.
1561 UINT32 CurrentLength
;
1562 UINT32 SectionLength
;
1563 UINT32 SectionStreamLength
;
1564 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1565 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1569 SectionStreamLength
= FileSize
;
1571 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) FileBuffer
;
1573 while (TotalLength
< SectionStreamLength
) {
1574 SectionLength
= *((UINT32
*) SectionHeader
->Size
) & 0x00ffffff;
1575 TotalLength
+= SectionLength
;
1577 if (TotalLength
== SectionStreamLength
) {
1581 // Move to the next byte following the section...
1583 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1584 CurrentLength
= (UINTN
) SectionHeader
- (UINTN
) FileBuffer
;
1587 // Figure out where the next section begins
1589 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ 3);
1590 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
&~ (UINTN
) 3);
1591 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1592 SectionHeader
= NextSectionHeader
;
1595 return CurrentLength
;
1603 BOOLEAN ForceUncompress
1607 Routine Description:
1613 argc - Number of command line parameters.
1614 argv - Array of pointers to command line parameter strings.
1615 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1616 is specified in the script. Otherwise, FALSE.
1619 STATUS_SUCCESS - Function exits successfully.
1620 STATUS_ERROR - Some error occurred during execution.
1624 FILE *PrimaryPackage
;
1625 FILE *OverridePackage
;
1627 CHAR8 BaseName
[_MAX_PATH
];
1629 CHAR8 GuidString
[_MAX_PATH
];
1630 EFI_FFS_FILE_HEADER FileHeader
;
1631 CHAR8 FileType
[_MAX_PATH
];
1632 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
1633 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined
;
1634 UINT64 FfsAlignment
;
1635 UINT32 FfsAlignment32
;
1636 CHAR8 InputString
[_MAX_PATH
];
1637 BOOLEAN ImageScriptInOveride
;
1642 EFI_FFS_FILE_TAIL TailValue
;
1647 FfsAttribDefined
= 0;
1650 PrimaryPackage
= NULL
;
1652 OverridePackage
= NULL
;
1655 strcpy (GuidString
, "00000000-0000-0000-0000-000000000000");
1656 Status
= StringToGuid (GuidString
, &FfsGuid
);
1658 Error (NULL
, 0, 0, GuidString
, "error parsing GUID string");
1659 return STATUS_ERROR
;
1663 ImageScriptInOveride
= FALSE
;
1665 // Initialize the simple file parsing routines. Then open
1666 // the primary package file for parsing.
1669 if (SFPOpenFile (mGlobals
.PrimaryPackagePath
) != STATUS_SUCCESS
) {
1670 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
1674 // First token in the file must be "PACKAGE.INF"
1676 if (!SFPIsToken ("PACKAGE.INF")) {
1677 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL
);
1681 // Find the [.] section
1683 if (!SFPSkipToToken ("[.]")) {
1684 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "could not locate [.] section in package file", NULL
);
1688 // Start parsing the data. The algorithm is essentially the same for each keyword:
1689 // 1. Identify the keyword
1690 // 2. Verify that the keyword/value pair has not already been defined
1691 // 3. Set some flag indicating that the keyword/value pair has been defined
1692 // 4. Skip over the "="
1693 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1696 if (SFPIsToken ("BASE_NAME")) {
1698 // Found BASE_NAME, format:
1699 // BASE_NAME = MyBaseName
1701 if (BaseName
[0] != 0) {
1702 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL
);
1706 if (!SFPIsToken ("=")) {
1707 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1711 if (!SFPGetNextToken (BaseName
, sizeof (BaseName
))) {
1712 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid base name", NULL
);
1715 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1717 // Found IMAGE_SCRIPT. Break out and process below.
1720 } else if (SFPIsToken ("FFS_FILEGUID")) {
1722 // found FILEGUID, format:
1723 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1725 if (GuidString
[0] != 0) {
1726 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL
);
1730 if (!SFPIsToken ("=")) {
1731 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1735 if (SFPGetGuidToken (GuidString
, sizeof (GuidString
)) != TRUE
) {
1736 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected file GUID", NULL
);
1740 Status
= StringToGuid (GuidString
, &FfsGuid
);
1742 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid file GUID", NULL
);
1745 } else if (SFPIsToken ("FFS_FILETYPE")) {
1747 // ***********************************************************************
1749 // Found FFS_FILETYPE, format:
1750 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1752 if (FileType
[0] != 0) {
1753 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL
);
1757 if (!SFPIsToken ("=")) {
1758 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1762 if (!SFPGetNextToken (FileType
, sizeof (FileType
))) {
1763 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL
);
1766 } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1768 // ***********************************************************************
1770 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1771 // Spec says the bit is for future expansion, and must be false.
1773 if (FfsAttribDefined
& FFS_ATTRIB_HEADER_EXTENSION
) {
1775 mGlobals
.PrimaryPackagePath
,
1776 SFPGetLineNumber (),
1778 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1784 FfsAttribDefined
|= FFS_ATTRIB_HEADER_EXTENSION
;
1785 if (!SFPIsToken ("=")) {
1786 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1790 if (SFPIsToken ("TRUE")) {
1792 mGlobals
.PrimaryPackagePath
,
1793 SFPGetLineNumber (),
1795 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1799 } else if (SFPIsToken ("FALSE")) {
1804 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL
);
1807 } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1809 // ***********************************************************************
1811 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1813 if (FfsAttribDefined
& FFS_ATTRIB_TAIL_PRESENT
) {
1814 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL
);
1818 FfsAttribDefined
|= FFS_ATTRIB_TAIL_PRESENT
;
1819 if (!SFPIsToken ("=")) {
1820 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1824 if (SFPIsToken ("TRUE")) {
1825 FfsAttrib
|= FFS_ATTRIB_TAIL_PRESENT
;
1826 } else if (SFPIsToken ("FALSE")) {
1831 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1834 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1836 // ***********************************************************************
1838 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1840 if (FfsAttribDefined
& FFS_ATTRIB_RECOVERY
) {
1841 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL
);
1845 FfsAttribDefined
|= FFS_ATTRIB_RECOVERY
;
1846 if (!SFPIsToken ("=")) {
1847 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1851 if (SFPIsToken ("TRUE")) {
1852 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
1853 } else if (SFPIsToken ("FALSE")) {
1858 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1861 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1863 // ***********************************************************************
1865 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1867 if (FfsAttribDefined
& FFS_ATTRIB_CHECKSUM
) {
1868 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL
);
1872 FfsAttribDefined
|= FFS_ATTRIB_CHECKSUM
;
1873 if (!SFPIsToken ("=")) {
1874 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1878 if (SFPIsToken ("TRUE")) {
1879 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
1880 } else if (SFPIsToken ("FALSE")) {
1885 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1888 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1890 // ***********************************************************************
1892 // Found FFS_ALIGNMENT, formats:
1893 // FFS_ALIGNMENT = 0-7
1894 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1896 if (FfsAttribDefined
& FFS_ATTRIB_DATA_ALIGNMENT
) {
1898 mGlobals
.PrimaryPackagePath
,
1899 SFPGetLineNumber (),
1901 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1907 FfsAttribDefined
|= FFS_ATTRIB_DATA_ALIGNMENT
;
1908 if (!SFPIsToken ("=")) {
1909 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1913 if (!SFPGetNumber (&FfsAlignment32
)) {
1914 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL
);
1918 if (FfsAlignment32
> 7) {
1919 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL
);
1923 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment32
) << 3);
1925 SFPGetNextToken (InputString
, sizeof (InputString
));
1926 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, InputString
, "unrecognized/unexpected token");
1931 // Close the primary package file
1935 // TODO: replace code below with basically a copy of the code above. Don't
1936 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1937 // to somehow keep track of whether or not the basename is defined multiple
1938 // times in the override package. Ditto on the file GUID.
1940 if (mGlobals
.OverridePackagePath
[0] != 0) {
1941 OverridePackage
= fopen (mGlobals
.OverridePackagePath
, "r");
1943 // NOTE: For package override to work correctly, the code below must be modified to
1944 // SET or CLEAR bits properly. For example, if the primary package set
1945 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1946 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1947 // the override functionality is not being used, so should be made obsolete. If I'm
1948 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1949 // used, and we'll address it then. 4/10/2003
1951 Error (__FILE__
, __LINE__
, 0, "package override functionality is not implemented correctly", NULL
);
1954 OverridePackage
= NULL
;
1957 #ifdef OVERRIDE_SUPPORTED
1958 if (OverridePackage
!= NULL
) {
1960 // Parse override package file
1962 fscanf (OverridePackage
, "%s", &InputString
);
1963 if (strcmpi (InputString
, "PACKAGE.INF") != 0) {
1964 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
1968 // Match [dir] to Build Directory
1970 if (FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
) != 0) {
1971 Error (mGlobals
.OverridePackagePath
, 1, 0, mGlobals
.BuildDirectory
, "section not found in package file");
1976 while ((InputString
[0] != '[') && (!feof (OverridePackage
))) {
1977 if (GetNextLine (InputString
, OverridePackage
, &LineNumber
) != -1) {
1978 if (InputString
[0] != '[') {
1980 if (strcmpi (InputString
, "BASE_NAME") == 0) {
1982 // found BASE_NAME, next is = and string.
1984 fscanf (OverridePackage
, "%s", &InputString
);
1985 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1986 if (strlen (InputString
) == 1) {
1990 fscanf (OverridePackage
, "%s", &InputString
);
1991 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1992 strcpy (BaseName
, InputString
);
1994 BreakString (InputString
, InputString
, 1);
1995 strcpy (BaseName
, InputString
);
1997 } else if (strcmpi (InputString
, "IMAGE_SCRIPT") == 0) {
1999 // found IMAGE_SCRIPT, come back later to process it
2001 ImageScriptInOveride
= TRUE
;
2002 fscanf (OverridePackage
, "%s", &InputString
);
2003 } else if (strcmpi (InputString
, "FFS_FILEGUID") == 0) {
2005 // found FILEGUID, next is = and string.
2007 fscanf (OverridePackage
, "%s", &InputString
);
2008 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2009 if (strlen (InputString
) == 1) {
2013 fscanf (OverridePackage
, "%s", &InputString
);
2014 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2015 Status
= StringToGuid (InputString
, &FfsGuid
);
2017 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2021 BreakString (InputString
, InputString
, 1);
2022 Status
= StringToGuid (InputString
, &FfsGuid
);
2024 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2028 } else if (strcmpi (InputString
, "FFS_FILETYPE") == 0) {
2030 // found FILETYPE, next is = and string.
2032 fscanf (OverridePackage
, "%s", &InputString
);
2033 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2034 if (strlen (InputString
) == 1) {
2038 fscanf (OverridePackage
, "%s", &InputString
);
2039 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2040 strcpy (FileType
, InputString
);
2042 BreakString (InputString
, InputString
, 1);
2043 strcpy (FileType
, InputString
);
2046 } else if (strcmpi (InputString
, "FFS_ATTRIB_RECOVERY") == 0) {
2048 // found FFS_ATTRIB_RECOVERY, next is = and string.
2050 fscanf (OverridePackage
, "%s", &InputString
);
2051 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2052 if (strlen (InputString
) == 1) {
2056 fscanf (OverridePackage
, "%s", &InputString
);
2057 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2058 if (strcmpi (InputString
, "TRUE") == 0) {
2059 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2062 BreakString (InputString
, InputString
, 1);
2063 if (strcmpi (InputString
, "TRUE") == 0) {
2064 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2067 } else if (strcmpi (InputString
, "FFS_ATTRIB_CHECKSUM") == 0) {
2069 // found FFS_ATTRIB_CHECKSUM, next is = and string.
2071 fscanf (OverridePackage
, "%s", &InputString
);
2072 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2073 if (strlen (InputString
) == 1) {
2077 fscanf (OverridePackage
, "%s", &InputString
);
2078 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2079 if (strcmpi (InputString
, "TRUE") == 0) {
2080 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2083 BreakString (InputString
, InputString
, 1);
2084 if (strcmpi (InputString
, "TRUE") == 0) {
2085 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2088 } else if (strcmpi (InputString
, "FFS_ALIGNMENT") == 0) {
2090 // found FFS_ALIGNMENT, next is = and string.
2092 fscanf (OverridePackage
, "%s", &InputString
);
2093 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2094 if (strlen (InputString
) == 1) {
2098 fscanf (OverridePackage
, "%s", &InputString
);
2099 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2101 BreakString (InputString
, InputString
, 1);
2104 AsciiStringToUint64 (InputString
, FALSE
, &FfsAlignment
);
2105 if (FfsAlignment
> 7) {
2106 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "invalid FFS_ALIGNMENT value");
2110 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment
) << 3);
2111 } else if (strchr (InputString
, '=') != NULL
) {
2112 BreakString (InputString
, String
, 1);
2113 fseek (OverridePackage
, (-1 * (strlen (String
) + 1)), SEEK_CUR
);
2114 BreakString (InputString
, InputString
, 0);
2121 #endif // #ifdef OVERRIDE_SUPPORTED
2123 // Require that they specified a file GUID at least, since that's how we're
2126 if (GuidString
[0] == 0) {
2127 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "FFS_FILEGUID must be specified", NULL
);
2128 return STATUS_ERROR
;
2131 // Build Header and process image script
2133 FileBuffer
= (UINT8
*) malloc ((1024 * 1024 * 16) * sizeof (UINT8
));
2134 if (FileBuffer
== NULL
) {
2135 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
2140 if (ImageScriptInOveride
) {
2141 #ifdef OVERRIDE_SUPORTED
2142 rewind (OverridePackage
);
2144 FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
);
2145 while (strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2146 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2147 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2148 if (strchr (InputString
, '=') != NULL
) {
2149 BreakString (InputString
, InputString
, 0);
2153 while (InputString
[0] != '{') {
2154 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2155 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2158 // Found start of image script, process it
2160 FileSize
+= ProcessScript (FileBuffer
, OverridePackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2161 if (FileSize
== -1) {
2165 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2166 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2169 if (BaseName
[0] == '\"') {
2170 StripQuotes (BaseName
);
2173 if (BaseName
[0] != 0) {
2174 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2176 strcpy (InputString
, GuidString
);
2179 switch (StringToType (FileType
)) {
2181 case EFI_FV_FILETYPE_SECURITY_CORE
:
2182 strcat (InputString
, ".SEC");
2185 case EFI_FV_FILETYPE_PEIM
:
2186 case EFI_FV_FILETYPE_PEI_CORE
:
2187 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2188 strcat (InputString
, ".PEI");
2191 case EFI_FV_FILETYPE_DRIVER
:
2192 case EFI_FV_FILETYPE_DXE_CORE
:
2193 strcat (InputString
, ".DXE");
2196 case EFI_FV_FILETYPE_APPLICATION
:
2197 strcat (InputString
, ".APP");
2200 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2201 strcat (InputString
, ".FVI");
2204 case EFI_FV_FILETYPE_ALL
:
2205 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2209 strcat (InputString
, ".FFS");
2213 if (ForceUncompress
) {
2214 strcat (InputString
, ".ORG");
2217 Out
= fopen (InputString
, "wb");
2219 Error (NULL
, 0, 0, InputString
, "could not open output file for writing");
2223 // create ffs header
2225 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2226 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2227 FileHeader
.Type
= StringToType (FileType
);
2228 FileHeader
.Attributes
= FfsAttrib
;
2230 // Now FileSize includes the EFI_FFS_FILE_HEADER
2232 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2233 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2234 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2235 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2237 // Fill in checksums and state, these must be zero for checksumming
2239 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2240 // FileHeader.IntegrityCheck.Checksum.File = 0;
2241 // FileHeader.State = 0;
2243 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2244 (UINT8
*) &FileHeader
,
2245 sizeof (EFI_FFS_FILE_HEADER
)
2247 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2248 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) &FileHeader
, FileSize
);
2250 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2253 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2257 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2258 Error (NULL
, 0, 0, "failed to write file header to output file", NULL
);
2264 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2265 Error (NULL
, 0, 0, "failed to write all bytes to output file", NULL
);
2271 #endif // #ifdef OVERRIDE_SUPPORTED
2274 // Open primary package file and process the IMAGE_SCRIPT section
2276 PrimaryPackage
= fopen (mGlobals
.PrimaryPackagePath
, "r");
2277 if (PrimaryPackage
== NULL
) {
2278 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
2283 FindSectionInPackage (".", PrimaryPackage
, &LineNumber
);
2284 while (strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2285 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2286 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2287 if (strchr (InputString
, '=') != NULL
) {
2288 BreakString (InputString
, InputString
, 0);
2292 while (InputString
[0] != '{') {
2293 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2294 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2297 // Found start of image script, process it
2299 FileSize
+= ProcessScript (FileBuffer
, PrimaryPackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2300 if (FileSize
== -1) {
2304 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2305 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2308 if (BaseName
[0] == '\"') {
2309 StripQuotes (BaseName
);
2312 if (BaseName
[0] != 0) {
2313 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2315 strcpy (InputString
, GuidString
);
2318 switch (StringToType (FileType
)) {
2320 case EFI_FV_FILETYPE_SECURITY_CORE
:
2321 strcat (InputString
, ".SEC");
2324 case EFI_FV_FILETYPE_PEIM
:
2325 case EFI_FV_FILETYPE_PEI_CORE
:
2326 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2327 strcat (InputString
, ".PEI");
2330 case EFI_FV_FILETYPE_DRIVER
:
2331 case EFI_FV_FILETYPE_DXE_CORE
:
2332 strcat (InputString
, ".DXE");
2335 case EFI_FV_FILETYPE_APPLICATION
:
2336 strcat (InputString
, ".APP");
2339 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2340 strcat (InputString
, ".FVI");
2343 case EFI_FV_FILETYPE_ALL
:
2344 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2348 strcat (InputString
, ".FFS");
2352 if (ForceUncompress
) {
2353 strcat (InputString
, ".ORG");
2356 Out
= fopen (InputString
, "wb");
2358 Error (NULL
, 0, 0, InputString
, "failed to open output file for writing");
2362 // Initialize the FFS file header
2364 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2365 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2366 FileHeader
.Type
= StringToType (FileType
);
2367 FileHeader
.Attributes
= FfsAttrib
;
2369 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2371 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2373 // If using a tail, then it adds two bytes
2375 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2377 // Tail is not allowed for pad and 0-length files
2379 if ((FileHeader
.Type
== EFI_FV_FILETYPE_FFS_PAD
) || (FileSize
== sizeof (EFI_FFS_FILE_HEADER
))) {
2381 mGlobals
.PrimaryPackagePath
,
2384 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2390 FileSize
+= sizeof (EFI_FFS_FILE_TAIL
);
2393 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2394 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2395 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2397 // Fill in checksums and state, they must be 0 for checksumming.
2399 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2400 // FileHeader.IntegrityCheck.Checksum.File = 0;
2401 // FileHeader.State = 0;
2403 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2404 (UINT8
*) &FileHeader
,
2405 sizeof (EFI_FFS_FILE_HEADER
)
2407 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2409 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2410 // Checksum does not include the tail
2412 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2413 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2415 FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
)
2418 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2420 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2424 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2427 // Set the state now. Spec says the checksum assumes the state is 0
2429 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2431 // If there is a tail, then set it
2433 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2434 TailValue
= FileHeader
.IntegrityCheck
.TailReference
;
2435 TailValue
= (UINT16
) (~TailValue
);
2437 (UINT8
*) FileBuffer
+ FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
),
2443 // Write the FFS file header
2445 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2446 Error (NULL
, 0, 0, "failed to write file header contents", NULL
);
2452 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2453 Error (NULL
, 0, 0, "failed to write file contents", NULL
);
2464 if (PrimaryPackage
!= NULL
) {
2465 fclose (PrimaryPackage
);
2468 if (FileBuffer
!= NULL
) {
2472 if (OverridePackage
!= NULL
) {
2473 fclose (OverridePackage
);
2476 return GetUtilityStatus ();
2486 Routine Description:
2492 argc - Number of command line parameters.
2493 argv - Array of pointers to parameter strings.
2496 STATUS_SUCCESS - Utility exits successfully.
2497 STATUS_ERROR - Some error occurred during execution.
2503 // Set the name of our utility for error reporting purposes.
2505 SetUtilityName (UTILITY_NAME
);
2506 Status
= ProcessCommandLineArgs (argc
, argv
);
2507 if (Status
!= STATUS_SUCCESS
) {
2511 Status
= MainEntry (argc
, argv
, TRUE
);
2512 if (Status
== STATUS_SUCCESS
) {
2513 MainEntry (argc
, argv
, FALSE
);
2516 // If any errors were reported via the standard error reporting
2517 // routines, then the status has been saved. Get the value and
2518 // return it to the caller.
2520 return GetUtilityStatus ();
2525 ProcessCommandLineArgs (
2531 Routine Description:
2532 Process the command line arguments.
2535 Argc - as passed in to main()
2536 Argv - as passed in to main()
2539 STATUS_SUCCESS - arguments all ok
2540 STATUS_ERROR - problem with args, so caller should exit
2545 // If no args, then print usage instructions and return an error
2549 return STATUS_ERROR
;
2552 memset (&mGlobals
, 0, sizeof (mGlobals
));
2556 if (strcmpi (Argv
[0], "-b") == 0) {
2558 // OPTION: -b BuildDirectory
2559 // Make sure there is another argument, then save it to our globals.
2562 Error (NULL
, 0, 0, "-b option requires the build directory name", NULL
);
2563 return STATUS_ERROR
;
2566 if (mGlobals
.BuildDirectory
[0]) {
2567 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2568 return STATUS_ERROR
;
2571 strcpy (mGlobals
.BuildDirectory
, Argv
[1]);
2574 } else if (strcmpi (Argv
[0], "-p1") == 0) {
2576 // OPTION: -p1 PrimaryPackageFile
2577 // Make sure there is another argument, then save it to our globals.
2580 Error (NULL
, 0, 0, Argv
[0], "option requires the primary package file name");
2581 return STATUS_ERROR
;
2584 if (mGlobals
.PrimaryPackagePath
[0]) {
2585 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2586 return STATUS_ERROR
;
2589 strcpy (mGlobals
.PrimaryPackagePath
, Argv
[1]);
2592 } else if (strcmpi (Argv
[0], "-p2") == 0) {
2594 // OPTION: -p2 OverridePackageFile
2595 // Make sure there is another argument, then save it to our globals.
2598 Error (NULL
, 0, 0, Argv
[0], "option requires the override package file name");
2599 return STATUS_ERROR
;
2602 if (mGlobals
.OverridePackagePath
[0]) {
2603 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2604 return STATUS_ERROR
;
2607 strcpy (mGlobals
.OverridePackagePath
, Argv
[1]);
2610 } else if (strcmpi (Argv
[0], "-v") == 0) {
2612 // OPTION: -v verbose
2614 mGlobals
.Verbose
= TRUE
;
2615 } else if (strcmpi (Argv
[0], "-h") == 0) {
2620 return STATUS_ERROR
;
2621 } else if (strcmpi (Argv
[0], "-?") == 0) {
2626 return STATUS_ERROR
;
2628 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
2630 return STATUS_ERROR
;
2637 // Must have at least specified the package file name
2639 if (mGlobals
.PrimaryPackagePath
[0] == 0) {
2640 Error (NULL
, 0, 0, "must specify primary package file", NULL
);
2641 return STATUS_ERROR
;
2644 return STATUS_SUCCESS
;