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
23 #include "TianoCommon.h"
24 #include "EfiFirmwareFileSystem.h"
25 #include "EfiFirmwareVolumeHeader.h"
26 #include "EfiImageFormat.h"
29 #include "EfiCustomizedCompress.h"
31 #include "GenFfsFile.h"
33 #include <ctype.h> // for isalpha()
35 // include file for _spawnv
40 #include "CommonLib.h"
41 #include "EfiUtilityMsgs.h"
42 #include "SimpleFileParsing.h"
44 #define UTILITY_NAME "GenFfsFile"
45 #define TOOLVERSION "0.32"
46 #define MAX_ARRAY_SIZE 100
51 OUT CHAR8
*Destination
,
53 IN OUT UINT32
*LineNumber
61 IN OUT UINT32
*LineNumber
66 FindSectionInPackage (
67 IN CHAR8
*BuildDirectory
,
68 IN
FILE *OverridePackage
,
69 IN OUT UINT32
*LineNumber
74 ProcessCommandLineArgs (
86 // Keep globals in this structure
89 UINT8 BuildDirectory
[_MAX_PATH
];
90 UINT8 PrimaryPackagePath
[_MAX_PATH
];
91 UINT8 OverridePackagePath
[_MAX_PATH
];
95 static EFI_GUID mZeroGuid
= { 0 };
106 Removes quotes and/or whitespace from around a string
110 String - String to remove quotes from
122 Index2
= strspn (String
, "\" \t\n");
123 StrLen
= strlen (String
);
125 for (Index
= Index2
; String
[Index
] != '\"', Index
< StrLen
; Index
++) {
126 String
[Index
- Index2
] = String
[Index
];
129 String
[Index
- Index2
] = 0;
141 Print Error / Help message.
154 printf (UTILITY_NAME
" -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n");
155 printf (" -b \"build directory\":\n ");
156 printf (" specifies the full path to the component build directory.\n");
157 printf (" -p1 \"P1_path\":\n");
158 printf (" specifies fully qualified file name to the primary package file.\n");
159 printf (" This file will normally exist in the same directory as the makefile\n");
160 printf (" for the component. Required.\n");
161 printf (" -p2 \"P2_path\":\n");
162 printf (" specifies fully qualified file name to the override package file.\n");
163 printf (" This file will normally exist in the build tip. Optional.\n");
176 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
180 String - String to test
182 In - Open file to move pointer within
186 -1 - End of file reached
195 if ((String
[0] == '/') && (String
[1] == '/')) {
196 while (CharBuffer
!= '\n') {
197 fscanf (In
, "%c", &CharBuffer
);
212 IN CONST CHAR8
*Source
,
213 OUT CHAR8
*Destination
,
220 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
224 Source - String to break
226 Destination - Buffer to place new string in
228 Direction - 0 to return all of source string before =
229 1 to return all of source string after =
243 if (strchr (Source
, '=') == NULL
) {
244 strcpy (Destination
, Source
);
249 if (Direction
== 0) {
251 // return part of string before =
253 while (Source
[Index
] != '=') {
254 Destination
[Index
] = Source
[Index
++];
257 Destination
[Index
] = 0;
260 // return part of string after =
262 strcpy (Destination
, strchr (Source
, '=') + 1);
269 OUT CHAR8
*Destination
,
271 IN OUT UINT32
*LineNumber
277 Gets the next non-commented line from the file
281 Destination - Where to put string
283 Package - Package to get string from
285 LineNumber - The actual line number.
289 -1 - End of file reached
294 CHAR8 String
[_MAX_PATH
];
295 fscanf (Package
, "%s", &String
);
296 if (feof (Package
)) {
300 while (TestComment (String
, Package
) == 1) {
301 fscanf (Package
, "%s", &String
);
302 if (feof (Package
)) {
307 strcpy (Destination
, String
);
314 IN OUT CHAR8
*String
,
316 IN OUT UINT32
*LineNumber
322 Checks to see if string is line continuation character, if so goes to next valid line
326 String - String to test
328 In - Open file to move pointer within
330 LineNumber - The line number.
344 while (String
[0] == '\\') {
345 while (ByteBuffer
!= '\n') {
346 fscanf (In
, "%c", &ByteBuffer
);
349 if (GetNextLine (String
, In
, LineNumber
) == -1) {
357 while (String
[0] == '\n') {
358 if (GetNextLine (String
, In
, LineNumber
) == -1) {
373 FindSectionInPackage (
374 IN CHAR8
*BuildDirectory
,
375 IN
FILE *OverridePackage
,
376 IN OUT UINT32
*LineNumber
382 Finds the matching section within the package
386 BuildDirectory - name of section to find
388 OverridePackage - Package file to search within
390 LineNumber - The line number.
394 -1 - End of file reached
399 CHAR8 String
[_MAX_PATH
];
400 CHAR8 NewString
[_MAX_PATH
];
403 while (strcmp (BuildDirectory
, String
) != 0) {
404 if (GetNextLine (NewString
, OverridePackage
, LineNumber
) != 0) {
408 if (NewString
[0] == '[') {
409 if (NewString
[strlen (NewString
) - 1] != ']') {
411 // have to construct string.
413 strcpy (String
, NewString
+ 1);
416 fscanf (OverridePackage
, "%s", &NewString
);
417 if (feof (OverridePackage
)) {
421 if (NewString
[0] != ']') {
422 if (strlen (String
) != 0) {
423 strcat (String
, " ");
426 strcat (String
, NewString
);
427 if (String
[strlen (String
) - 1] == ']') {
428 String
[strlen (String
) - 1] = 0;
436 NewString
[strlen (NewString
) - 1] = 0;
437 strcpy (String
, NewString
+ 1);
447 GenSimpleGuidSection (
448 IN OUT UINT8
*FileBuffer
,
449 IN OUT UINT32
*BufferSize
,
451 IN EFI_GUID SignGuid
,
452 IN UINT16 GuidedSectionAttributes
458 add GUIDed section header for the data buffer.
459 data stays in same location (overwrites source data).
463 FileBuffer - Buffer containing data to sign
465 BufferSize - On input, the size of FileBuffer. On output, the size of
466 actual section data (including added section header).
468 DataSize - Length of data to Sign
470 SignGuid - Guid to be add.
472 GuidedSectionAttributes - The section attribute.
476 EFI_SUCCESS - Successful
477 EFI_OUT_OF_RESOURCES - Not enough resource.
483 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
494 TotalSize
= DataSize
+ sizeof (EFI_GUID_DEFINED_SECTION
);
495 GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
496 GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
497 GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
498 GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
499 memcpy (&(GuidSectionHeader
.SectionDefinitionGuid
), &SignGuid
, sizeof (EFI_GUID
));
500 GuidSectionHeader
.Attributes
= GuidedSectionAttributes
;
501 GuidSectionHeader
.DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
);
503 SwapBuffer
= (UINT8
*) malloc (DataSize
);
504 if (SwapBuffer
== NULL
) {
505 return EFI_OUT_OF_RESOURCES
;
508 memcpy (SwapBuffer
, FileBuffer
, DataSize
);
509 memcpy (FileBuffer
, &GuidSectionHeader
, sizeof (EFI_GUID_DEFINED_SECTION
));
510 memcpy (FileBuffer
+ sizeof (EFI_GUID_DEFINED_SECTION
), SwapBuffer
, DataSize
);
513 // Make sure section ends on a DWORD boundary
515 while ((TotalSize
& 0x03) != 0) {
516 FileBuffer
[TotalSize
] = 0;
520 *BufferSize
= TotalSize
;
522 if (SwapBuffer
!= NULL
) {
541 Compress the data and add section header for the compressed data.
542 Compressed data (with section header) stays in same location as the source
543 (overwrites source data).
547 FileBuffer - Buffer containing data to Compress
549 BufferSize - On input, the size of FileBuffer. On output, the size of
550 actual compressed data (including added section header).
551 When buffer is too small, this value indicates the size needed.
553 DataSize - The size of data to compress
555 Type - The compression type (not used currently).
556 Assume EFI_HEAVY_COMPRESSION.
560 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
561 EFI_UNSUPPORTED - Compress type can not be supported.
562 EFI_SUCCESS - Successful
563 EFI_OUT_OF_RESOURCES - Not enough resource.
571 EFI_COMPRESSION_SECTION CompressionSet
;
572 UINT8 CompressionType
;
573 COMPRESS_FUNCTION CompressFunction
;
575 Status
= EFI_SUCCESS
;
579 CompressFunction
= NULL
;
582 // Get the compress type
584 if (_strcmpi (Type
, "Dummy") == 0) {
586 // Added "Dummy" to keep backward compatibility.
588 CompressionType
= EFI_STANDARD_COMPRESSION
;
589 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
591 } else if (_strcmpi (Type
, "LZH") == 0) {
593 // EFI stardard compression (LZH)
595 CompressionType
= EFI_STANDARD_COMPRESSION
;
596 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
600 // Customized compression
602 Status
= SetCustomizedCompressionType (Type
);
603 if (EFI_ERROR (Status
)) {
607 CompressionType
= EFI_CUSTOMIZED_COMPRESSION
;
608 CompressFunction
= (COMPRESS_FUNCTION
) CustomizedCompress
;
611 // Compress the raw data
613 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
614 if (Status
== EFI_BUFFER_TOO_SMALL
) {
615 CompData
= malloc (CompSize
);
617 return EFI_OUT_OF_RESOURCES
;
620 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
623 if (EFI_ERROR (Status
)) {
624 if (CompData
!= NULL
) {
631 TotalSize
= CompSize
+ sizeof (EFI_COMPRESSION_SECTION
);
636 if (TotalSize
> *BufferSize
) {
637 *BufferSize
= TotalSize
;
638 if (CompData
!= NULL
) {
642 return EFI_BUFFER_TOO_SMALL
;
645 // Add the section header for the compressed data
647 CompressionSet
.CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
648 CompressionSet
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
649 CompressionSet
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
650 CompressionSet
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
651 CompressionSet
.CompressionType
= CompressionType
;
652 CompressionSet
.UncompressedLength
= DataSize
;
655 // Copy header and data to the buffer
657 memcpy (FileBuffer
, &CompressionSet
, sizeof (EFI_COMPRESSION_SECTION
));
658 memcpy (FileBuffer
+ sizeof (CompressionSet
), CompData
, CompSize
);
661 // Make sure section ends on a DWORD boundary
663 while ((TotalSize
& 0x03) != 0) {
664 FileBuffer
[TotalSize
] = 0;
668 *BufferSize
= TotalSize
;
670 if (CompData
!= NULL
) {
686 Removes Parenthesis from around a string
690 String - String to remove parens from
700 if (String
[0] != '(') {
704 for (Index
= 1; String
[Index
] != ')'; Index
++) {
705 String
[Index
- 1] = String
[Index
];
706 if (String
[Index
] == 0) {
711 String
[Index
- 1] = 0;
725 Removes Equal Mark from around a string
729 String - String to remove equal mark from
739 if (String
[0] != '=' && String
[strlen (String
) - 1] != '=') {
743 if (String
[0] == '=') {
745 for (Index
= 1; String
[Index
] != 0; Index
++) {
746 String
[Index
- 1] = String
[Index
];
749 String
[Index
- 1] = 0;
752 if (String
[strlen (String
) - 1] == '=') {
753 String
[strlen (String
) - 1] = 0;
761 ProcessEnvironmentVariable (
769 Converts environment variables to values
773 Buffer - Buffer containing Environment Variable String
775 NewBuffer - Buffer containing value of environment variable
780 Number of characters from Buffer used
786 CHAR8 VariableBuffer
[_MAX_PATH
];
791 while (Buffer
[Index
] != ')') {
792 VariableBuffer
[Index
- 2] = Buffer
[Index
++];
795 VariableBuffer
[Index
- 2] = 0;
798 if (getenv (VariableBuffer
) != NULL
) {
799 strcpy (NewBuffer
, getenv (VariableBuffer
));
801 printf ("Environment variable %s not found!\n", VariableBuffer
);
809 SplitAttributesField (
811 IN CHAR8
*AttributesArray
[],
812 IN OUT UINT32
*NumberOfAttributes
815 NumberOfAttributes: on input, it specifies the current number of attributes
816 stored in AttributeArray.
817 on output, it is updated to the latest number of attributes
818 stored in AttributesArray.
827 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
828 ZeroMem (CharBuffer
, _MAX_PATH
);
830 for (Index
= 0, z
= 0, Index2
= 0; Index
< strlen (Buffer
); Index
++) {
832 if (Buffer
[Index
] != '|') {
833 CharBuffer
[z
] = Buffer
[Index
];
838 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
842 // allocate new char buffer for the next attributes string
844 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
845 ZeroMem (CharBuffer
, _MAX_PATH
);
852 // record the last attributes string in the Buffer
854 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
857 *NumberOfAttributes
+= Index2
;
865 CHAR8
*ToolArgumentsArray
[],
867 CHAR8
**PtrInputFileName
,
868 CHAR8
**PtrOutputFileName
,
870 UINT16
*GuidedSectionAttributes
873 CHAR8 Buffer
[_MAX_PATH
];
874 BOOLEAN ArgumentsFlag
;
878 BOOLEAN AttributesFlag
;
887 CHAR8
*AttributesArray
[MAX_ARRAY_SIZE
];
888 UINT32 NumberOfAttributes
;
889 CHAR8
*InputFileName
;
890 CHAR8
*OutputFileName
;
894 ArgumentsFlag
= FALSE
;
898 AttributesFlag
= FALSE
;
900 // Start at 1, since ToolArgumentsArray[0]
901 // is the program name.
908 NumberOfAttributes
= 0;
909 InputFileName
= NULL
;
910 OutputFileName
= NULL
;
912 ZeroMem (Buffer
, _MAX_PATH
);
913 ZeroMem (AttributesArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
915 while (Buffer
[0] != ')') {
917 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
918 CheckSlash (Buffer
, Package
, &LineNumber
);
919 StripEqualMark (Buffer
);
921 Error (NULL
, 0, 0, "failed to get next line from package file", NULL
);
925 if (Buffer
[0] == ')') {
927 } else if (_strcmpi (Buffer
, "ARGS") == 0) {
929 ArgumentsFlag
= TRUE
;
930 AttributesFlag
= FALSE
;
933 } else if (_strcmpi (Buffer
, "INPUT") == 0) {
936 ArgumentsFlag
= FALSE
;
937 AttributesFlag
= FALSE
;
940 } else if (_strcmpi (Buffer
, "OUTPUT") == 0) {
943 ArgumentsFlag
= FALSE
;
944 AttributesFlag
= FALSE
;
947 } else if (_strcmpi (Buffer
, "GUID") == 0) {
950 ArgumentsFlag
= FALSE
;
951 AttributesFlag
= FALSE
;
953 // fetch the GUID for the section
957 } else if (_strcmpi (Buffer
, "ATTRIBUTES") == 0) {
959 AttributesFlag
= TRUE
;
960 ArgumentsFlag
= FALSE
;
962 // fetch the GUIDed Section's Attributes
966 } else if (_strcmpi (Buffer
, "") == 0) {
970 // get all command arguments into ToolArgumentsArray
974 StripEqualMark (Buffer
);
976 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
977 if (CharBuffer
== NULL
) {
981 ZeroMem (CharBuffer
, sizeof (_MAX_PATH
));
983 ToolArgumentsArray
[argc
] = CharBuffer
;
985 if (Buffer
[0] == '$') {
986 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolArgumentsArray
[argc
]);
988 // if there is string after the environment variable, cat it.
990 if ((UINT32
) Index
< strlen (Buffer
)) {
991 strcat (ToolArgumentsArray
[argc
], &Buffer
[Index
]);
994 strcpy (ToolArgumentsArray
[argc
], Buffer
);
998 ToolArgumentsArray
[argc
] = NULL
;
1004 StripEqualMark (Buffer
);
1006 InputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1007 if (InputFileName
== NULL
) {
1011 ZeroMem (InputFileName
, sizeof (_MAX_PATH
));
1013 if (Buffer
[0] == '$') {
1014 Index
= ProcessEnvironmentVariable (&Buffer
[0], InputFileName
);
1016 // if there is string after the environment variable, cat it.
1018 if ((UINT32
) Index
< strlen (Buffer
)) {
1019 strcat (InputFileName
, &Buffer
[Index
]);
1022 strcpy (InputFileName
, Buffer
);
1031 StripEqualMark (Buffer
);
1033 OutputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1034 if (OutputFileName
== NULL
) {
1038 ZeroMem (OutputFileName
, sizeof (_MAX_PATH
));
1040 if (Buffer
[0] == '$') {
1041 Index
= ProcessEnvironmentVariable (&Buffer
[0], OutputFileName
);
1043 // if there is string after the environment variable, cat it.
1045 if ((UINT32
) Index
< strlen (Buffer
)) {
1046 strcat (OutputFileName
, &Buffer
[Index
]);
1049 strcpy (OutputFileName
, Buffer
);
1058 StripEqualMark (Buffer
);
1060 Status
= StringToGuid (Buffer
, Guid
);
1061 if (EFI_ERROR (Status
)) {
1069 if (AttributesFlag
) {
1071 StripEqualMark (Buffer
);
1074 // there might be no space between each attribute in the statement,
1075 // split them aside and return each attribute string
1076 // in the AttributesArray
1078 SplitAttributesField (Buffer
, AttributesArray
, &NumberOfAttributes
);
1082 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1083 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1085 for (z
= 0; z
< NumberOfAttributes
; z
++) {
1086 if (_strcmpi (AttributesArray
[z
], "PROCESSING_REQUIRED") == 0) {
1087 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1088 } else if (_strcmpi (AttributesArray
[z
], "AUTH_STATUS_VALID") == 0) {
1089 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1095 for (Index2
= 0; Index2
< MAX_ARRAY_SIZE
; Index2
++) {
1096 if (AttributesArray
[Index2
] == NULL
) {
1100 free (AttributesArray
[Index2
]);
1103 *PtrInputFileName
= InputFileName
;
1104 *PtrOutputFileName
= OutputFileName
;
1112 IN OUT UINT8
*FileBuffer
,
1114 IN CHAR8
*BuildDirectory
,
1115 IN BOOLEAN ForceUncompress
1119 Routine Description:
1121 Signs the section, data stays in same location
1125 FileBuffer - Data Buffer
1127 Package - Points to curly brace in Image Script
1129 BuildDirectory - Name of the source directory parameter
1131 ForceUncompress - Whether to force uncompress.
1135 Number of bytes added to file buffer
1142 CHAR8 Buffer
[_MAX_PATH
];
1143 CHAR8 Type
[_MAX_PATH
];
1144 CHAR8 FileName
[_MAX_PATH
];
1145 CHAR8 NewBuffer
[_MAX_PATH
];
1151 UINT32 SourceDataSize
;
1152 CHAR8
*ToolArgumentsArray
[MAX_ARRAY_SIZE
];
1153 CHAR8
*OutputFileName
;
1154 CHAR8
*InputFileName
;
1155 CHAR8 ToolName
[_MAX_PATH
];
1164 UINT16 GuidedSectionAttributes
;
1165 UINT8
*TargetFileBuffer
;
1167 OutputFileName
= NULL
;
1168 InputFileName
= NULL
;
1172 GuidedSectionAttributes
= 0;
1173 TargetFileBuffer
= NULL
;
1178 for (Index3
= 0; Index3
< MAX_ARRAY_SIZE
; ++Index3
) {
1179 ToolArgumentsArray
[Index3
] = NULL
;
1182 while (Buffer
[0] != '}') {
1183 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1184 CheckSlash (Buffer
, Package
, &LineNumber
);
1186 printf ("ERROR in IMAGE SCRIPT!\n");
1191 if (_strcmpi (Buffer
, "Compress") == 0) {
1196 // read compression type
1198 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1199 CheckSlash (Buffer
, Package
, &LineNumber
);
1202 StripParens (Buffer
);
1203 if (Buffer
[0] == '$') {
1204 ProcessEnvironmentVariable (&Buffer
[0], Type
);
1206 strcpy (Type
, Buffer
);
1211 while (Buffer
[0] != '{') {
1212 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1213 CheckSlash (Buffer
, Package
, &LineNumber
);
1217 ReturnValue
= ProcessScript (&FileBuffer
[Size
], Package
, BuildDirectory
, ForceUncompress
);
1218 if (ReturnValue
== -1) {
1223 // Call compress routine on buffer.
1224 // Occasionally, compressed data + section header would
1225 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1226 // returned from CompressSection()
1228 SourceDataSize
= ReturnValue
;
1230 if (!ForceUncompress
) {
1232 Status
= CompressSection (
1239 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1240 Status
= CompressSection (
1248 if (EFI_ERROR (Status
)) {
1254 Size
+= ReturnValue
;
1256 } else if (_strcmpi (Buffer
, "Tool") == 0) {
1258 ZeroMem (ToolName
, _MAX_PATH
);
1259 ZeroMem (ToolArgumentsArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
1260 ZeroMem (&SignGuid
, sizeof (EFI_GUID
));
1263 // handle signing Tool
1265 while (Buffer
[0] != '(') {
1266 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1267 CheckSlash (Buffer
, Package
, &LineNumber
);
1271 if (_strcmpi (Buffer
, "(") == 0) {
1272 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1273 CheckSlash (Buffer
, Package
, &LineNumber
);
1277 StripParens (Buffer
);
1279 if (Buffer
[0] == '$') {
1280 Index
= ProcessEnvironmentVariable (&Buffer
[0], ToolName
);
1282 // if there is string after the environment variable, cat it.
1284 if ((UINT32
) Index
< strlen (Buffer
)) {
1285 strcat (ToolName
, &Buffer
[Index
]);
1288 strcpy (ToolName
, Buffer
);
1291 ToolArgumentsArray
[0] = ToolName
;
1296 if (GetToolArguments (
1302 &GuidedSectionAttributes
1308 // if the tool need input file,
1309 // dump the file buffer to the specified input file.
1311 if (InputFileName
!= NULL
) {
1312 InputFile
= fopen (InputFileName
, "wb");
1313 if (InputFile
== NULL
) {
1314 Error (NULL
, 0, 0, InputFileName
, "failed to open output file for writing");
1319 fwrite (FileBuffer
, sizeof (UINT8
), Size
, InputFile
);
1322 free (InputFileName
);
1323 InputFileName
= NULL
;
1326 // dispatch signing tool
1328 returnint
= _spawnv (_P_WAIT
, ToolName
, ToolArgumentsArray
);
1329 if (returnint
!= 0) {
1330 Error (NULL
, 0, 0, ToolName
, "external tool failed");
1335 // if the tool has output file,
1336 // dump the output file to the file buffer
1338 if (OutputFileName
!= NULL
) {
1340 OutputFile
= fopen (OutputFileName
, "rb");
1341 if (OutputFile
== NULL
) {
1342 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file for writing");
1347 TargetFileBuffer
= &FileBuffer
[Size
];
1348 SourceDataSize
= Size
;
1350 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1351 while (!feof (OutputFile
)) {
1352 FileBuffer
[Size
++] = Temp
;
1353 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1356 while ((Size
& 0x03) != 0) {
1357 FileBuffer
[Size
] = 0;
1361 SourceDataSize
= Size
- SourceDataSize
;
1363 fclose (OutputFile
);
1365 free (OutputFileName
);
1366 OutputFileName
= NULL
;
1368 if (CompareGuid (&SignGuid
, &mZeroGuid
) != 0) {
1369 ReturnValue
= SourceDataSize
;
1370 Status
= GenSimpleGuidSection (
1375 GuidedSectionAttributes
1377 if (EFI_ERROR (Status
)) {
1386 } else if (Buffer
[0] != '}') {
1388 // if we are here, we should see either a file name,
1394 // Prepend the build directory to the file name if the
1395 // file name does not already contain a full path.
1397 if (!isalpha (Buffer
[0]) || (Buffer
[1] != ':')) {
1398 sprintf (FileName
, "%s\\", BuildDirectory
);
1401 while (Buffer
[Index3
] != '\n') {
1402 if (Buffer
[Index3
] == '$') {
1403 Index3
+= ProcessEnvironmentVariable (&Buffer
[Index3
], NewBuffer
);
1404 strcat (FileName
, NewBuffer
);
1407 if (Buffer
[Index3
] == 0) {
1410 Index2
= strlen (FileName
);
1411 FileName
[Index2
++] = Buffer
[Index3
++];
1412 FileName
[Index2
] = 0;
1416 InFile
= fopen (FileName
, "rb");
1417 if (InFile
== NULL
) {
1418 Error (NULL
, 0, 0, FileName
, "failed to open file for reading");
1423 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1424 while (!feof (InFile
)) {
1425 FileBuffer
[Size
++] = ByteBuffer
;
1426 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1433 // Make sure section ends on a DWORD boundary
1435 while ((Size
& 0x03) != 0) {
1436 FileBuffer
[Size
] = 0;
1444 for (Index3
= 1; Index3
< MAX_ARRAY_SIZE
; Index3
++) {
1445 if (ToolArgumentsArray
[Index3
] == NULL
) {
1449 free (ToolArgumentsArray
[Index3
]);
1467 Routine Description:
1469 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1470 unrecognized file type was specified.
1474 String - File type string
1482 if (_strcmpi (String
, "EFI_FV_FILETYPE_RAW") == 0) {
1483 return EFI_FV_FILETYPE_RAW
;
1486 if (_strcmpi (String
, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1487 return EFI_FV_FILETYPE_FREEFORM
;
1490 if (_strcmpi (String
, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1491 return EFI_FV_FILETYPE_SECURITY_CORE
;
1494 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1495 return EFI_FV_FILETYPE_PEI_CORE
;
1498 if (_strcmpi (String
, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1499 return EFI_FV_FILETYPE_DXE_CORE
;
1502 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEIM") == 0) {
1503 return EFI_FV_FILETYPE_PEIM
;
1506 if (_strcmpi (String
, "EFI_FV_FILETYPE_DRIVER") == 0) {
1507 return EFI_FV_FILETYPE_DRIVER
;
1510 if (_strcmpi (String
, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1511 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
1514 if (_strcmpi (String
, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1515 return EFI_FV_FILETYPE_APPLICATION
;
1518 if (_strcmpi (String
, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1519 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
1522 return EFI_FV_FILETYPE_ALL
;
1528 IN UINT8
*FileBuffer
,
1533 Routine Description:
1534 Adjusts file size to insure sectioned file is exactly the right length such
1535 that it ends on exactly the last byte of the last section. ProcessScript()
1536 may have padded beyond the end of the last section out to a 4 byte boundary.
1537 This padding is stripped.
1540 FileBuffer - Data Buffer - contains a section stream
1541 FileSize - Size of FileBuffer as returned from ProcessScript()
1544 Corrected size of file.
1549 UINT32 CurrentLength
;
1550 UINT32 SectionLength
;
1551 UINT32 SectionStreamLength
;
1552 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1553 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1557 SectionStreamLength
= FileSize
;
1559 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) FileBuffer
;
1561 while (TotalLength
< SectionStreamLength
) {
1562 SectionLength
= *((UINT32
*) SectionHeader
->Size
) & 0x00ffffff;
1563 TotalLength
+= SectionLength
;
1565 if (TotalLength
== SectionStreamLength
) {
1569 // Move to the next byte following the section...
1571 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1572 CurrentLength
= (UINTN
) SectionHeader
- (UINTN
) FileBuffer
;
1575 // Figure out where the next section begins
1577 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ 3);
1578 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
&~ (UINTN
) 3);
1579 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1580 SectionHeader
= NextSectionHeader
;
1583 return CurrentLength
;
1591 BOOLEAN ForceUncompress
1595 Routine Description:
1601 argc - Number of command line parameters.
1602 argv - Array of pointers to command line parameter strings.
1603 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1604 is specified in the script. Otherwise, FALSE.
1607 STATUS_SUCCESS - Function exits successfully.
1608 STATUS_ERROR - Some error occurred during execution.
1612 FILE *PrimaryPackage
;
1613 FILE *OverridePackage
;
1615 CHAR8 BaseName
[_MAX_PATH
];
1617 CHAR8 GuidString
[_MAX_PATH
];
1618 EFI_FFS_FILE_HEADER FileHeader
;
1619 CHAR8 FileType
[_MAX_PATH
];
1620 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
1621 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined
;
1622 UINT64 FfsAlignment
;
1623 UINT32 FfsAlignment32
;
1624 CHAR8 InputString
[_MAX_PATH
];
1625 BOOLEAN ImageScriptInOveride
;
1630 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1631 EFI_FFS_FILE_TAIL TailValue
;
1636 FfsAttribDefined
= 0;
1639 PrimaryPackage
= NULL
;
1641 OverridePackage
= NULL
;
1644 strcpy (GuidString
, "00000000-0000-0000-0000-000000000000");
1645 Status
= StringToGuid (GuidString
, &FfsGuid
);
1647 Error (NULL
, 0, 0, GuidString
, "error parsing GUID string");
1648 return STATUS_ERROR
;
1652 ImageScriptInOveride
= FALSE
;
1654 // Initialize the simple file parsing routines. Then open
1655 // the primary package file for parsing.
1658 if (SFPOpenFile (mGlobals
.PrimaryPackagePath
) != STATUS_SUCCESS
) {
1659 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
1663 // First token in the file must be "PACKAGE.INF"
1665 if (!SFPIsToken ("PACKAGE.INF")) {
1666 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL
);
1670 // Find the [.] section
1672 if (!SFPSkipToToken ("[.]")) {
1673 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "could not locate [.] section in package file", NULL
);
1677 // Start parsing the data. The algorithm is essentially the same for each keyword:
1678 // 1. Identify the keyword
1679 // 2. Verify that the keyword/value pair has not already been defined
1680 // 3. Set some flag indicating that the keyword/value pair has been defined
1681 // 4. Skip over the "="
1682 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1685 if (SFPIsToken ("BASE_NAME")) {
1687 // Found BASE_NAME, format:
1688 // BASE_NAME = MyBaseName
1690 if (BaseName
[0] != 0) {
1691 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL
);
1695 if (!SFPIsToken ("=")) {
1696 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1700 if (!SFPGetNextToken (BaseName
, sizeof (BaseName
))) {
1701 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid base name", NULL
);
1704 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1706 // Found IMAGE_SCRIPT. Break out and process below.
1709 } else if (SFPIsToken ("FFS_FILEGUID")) {
1711 // found FILEGUID, format:
1712 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1714 if (GuidString
[0] != 0) {
1715 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL
);
1719 if (!SFPIsToken ("=")) {
1720 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1724 if (SFPGetGuidToken (GuidString
, sizeof (GuidString
)) != TRUE
) {
1725 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected file GUID", NULL
);
1729 Status
= StringToGuid (GuidString
, &FfsGuid
);
1731 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid file GUID", NULL
);
1734 } else if (SFPIsToken ("FFS_FILETYPE")) {
1736 // ***********************************************************************
1738 // Found FFS_FILETYPE, format:
1739 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1741 if (FileType
[0] != 0) {
1742 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL
);
1746 if (!SFPIsToken ("=")) {
1747 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1751 if (!SFPGetNextToken (FileType
, sizeof (FileType
))) {
1752 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL
);
1756 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1757 else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1759 // ***********************************************************************
1761 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1762 // Spec says the bit is for future expansion, and must be false.
1764 if (FfsAttribDefined
& FFS_ATTRIB_HEADER_EXTENSION
) {
1766 mGlobals
.PrimaryPackagePath
,
1767 SFPGetLineNumber (),
1769 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1775 FfsAttribDefined
|= FFS_ATTRIB_HEADER_EXTENSION
;
1776 if (!SFPIsToken ("=")) {
1777 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1781 if (SFPIsToken ("TRUE")) {
1783 mGlobals
.PrimaryPackagePath
,
1784 SFPGetLineNumber (),
1786 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1790 } else if (SFPIsToken ("FALSE")) {
1795 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL
);
1800 else if (SFPIsToken ("FFS_ATTRIB_FIXED")) {
1802 // ***********************************************************************
1804 // Found: FFS_ATTRIB_FIXED = TRUE | FALSE
1806 if (FfsAttribDefined
& FFS_ATTRIB_FIXED
) {
1807 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_FIXED previously defined", NULL
);
1811 FfsAttribDefined
|= FFS_ATTRIB_FIXED
;
1812 if (!SFPIsToken ("=")) {
1813 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1817 if (SFPIsToken ("TRUE")) {
1818 FfsAttrib
|= FFS_ATTRIB_FIXED
;
1819 } else if (SFPIsToken ("FALSE")) {
1824 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1829 else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1831 // ***********************************************************************
1833 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1835 if (FfsAttribDefined
& FFS_ATTRIB_TAIL_PRESENT
) {
1836 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL
);
1840 FfsAttribDefined
|= FFS_ATTRIB_TAIL_PRESENT
;
1841 if (!SFPIsToken ("=")) {
1842 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1846 if (SFPIsToken ("TRUE")) {
1847 FfsAttrib
|= FFS_ATTRIB_TAIL_PRESENT
;
1848 } else if (SFPIsToken ("FALSE")) {
1853 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1856 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1858 // ***********************************************************************
1860 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1862 if (FfsAttribDefined
& FFS_ATTRIB_RECOVERY
) {
1863 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL
);
1867 FfsAttribDefined
|= FFS_ATTRIB_RECOVERY
;
1868 if (!SFPIsToken ("=")) {
1869 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1873 if (SFPIsToken ("TRUE")) {
1874 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
1875 } else if (SFPIsToken ("FALSE")) {
1880 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1883 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1885 // ***********************************************************************
1887 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1889 if (FfsAttribDefined
& FFS_ATTRIB_CHECKSUM
) {
1890 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL
);
1894 FfsAttribDefined
|= FFS_ATTRIB_CHECKSUM
;
1895 if (!SFPIsToken ("=")) {
1896 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1900 if (SFPIsToken ("TRUE")) {
1901 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
1902 } else if (SFPIsToken ("FALSE")) {
1907 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1910 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1912 // ***********************************************************************
1914 // Found FFS_ALIGNMENT, formats:
1915 // FFS_ALIGNMENT = 0-7
1916 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1918 if (FfsAttribDefined
& FFS_ATTRIB_DATA_ALIGNMENT
) {
1920 mGlobals
.PrimaryPackagePath
,
1921 SFPGetLineNumber (),
1923 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1929 FfsAttribDefined
|= FFS_ATTRIB_DATA_ALIGNMENT
;
1930 if (!SFPIsToken ("=")) {
1931 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1935 if (!SFPGetNumber (&FfsAlignment32
)) {
1936 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL
);
1940 if (FfsAlignment32
> 7) {
1941 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL
);
1945 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment32
) << 3);
1947 SFPGetNextToken (InputString
, sizeof (InputString
));
1948 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, InputString
, "unrecognized/unexpected token");
1953 // Close the primary package file
1957 // TODO: replace code below with basically a copy of the code above. Don't
1958 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1959 // to somehow keep track of whether or not the basename is defined multiple
1960 // times in the override package. Ditto on the file GUID.
1962 if (mGlobals
.OverridePackagePath
[0] != 0) {
1963 OverridePackage
= fopen (mGlobals
.OverridePackagePath
, "r");
1965 // NOTE: For package override to work correctly, the code below must be modified to
1966 // SET or CLEAR bits properly. For example, if the primary package set
1967 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1968 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1969 // the override functionality is not being used, so should be made obsolete. If I'm
1970 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1971 // used, and we'll address it then. 4/10/2003
1973 Error (__FILE__
, __LINE__
, 0, "package override functionality is not implemented correctly", NULL
);
1976 OverridePackage
= NULL
;
1979 #ifdef OVERRIDE_SUPPORTED
1980 if (OverridePackage
!= NULL
) {
1982 // Parse override package file
1984 fscanf (OverridePackage
, "%s", &InputString
);
1985 if (_strcmpi (InputString
, "PACKAGE.INF") != 0) {
1986 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
1990 // Match [dir] to Build Directory
1992 if (FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
) != 0) {
1993 Error (mGlobals
.OverridePackagePath
, 1, 0, mGlobals
.BuildDirectory
, "section not found in package file");
1998 while ((InputString
[0] != '[') && (!feof (OverridePackage
))) {
1999 if (GetNextLine (InputString
, OverridePackage
, &LineNumber
) != -1) {
2000 if (InputString
[0] != '[') {
2002 if (_strcmpi (InputString
, "BASE_NAME") == 0) {
2004 // found BASE_NAME, next is = and string.
2006 fscanf (OverridePackage
, "%s", &InputString
);
2007 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2008 if (strlen (InputString
) == 1) {
2012 fscanf (OverridePackage
, "%s", &InputString
);
2013 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2014 strcpy (BaseName
, InputString
);
2016 BreakString (InputString
, InputString
, 1);
2017 strcpy (BaseName
, InputString
);
2019 } else if (_strcmpi (InputString
, "IMAGE_SCRIPT") == 0) {
2021 // found IMAGE_SCRIPT, come back later to process it
2023 ImageScriptInOveride
= TRUE
;
2024 fscanf (OverridePackage
, "%s", &InputString
);
2025 } else if (_strcmpi (InputString
, "FFS_FILEGUID") == 0) {
2027 // found FILEGUID, next is = and string.
2029 fscanf (OverridePackage
, "%s", &InputString
);
2030 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2031 if (strlen (InputString
) == 1) {
2035 fscanf (OverridePackage
, "%s", &InputString
);
2036 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2037 Status
= StringToGuid (InputString
, &FfsGuid
);
2039 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2043 BreakString (InputString
, InputString
, 1);
2044 Status
= StringToGuid (InputString
, &FfsGuid
);
2046 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2050 } else if (_strcmpi (InputString
, "FFS_FILETYPE") == 0) {
2052 // found FILETYPE, next is = and string.
2054 fscanf (OverridePackage
, "%s", &InputString
);
2055 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2056 if (strlen (InputString
) == 1) {
2060 fscanf (OverridePackage
, "%s", &InputString
);
2061 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2062 strcpy (FileType
, InputString
);
2064 BreakString (InputString
, InputString
, 1);
2065 strcpy (FileType
, InputString
);
2068 } else if (_strcmpi (InputString
, "FFS_ATTRIB_RECOVERY") == 0) {
2070 // found FFS_ATTRIB_RECOVERY, next is = and string.
2072 fscanf (OverridePackage
, "%s", &InputString
);
2073 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2074 if (strlen (InputString
) == 1) {
2078 fscanf (OverridePackage
, "%s", &InputString
);
2079 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2080 if (_strcmpi (InputString
, "TRUE") == 0) {
2081 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2084 BreakString (InputString
, InputString
, 1);
2085 if (_strcmpi (InputString
, "TRUE") == 0) {
2086 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2089 } else if (_strcmpi (InputString
, "FFS_ATTRIB_CHECKSUM") == 0) {
2091 // found FFS_ATTRIB_CHECKSUM, next is = and string.
2093 fscanf (OverridePackage
, "%s", &InputString
);
2094 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2095 if (strlen (InputString
) == 1) {
2099 fscanf (OverridePackage
, "%s", &InputString
);
2100 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2101 if (_strcmpi (InputString
, "TRUE") == 0) {
2102 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2105 BreakString (InputString
, InputString
, 1);
2106 if (_strcmpi (InputString
, "TRUE") == 0) {
2107 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2110 } else if (_strcmpi (InputString
, "FFS_ALIGNMENT") == 0) {
2112 // found FFS_ALIGNMENT, next is = and string.
2114 fscanf (OverridePackage
, "%s", &InputString
);
2115 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2116 if (strlen (InputString
) == 1) {
2120 fscanf (OverridePackage
, "%s", &InputString
);
2121 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2123 BreakString (InputString
, InputString
, 1);
2126 AsciiStringToUint64 (InputString
, FALSE
, &FfsAlignment
);
2127 if (FfsAlignment
> 7) {
2128 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "invalid FFS_ALIGNMENT value");
2132 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment
) << 3);
2133 } else if (strchr (InputString
, '=') != NULL
) {
2134 BreakString (InputString
, String
, 1);
2135 fseek (OverridePackage
, (-1 * (strlen (String
) + 1)), SEEK_CUR
);
2136 BreakString (InputString
, InputString
, 0);
2143 #endif // #ifdef OVERRIDE_SUPPORTED
2145 // Require that they specified a file GUID at least, since that's how we're
2148 if (GuidString
[0] == 0) {
2149 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "FFS_FILEGUID must be specified", NULL
);
2150 return STATUS_ERROR
;
2153 // Build Header and process image script
2155 FileBuffer
= (UINT8
*) malloc ((1024 * 1024 * 16) * sizeof (UINT8
));
2156 if (FileBuffer
== NULL
) {
2157 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
2162 if (ImageScriptInOveride
) {
2163 #ifdef OVERRIDE_SUPPORTED
2164 rewind (OverridePackage
);
2166 FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
);
2167 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2168 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2169 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2170 if (strchr (InputString
, '=') != NULL
) {
2171 BreakString (InputString
, InputString
, 0);
2175 while (InputString
[0] != '{') {
2176 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2177 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2180 // Found start of image script, process it
2182 FileSize
+= ProcessScript (FileBuffer
, OverridePackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2183 if (FileSize
== -1) {
2184 Error (NULL
, 0, 0, "failed to process script", NULL
);
2188 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2189 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2192 if (BaseName
[0] == '\"') {
2193 StripQuotes (BaseName
);
2196 if (BaseName
[0] != 0) {
2197 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2199 strcpy (InputString
, GuidString
);
2202 switch (StringToType (FileType
)) {
2204 case EFI_FV_FILETYPE_SECURITY_CORE
:
2205 strcat (InputString
, ".SEC");
2208 case EFI_FV_FILETYPE_PEIM
:
2209 case EFI_FV_FILETYPE_PEI_CORE
:
2210 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2211 strcat (InputString
, ".PEI");
2214 case EFI_FV_FILETYPE_DRIVER
:
2215 case EFI_FV_FILETYPE_DXE_CORE
:
2216 strcat (InputString
, ".DXE");
2219 case EFI_FV_FILETYPE_APPLICATION
:
2220 strcat (InputString
, ".APP");
2223 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2224 strcat (InputString
, ".FVI");
2227 case EFI_FV_FILETYPE_RAW
:
2228 strcat (InputString
, ".RAW");
2231 case EFI_FV_FILETYPE_ALL
:
2232 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2236 strcat (InputString
, ".FFS");
2240 if (ForceUncompress
) {
2241 strcat (InputString
, ".ORG");
2244 Out
= fopen (InputString
, "wb");
2246 Error (NULL
, 0, 0, InputString
, "could not open output file for writing");
2250 // create ffs header
2252 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2253 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2254 FileHeader
.Type
= StringToType (FileType
);
2255 FileHeader
.Attributes
= FfsAttrib
;
2257 // Now FileSize includes the EFI_FFS_FILE_HEADER
2259 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2260 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2261 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2262 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2264 // Fill in checksums and state, these must be zero for checksumming
2266 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2267 // FileHeader.IntegrityCheck.Checksum.File = 0;
2268 // FileHeader.State = 0;
2270 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2271 (UINT8
*) &FileHeader
,
2272 sizeof (EFI_FFS_FILE_HEADER
)
2274 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2275 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) &FileHeader
, FileSize
);
2277 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2280 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2284 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2285 Error (NULL
, 0, 0, "failed to write file header to output file", NULL
);
2291 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2292 Error (NULL
, 0, 0, "failed to write all bytes to output file", NULL
);
2298 #endif // #ifdef OVERRIDE_SUPPORTED
2301 // Open primary package file and process the IMAGE_SCRIPT section
2303 PrimaryPackage
= fopen (mGlobals
.PrimaryPackagePath
, "r");
2304 if (PrimaryPackage
== NULL
) {
2305 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
2310 FindSectionInPackage (".", PrimaryPackage
, &LineNumber
);
2311 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2312 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2313 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2314 if (strchr (InputString
, '=') != NULL
) {
2315 BreakString (InputString
, InputString
, 0);
2319 while (InputString
[0] != '{') {
2320 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2321 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2324 // Found start of image script, process it
2326 FileSize
+= ProcessScript (FileBuffer
, PrimaryPackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2327 if (FileSize
== -1) {
2328 Error (NULL
, 0, 0, "failed to process script", NULL
);
2332 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2333 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2336 if (BaseName
[0] == '\"') {
2337 StripQuotes (BaseName
);
2340 if (BaseName
[0] != 0) {
2341 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2343 strcpy (InputString
, GuidString
);
2346 switch (StringToType (FileType
)) {
2348 case EFI_FV_FILETYPE_SECURITY_CORE
:
2349 strcat (InputString
, ".SEC");
2352 case EFI_FV_FILETYPE_PEIM
:
2353 case EFI_FV_FILETYPE_PEI_CORE
:
2354 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2355 strcat (InputString
, ".PEI");
2358 case EFI_FV_FILETYPE_DRIVER
:
2359 case EFI_FV_FILETYPE_DXE_CORE
:
2360 strcat (InputString
, ".DXE");
2363 case EFI_FV_FILETYPE_APPLICATION
:
2364 strcat (InputString
, ".APP");
2367 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2368 strcat (InputString
, ".FVI");
2371 case EFI_FV_FILETYPE_RAW
:
2372 strcat (InputString
, ".RAW");
2375 case EFI_FV_FILETYPE_ALL
:
2376 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2380 strcat (InputString
, ".FFS");
2384 if (ForceUncompress
) {
2385 strcat (InputString
, ".ORG");
2388 Out
= fopen (InputString
, "wb");
2390 Error (NULL
, 0, 0, InputString
, "failed to open output file for writing");
2394 // Initialize the FFS file header
2396 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2397 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2398 FileHeader
.Type
= StringToType (FileType
);
2399 FileHeader
.Attributes
= FfsAttrib
;
2401 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2403 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2405 // If using a tail, then it adds two bytes
2407 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2409 // Tail is not allowed for pad and 0-length files
2411 if ((FileHeader
.Type
== EFI_FV_FILETYPE_FFS_PAD
) || (FileSize
== sizeof (EFI_FFS_FILE_HEADER
))) {
2413 mGlobals
.PrimaryPackagePath
,
2416 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2422 FileSize
+= sizeof (EFI_FFS_FILE_TAIL
);
2425 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2426 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2427 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2429 // Fill in checksums and state, they must be 0 for checksumming.
2431 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2432 // FileHeader.IntegrityCheck.Checksum.File = 0;
2433 // FileHeader.State = 0;
2435 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2436 (UINT8
*) &FileHeader
,
2437 sizeof (EFI_FFS_FILE_HEADER
)
2439 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2441 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2442 // Checksum does not include the tail
2444 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2445 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2447 FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
)
2450 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2452 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2456 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2459 // Set the state now. Spec says the checksum assumes the state is 0
2461 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2463 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2466 // If there is a tail, then set it
2468 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2469 TailValue
= FileHeader
.IntegrityCheck
.TailReference
;
2470 TailValue
= (UINT16
) (~TailValue
);
2472 (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
2585 return STATUS_ERROR
;
2588 memset (&mGlobals
, 0, sizeof (mGlobals
));
2592 if (_strcmpi (Argv
[0], "-b") == 0) {
2594 // OPTION: -b BuildDirectory
2595 // Make sure there is another argument, then save it to our globals.
2598 Error (NULL
, 0, 0, "-b option requires the build directory name", NULL
);
2599 return STATUS_ERROR
;
2602 if (mGlobals
.BuildDirectory
[0]) {
2603 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2604 return STATUS_ERROR
;
2607 strcpy (mGlobals
.BuildDirectory
, Argv
[1]);
2610 } else if (_strcmpi (Argv
[0], "-p1") == 0) {
2612 // OPTION: -p1 PrimaryPackageFile
2613 // Make sure there is another argument, then save it to our globals.
2616 Error (NULL
, 0, 0, Argv
[0], "option requires the primary package file name");
2617 return STATUS_ERROR
;
2620 if (mGlobals
.PrimaryPackagePath
[0]) {
2621 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2622 return STATUS_ERROR
;
2625 strcpy (mGlobals
.PrimaryPackagePath
, Argv
[1]);
2628 } else if (_strcmpi (Argv
[0], "-p2") == 0) {
2630 // OPTION: -p2 OverridePackageFile
2631 // Make sure there is another argument, then save it to our globals.
2634 Error (NULL
, 0, 0, Argv
[0], "option requires the override package file name");
2635 return STATUS_ERROR
;
2638 if (mGlobals
.OverridePackagePath
[0]) {
2639 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2640 return STATUS_ERROR
;
2643 strcpy (mGlobals
.OverridePackagePath
, Argv
[1]);
2646 } else if (_strcmpi (Argv
[0], "-v") == 0) {
2648 // OPTION: -v verbose
2650 mGlobals
.Verbose
= TRUE
;
2651 } else if (_strcmpi (Argv
[0], "-h") == 0) {
2656 return STATUS_ERROR
;
2657 } else if (_strcmpi (Argv
[0], "-?") == 0) {
2662 return STATUS_ERROR
;
2664 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
2666 return STATUS_ERROR
;
2673 // Must have at least specified the package file name
2675 if (mGlobals
.PrimaryPackagePath
[0] == 0) {
2676 Error (NULL
, 0, 0, "must specify primary package file", NULL
);
2677 return STATUS_ERROR
;
2680 return STATUS_SUCCESS
;