3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
4 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"
30 #include "EfiCustomizedCompress.h"
32 #include "GenFfsFile.h"
34 #include <ctype.h> // for isalpha()
36 // include file for _spawnv
41 #include "CommonLib.h"
42 #include "EfiUtilityMsgs.h"
43 #include "SimpleFileParsing.h"
45 #define UTILITY_NAME "GenFfsFile"
46 #define UTILITY_VERSION "v1.1"
47 #define MAX_ARRAY_SIZE 100
52 OUT CHAR8
*Destination
,
54 IN OUT UINT32
*LineNumber
62 IN OUT UINT32
*LineNumber
67 FindSectionInPackage (
68 IN CHAR8
*BuildDirectory
,
69 IN
FILE *OverridePackage
,
70 IN OUT UINT32
*LineNumber
75 ProcessCommandLineArgs (
111 // Linked list to keep track of all macros
113 typedef struct _MACRO
{
120 // Keep globals in this structure
123 UINT8 BuildDirectory
[_MAX_PATH
];
124 UINT8 PrimaryPackagePath
[_MAX_PATH
];
125 UINT8 OverridePackagePath
[_MAX_PATH
];
126 UINT8 OutputFilePath
[_MAX_PATH
];
131 static EFI_GUID mZeroGuid
= { 0 };
133 static UINT8 MinFfsDataAlignOverride
= 0;
144 Removes quotes and/or whitespace from around a string
148 String - String to remove quotes from
160 Index2
= strspn (String
, "\" \t\n");
161 StrLen
= strlen (String
);
163 for (Index
= Index2
; String
[Index
] != '\"', Index
< StrLen
; Index
++) {
164 String
[Index
- Index2
] = String
[Index
];
167 String
[Index
- Index2
] = 0;
179 Print Error / Help message.
192 const char *Str
[] = {
193 UTILITY_NAME
" "UTILITY_VERSION
" - Intel Generate FFS File Utility",
194 " Copyright (C), 2004 - 2009 Intel Corporation",
196 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
197 " Built from "UTILITY_BUILD
", project of "UTILITY_VENDOR
,
201 " "UTILITY_NAME
" [OPTION]...",
203 " -b BuildDirectory Specifies the full path to the component build directory",
204 " -p1 P1Path Specifies fully qualified file name to the primary package",
205 " file. This file will normally exist in the same directory",
206 " as the makefile for the component. Required.",
207 " -p2 P2Path Specifies fully qualified file name to the override",
208 " package. This file will normally exist in the build tip.",
210 " -d Name=Value Add a macro definition for the package file. Optional.",
211 " -o OutputFile Specifies the file name of output file. Optional.",
212 " -v Verbose. Optional.",
215 for (Index
= 0; Str
[Index
] != NULL
; Index
++) {
216 fprintf (stdout
, "%s\n", Str
[Index
]);
230 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
234 String - String to test
236 In - Open file to move pointer within
240 -1 - End of file reached
249 if ((String
[0] == '/') && (String
[1] == '/')) {
250 while (CharBuffer
!= '\n') {
251 fscanf (In
, "%c", &CharBuffer
);
266 IN CONST CHAR8
*Source
,
267 OUT CHAR8
*Destination
,
274 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
278 Source - String to break
280 Destination - Buffer to place new string in
282 Direction - 0 to return all of source string before =
283 1 to return all of source string after =
297 if (strchr (Source
, '=') == NULL
) {
298 strcpy (Destination
, Source
);
303 if (Direction
== 0) {
305 // return part of string before =
307 while (Source
[Index
] != '=') {
308 Destination
[Index
] = Source
[Index
++];
311 Destination
[Index
] = 0;
314 // return part of string after =
316 strcpy (Destination
, strchr (Source
, '=') + 1);
323 OUT CHAR8
*Destination
,
325 IN OUT UINT32
*LineNumber
331 Gets the next non-commented line from the file
335 Destination - Where to put string
337 Package - Package to get string from
339 LineNumber - The actual line number.
343 -1 - End of file reached
348 CHAR8 String
[_MAX_PATH
];
349 fscanf (Package
, "%s", &String
);
350 if (feof (Package
)) {
354 while (TestComment (String
, Package
) == 1) {
355 fscanf (Package
, "%s", &String
);
356 if (feof (Package
)) {
361 strcpy (Destination
, String
);
368 IN OUT CHAR8
*String
,
370 IN OUT UINT32
*LineNumber
376 Checks to see if string is line continuation character, if so goes to next valid line
380 String - String to test
382 In - Open file to move pointer within
384 LineNumber - The line number.
398 while (String
[0] == '\\') {
399 while (ByteBuffer
!= '\n') {
400 fscanf (In
, "%c", &ByteBuffer
);
403 if (GetNextLine (String
, In
, LineNumber
) == -1) {
411 while (String
[0] == '\n') {
412 if (GetNextLine (String
, In
, LineNumber
) == -1) {
427 FindSectionInPackage (
428 IN CHAR8
*BuildDirectory
,
429 IN
FILE *OverridePackage
,
430 IN OUT UINT32
*LineNumber
436 Finds the matching section within the package
440 BuildDirectory - name of section to find
442 OverridePackage - Package file to search within
444 LineNumber - The line number.
448 -1 - End of file reached
453 CHAR8 String
[_MAX_PATH
];
454 CHAR8 NewString
[_MAX_PATH
];
457 while (strcmp (BuildDirectory
, String
) != 0) {
458 if (GetNextLine (NewString
, OverridePackage
, LineNumber
) != 0) {
462 if (NewString
[0] == '[') {
463 if (NewString
[strlen (NewString
) - 1] != ']') {
465 // have to construct string.
467 strcpy (String
, NewString
+ 1);
470 fscanf (OverridePackage
, "%s", &NewString
);
471 if (feof (OverridePackage
)) {
475 if (NewString
[0] != ']') {
476 if (strlen (String
) != 0) {
477 strcat (String
, " ");
480 strcat (String
, NewString
);
481 if (String
[strlen (String
) - 1] == ']') {
482 String
[strlen (String
) - 1] = 0;
490 NewString
[strlen (NewString
) - 1] = 0;
491 strcpy (String
, NewString
+ 1);
501 GenSimpleGuidSection (
502 IN OUT UINT8
*FileBuffer
,
503 IN OUT UINT32
*BufferSize
,
505 IN EFI_GUID SignGuid
,
506 IN UINT16 GuidedSectionAttributes
512 add GUIDed section header for the data buffer.
513 data stays in same location (overwrites source data).
517 FileBuffer - Buffer containing data to sign
519 BufferSize - On input, the size of FileBuffer. On output, the size of
520 actual section data (including added section header).
522 DataSize - Length of data to Sign
524 SignGuid - Guid to be add.
526 GuidedSectionAttributes - The section attribute.
530 EFI_SUCCESS - Successful
531 EFI_OUT_OF_RESOURCES - Not enough resource.
537 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
548 TotalSize
= DataSize
+ sizeof (EFI_GUID_DEFINED_SECTION
);
549 GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
550 GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
551 GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
552 GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
553 memcpy (&(GuidSectionHeader
.SectionDefinitionGuid
), &SignGuid
, sizeof (EFI_GUID
));
554 GuidSectionHeader
.Attributes
= GuidedSectionAttributes
;
555 GuidSectionHeader
.DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
);
557 SwapBuffer
= (UINT8
*) malloc (DataSize
);
558 if (SwapBuffer
== NULL
) {
559 return EFI_OUT_OF_RESOURCES
;
562 memcpy (SwapBuffer
, FileBuffer
, DataSize
);
563 memcpy (FileBuffer
, &GuidSectionHeader
, sizeof (EFI_GUID_DEFINED_SECTION
));
564 memcpy (FileBuffer
+ sizeof (EFI_GUID_DEFINED_SECTION
), SwapBuffer
, DataSize
);
567 // Make sure section ends on a DWORD boundary
569 while ((TotalSize
& 0x03) != 0) {
570 FileBuffer
[TotalSize
] = 0;
574 *BufferSize
= TotalSize
;
576 if (SwapBuffer
!= NULL
) {
595 Compress the data and add section header for the compressed data.
596 Compressed data (with section header) stays in same location as the source
597 (overwrites source data).
601 FileBuffer - Buffer containing data to Compress
603 BufferSize - On input, the size of FileBuffer. On output, the size of
604 actual compressed data (including added section header).
605 When buffer is too small, this value indicates the size needed.
607 DataSize - The size of data to compress
609 Type - The compression type (not used currently).
610 Assume EFI_HEAVY_COMPRESSION.
614 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
615 EFI_UNSUPPORTED - Compress type can not be supported.
616 EFI_SUCCESS - Successful
617 EFI_OUT_OF_RESOURCES - Not enough resource.
625 EFI_COMPRESSION_SECTION CompressionSet
;
626 UINT8 CompressionType
;
627 COMPRESS_FUNCTION CompressFunction
;
629 Status
= EFI_SUCCESS
;
633 CompressFunction
= NULL
;
636 // Get the compress type
638 if (_strcmpi (Type
, "Dummy") == 0) {
640 // Added "Dummy" to keep backward compatibility.
642 CompressionType
= EFI_STANDARD_COMPRESSION
;
643 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
645 } else if (_strcmpi (Type
, "LZH") == 0) {
647 // EFI stardard compression (LZH)
649 CompressionType
= EFI_STANDARD_COMPRESSION
;
650 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
654 // Customized compression
656 Status
= SetCustomizedCompressionType (Type
);
657 if (EFI_ERROR (Status
)) {
661 CompressionType
= EFI_CUSTOMIZED_COMPRESSION
;
662 CompressFunction
= (COMPRESS_FUNCTION
) CustomizedCompress
;
665 // Compress the raw data
667 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
668 if (Status
== EFI_BUFFER_TOO_SMALL
) {
669 CompData
= malloc (CompSize
);
671 return EFI_OUT_OF_RESOURCES
;
674 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
677 if (EFI_ERROR (Status
)) {
678 if (CompData
!= NULL
) {
685 TotalSize
= CompSize
+ sizeof (EFI_COMPRESSION_SECTION
);
690 if (TotalSize
> *BufferSize
) {
691 *BufferSize
= TotalSize
;
692 if (CompData
!= NULL
) {
696 return EFI_BUFFER_TOO_SMALL
;
699 // Add the section header for the compressed data
701 CompressionSet
.CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
702 CompressionSet
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
703 CompressionSet
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
704 CompressionSet
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
705 CompressionSet
.CompressionType
= CompressionType
;
706 CompressionSet
.UncompressedLength
= DataSize
;
709 // Copy header and data to the buffer
711 memcpy (FileBuffer
, &CompressionSet
, sizeof (EFI_COMPRESSION_SECTION
));
712 memcpy (FileBuffer
+ sizeof (CompressionSet
), CompData
, CompSize
);
715 // Make sure section ends on a DWORD boundary
717 while ((TotalSize
& 0x03) != 0) {
718 FileBuffer
[TotalSize
] = 0;
722 *BufferSize
= TotalSize
;
724 if (CompData
!= NULL
) {
740 Removes Parenthesis from around a string
744 String - String to remove parens from
754 if (String
[0] != '(') {
758 for (Index
= 1; String
[Index
] != ')'; Index
++) {
759 String
[Index
- 1] = String
[Index
];
760 if (String
[Index
] == 0) {
765 String
[Index
- 1] = 0;
779 Removes Equal Mark from around a string
783 String - String to remove equal mark from
793 if (String
[0] != '=' && String
[strlen (String
) - 1] != '=') {
797 if (String
[0] == '=') {
799 for (Index
= 1; String
[Index
] != 0; Index
++) {
800 String
[Index
- 1] = String
[Index
];
803 String
[Index
- 1] = 0;
806 if (String
[strlen (String
) - 1] == '=') {
807 String
[strlen (String
) - 1] = 0;
815 SplitAttributesField (
817 IN CHAR8
*AttributesArray
[],
818 IN OUT UINT32
*NumberOfAttributes
821 NumberOfAttributes: on input, it specifies the current number of attributes
822 stored in AttributeArray.
823 on output, it is updated to the latest number of attributes
824 stored in AttributesArray.
833 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
834 ZeroMem (CharBuffer
, _MAX_PATH
);
836 for (Index
= 0, z
= 0, Index2
= 0; Index
< strlen (Buffer
); Index
++) {
838 if (Buffer
[Index
] != '|') {
839 CharBuffer
[z
] = Buffer
[Index
];
844 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
848 // allocate new char buffer for the next attributes string
850 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
851 ZeroMem (CharBuffer
, _MAX_PATH
);
858 // record the last attributes string in the Buffer
860 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
863 *NumberOfAttributes
+= Index2
;
871 CHAR8
*ToolArgumentsArray
[],
873 CHAR8
**PtrInputFileName
,
874 CHAR8
**PtrOutputFileName
,
876 UINT16
*GuidedSectionAttributes
879 CHAR8 Buffer
[_MAX_PATH
];
880 BOOLEAN ArgumentsFlag
;
884 BOOLEAN AttributesFlag
;
892 CHAR8
*AttributesArray
[MAX_ARRAY_SIZE
];
893 UINT32 NumberOfAttributes
;
894 CHAR8
*InputFileName
;
895 CHAR8
*OutputFileName
;
899 ArgumentsFlag
= FALSE
;
903 AttributesFlag
= FALSE
;
905 // Start at 1, since ToolArgumentsArray[0]
906 // is the program name.
913 NumberOfAttributes
= 0;
914 InputFileName
= NULL
;
915 OutputFileName
= NULL
;
917 ZeroMem (Buffer
, _MAX_PATH
);
918 ZeroMem (AttributesArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
920 while (Buffer
[0] != ')') {
922 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
923 CheckSlash (Buffer
, Package
, &LineNumber
);
924 StripEqualMark (Buffer
);
926 Error (NULL
, 0, 0, "failed to get next line from package file", NULL
);
930 if (Buffer
[0] == ')') {
932 } else if (_strcmpi (Buffer
, "ARGS") == 0) {
934 ArgumentsFlag
= TRUE
;
935 AttributesFlag
= FALSE
;
938 } else if (_strcmpi (Buffer
, "INPUT") == 0) {
941 ArgumentsFlag
= FALSE
;
942 AttributesFlag
= FALSE
;
945 } else if (_strcmpi (Buffer
, "OUTPUT") == 0) {
948 ArgumentsFlag
= FALSE
;
949 AttributesFlag
= FALSE
;
952 } else if (_strcmpi (Buffer
, "GUID") == 0) {
955 ArgumentsFlag
= FALSE
;
956 AttributesFlag
= FALSE
;
958 // fetch the GUID for the section
962 } else if (_strcmpi (Buffer
, "ATTRIBUTES") == 0) {
964 AttributesFlag
= TRUE
;
965 ArgumentsFlag
= FALSE
;
967 // fetch the GUIDed Section's Attributes
971 } else if (_strcmpi (Buffer
, "") == 0) {
975 // get all command arguments into ToolArgumentsArray
979 StripEqualMark (Buffer
);
981 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
982 if (CharBuffer
== NULL
) {
986 ZeroMem (CharBuffer
, sizeof (_MAX_PATH
));
988 ToolArgumentsArray
[argc
] = CharBuffer
;
990 strcpy (ToolArgumentsArray
[argc
], Buffer
);
993 ToolArgumentsArray
[argc
] = NULL
;
999 StripEqualMark (Buffer
);
1001 InputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1002 if (InputFileName
== NULL
) {
1006 ZeroMem (InputFileName
, sizeof (_MAX_PATH
));
1008 strcpy (InputFileName
, Buffer
);
1016 StripEqualMark (Buffer
);
1018 OutputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1019 if (OutputFileName
== NULL
) {
1023 ZeroMem (OutputFileName
, sizeof (_MAX_PATH
));
1025 strcpy (OutputFileName
, Buffer
);
1033 StripEqualMark (Buffer
);
1035 Status
= StringToGuid (Buffer
, Guid
);
1036 if (EFI_ERROR (Status
)) {
1044 if (AttributesFlag
) {
1046 StripEqualMark (Buffer
);
1049 // there might be no space between each attribute in the statement,
1050 // split them aside and return each attribute string
1051 // in the AttributesArray
1053 SplitAttributesField (Buffer
, AttributesArray
, &NumberOfAttributes
);
1057 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1058 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1060 for (z
= 0; z
< NumberOfAttributes
; z
++) {
1061 if (_strcmpi (AttributesArray
[z
], "PROCESSING_REQUIRED") == 0) {
1062 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1063 } else if (_strcmpi (AttributesArray
[z
], "AUTH_STATUS_VALID") == 0) {
1064 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1070 for (Index2
= 0; Index2
< MAX_ARRAY_SIZE
; Index2
++) {
1071 if (AttributesArray
[Index2
] == NULL
) {
1075 free (AttributesArray
[Index2
]);
1078 *PtrInputFileName
= InputFileName
;
1079 *PtrOutputFileName
= OutputFileName
;
1087 IN OUT UINT8
*FileBuffer
,
1089 IN CHAR8
*BuildDirectory
,
1090 IN BOOLEAN ForceUncompress
1094 Routine Description:
1096 Signs the section, data stays in same location
1100 FileBuffer - Data Buffer
1102 Package - Points to curly brace in Image Script
1104 BuildDirectory - Name of the source directory parameter
1106 ForceUncompress - Whether to force uncompress.
1110 Number of bytes added to file buffer
1119 UINT16 TeStrippedSize
;
1120 CHAR8 Buffer
[_MAX_PATH
];
1121 CHAR8 Type
[_MAX_PATH
];
1122 CHAR8 FileName
[_MAX_PATH
];
1128 UINT32 SourceDataSize
;
1129 CHAR8
*ToolArgumentsArray
[MAX_ARRAY_SIZE
];
1130 CHAR8
*OutputFileName
;
1131 CHAR8
*InputFileName
;
1132 CHAR8 ToolName
[_MAX_PATH
];
1140 UINT16 GuidedSectionAttributes
;
1141 UINT8
*TargetFileBuffer
;
1143 OutputFileName
= NULL
;
1144 InputFileName
= NULL
;
1148 GuidedSectionAttributes
= 0;
1149 TargetFileBuffer
= NULL
;
1154 for (Index3
= 0; Index3
< MAX_ARRAY_SIZE
; ++Index3
) {
1155 ToolArgumentsArray
[Index3
] = NULL
;
1158 while (Buffer
[0] != '}') {
1159 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1160 CheckSlash (Buffer
, Package
, &LineNumber
);
1162 printf ("ERROR in IMAGE SCRIPT!\n");
1167 if (_strcmpi (Buffer
, "Compress") == 0) {
1172 // read compression type
1174 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1175 CheckSlash (Buffer
, Package
, &LineNumber
);
1178 StripParens (Buffer
);
1179 strcpy (Type
, Buffer
);
1183 while (Buffer
[0] != '{') {
1184 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1185 CheckSlash (Buffer
, Package
, &LineNumber
);
1189 ReturnValue
= ProcessScript (&FileBuffer
[Size
], Package
, BuildDirectory
, ForceUncompress
);
1190 if (ReturnValue
== -1) {
1195 // Call compress routine on buffer.
1196 // Occasionally, compressed data + section header would
1197 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1198 // returned from CompressSection()
1200 SourceDataSize
= ReturnValue
;
1202 if (!ForceUncompress
) {
1204 Status
= CompressSection (
1211 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1212 Status
= CompressSection (
1220 if (EFI_ERROR (Status
)) {
1226 Size
+= ReturnValue
;
1228 } else if (_strcmpi (Buffer
, "Tool") == 0) {
1230 ZeroMem (ToolName
, _MAX_PATH
);
1231 ZeroMem (ToolArgumentsArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
1232 ZeroMem (&SignGuid
, sizeof (EFI_GUID
));
1235 // handle signing Tool
1237 while (Buffer
[0] != '(') {
1238 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1239 CheckSlash (Buffer
, Package
, &LineNumber
);
1243 if (_strcmpi (Buffer
, "(") == 0) {
1244 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1245 CheckSlash (Buffer
, Package
, &LineNumber
);
1249 StripParens (Buffer
);
1250 strcpy (ToolName
, Buffer
);
1251 ToolArgumentsArray
[0] = ToolName
;
1256 if (GetToolArguments (
1262 &GuidedSectionAttributes
1268 // if the tool need input file,
1269 // dump the file buffer to the specified input file.
1271 if (InputFileName
!= NULL
) {
1272 InputFile
= fopen (InputFileName
, "wb");
1273 if (InputFile
== NULL
) {
1274 Error (NULL
, 0, 0, InputFileName
, "failed to open output file for writing");
1279 fwrite (FileBuffer
, sizeof (UINT8
), Size
, InputFile
);
1282 free (InputFileName
);
1283 InputFileName
= NULL
;
1286 // dispatch signing tool
1288 returnint
= _spawnv (_P_WAIT
, ToolName
, ToolArgumentsArray
);
1289 if (returnint
!= 0) {
1290 Error (NULL
, 0, 0, ToolName
, "external tool failed");
1295 // if the tool has output file,
1296 // dump the output file to the file buffer
1298 if (OutputFileName
!= NULL
) {
1300 OutputFile
= fopen (OutputFileName
, "rb");
1301 if (OutputFile
== NULL
) {
1302 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file for writing");
1307 TargetFileBuffer
= &FileBuffer
[Size
];
1308 SourceDataSize
= Size
;
1310 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1311 while (!feof (OutputFile
)) {
1312 FileBuffer
[Size
++] = Temp
;
1313 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1316 while ((Size
& 0x03) != 0) {
1317 FileBuffer
[Size
] = 0;
1321 SourceDataSize
= Size
- SourceDataSize
;
1323 fclose (OutputFile
);
1325 free (OutputFileName
);
1326 OutputFileName
= NULL
;
1328 if (CompareGuid (&SignGuid
, &mZeroGuid
) != 0) {
1329 ReturnValue
= SourceDataSize
;
1330 Status
= GenSimpleGuidSection (
1335 GuidedSectionAttributes
1337 if (EFI_ERROR (Status
)) {
1346 } else if (Buffer
[0] != '}') {
1348 // if we are here, we should see either a file name,
1354 // Prepend the build directory to the file name if the
1355 // file name does not already contain a full path.
1357 if (!isalpha (Buffer
[0]) || (Buffer
[1] != ':')) {
1358 sprintf (FileName
, "%s\\", BuildDirectory
);
1361 while (Buffer
[Index3
] != '\n') {
1362 if (Buffer
[Index3
] == 0) {
1365 Index2
= strlen (FileName
);
1366 FileName
[Index2
++] = Buffer
[Index3
++];
1367 FileName
[Index2
] = 0;
1371 InFile
= fopen (FileName
, "rb");
1372 if (InFile
== NULL
) {
1373 Error (NULL
, 0, 0, FileName
, "failed to open file for reading");
1379 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1380 while (!feof (InFile
)) {
1381 FileBuffer
[Size
++] = ByteBuffer
;
1382 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1389 // Adjust the TE Section for IPF so that the function entries are 16-byte aligned.
1391 if (Size
- OldSize
>= sizeof (EFI_COMMON_SECTION_HEADER
) + sizeof (EFI_TE_IMAGE_HEADER
) &&
1392 ((EFI_COMMON_SECTION_HEADER
*) &FileBuffer
[OldSize
])->Type
== EFI_SECTION_TE
&&
1393 ((EFI_TE_IMAGE_HEADER
*) &FileBuffer
[OldSize
+ 4])->Machine
== EFI_IMAGE_MACHINE_IA64
) {
1394 TeStrippedSize
= ((EFI_TE_IMAGE_HEADER
*) &FileBuffer
[OldSize
+ 4])->StrippedSize
;
1395 Adjust
= TeStrippedSize
- (OldSize
+ sizeof (EFI_COMMON_SECTION_HEADER
) + sizeof (EFI_TE_IMAGE_HEADER
));
1398 memmove (&FileBuffer
[OldSize
+ Adjust
], &FileBuffer
[OldSize
], Size
- OldSize
);
1400 // Pad with RAW Section type
1402 *(UINT32
*)&FileBuffer
[OldSize
] = 0x19000000 | Adjust
;
1405 // Make sure the Data alignment in FFS header is no less than 1 (16-byte aligned)
1407 MinFfsDataAlignOverride
= 1;
1412 // Make sure section ends on a DWORD boundary
1414 while ((Size
& 0x03) != 0) {
1415 FileBuffer
[Size
] = 0;
1423 for (Index3
= 1; Index3
< MAX_ARRAY_SIZE
; Index3
++) {
1424 if (ToolArgumentsArray
[Index3
] == NULL
) {
1428 free (ToolArgumentsArray
[Index3
]);
1446 Routine Description:
1448 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1449 unrecognized file type was specified.
1453 String - File type string
1461 if (_strcmpi (String
, "EFI_FV_FILETYPE_RAW") == 0) {
1462 return EFI_FV_FILETYPE_RAW
;
1465 if (_strcmpi (String
, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1466 return EFI_FV_FILETYPE_FREEFORM
;
1469 if (_strcmpi (String
, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1470 return EFI_FV_FILETYPE_SECURITY_CORE
;
1473 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1474 return EFI_FV_FILETYPE_PEI_CORE
;
1477 if (_strcmpi (String
, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1478 return EFI_FV_FILETYPE_DXE_CORE
;
1481 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEIM") == 0) {
1482 return EFI_FV_FILETYPE_PEIM
;
1485 if (_strcmpi (String
, "EFI_FV_FILETYPE_DRIVER") == 0) {
1486 return EFI_FV_FILETYPE_DRIVER
;
1489 if (_strcmpi (String
, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1490 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
1493 if (_strcmpi (String
, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1494 return EFI_FV_FILETYPE_APPLICATION
;
1497 if (_strcmpi (String
, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1498 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
1501 return EFI_FV_FILETYPE_ALL
;
1507 IN UINT8
*FileBuffer
,
1512 Routine Description:
1513 Adjusts file size to insure sectioned file is exactly the right length such
1514 that it ends on exactly the last byte of the last section. ProcessScript()
1515 may have padded beyond the end of the last section out to a 4 byte boundary.
1516 This padding is stripped.
1519 FileBuffer - Data Buffer - contains a section stream
1520 FileSize - Size of FileBuffer as returned from ProcessScript()
1523 Corrected size of file.
1528 UINT32 CurrentLength
;
1529 UINT32 SectionLength
;
1530 UINT32 SectionStreamLength
;
1531 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1532 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1536 SectionStreamLength
= FileSize
;
1538 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) FileBuffer
;
1540 while (TotalLength
< SectionStreamLength
) {
1541 SectionLength
= *((UINT32
*) SectionHeader
->Size
) & 0x00ffffff;
1542 TotalLength
+= SectionLength
;
1544 if (TotalLength
== SectionStreamLength
) {
1548 // Move to the next byte following the section...
1550 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1551 CurrentLength
= (UINTN
) SectionHeader
- (UINTN
) FileBuffer
;
1554 // Figure out where the next section begins
1556 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ 3);
1557 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
&~ (UINTN
) 3);
1558 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1559 SectionHeader
= NextSectionHeader
;
1562 return CurrentLength
;
1570 BOOLEAN ForceUncompress
1574 Routine Description:
1580 argc - Number of command line parameters.
1581 argv - Array of pointers to command line parameter strings.
1582 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1583 is specified in the script. Otherwise, FALSE.
1586 STATUS_SUCCESS - Function exits successfully.
1587 STATUS_ERROR - Some error occurred during execution.
1591 FILE *PrimaryPackage
;
1592 FILE *OverridePackage
;
1594 CHAR8 BaseName
[_MAX_PATH
];
1596 CHAR8 GuidString
[_MAX_PATH
];
1597 EFI_FFS_FILE_HEADER FileHeader
;
1598 CHAR8 FileType
[_MAX_PATH
];
1599 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
1600 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined
;
1601 UINT64 FfsAlignment
;
1602 UINT32 FfsAlignment32
;
1603 CHAR8 InputString
[_MAX_PATH
];
1604 BOOLEAN ImageScriptInOveride
;
1609 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1610 EFI_FFS_FILE_TAIL TailValue
;
1615 FfsAttribDefined
= 0;
1618 PrimaryPackage
= NULL
;
1620 OverridePackage
= NULL
;
1623 strcpy (GuidString
, "00000000-0000-0000-0000-000000000000");
1624 Status
= StringToGuid (GuidString
, &FfsGuid
);
1626 Error (NULL
, 0, 0, GuidString
, "error parsing GUID string");
1627 return STATUS_ERROR
;
1631 ImageScriptInOveride
= FALSE
;
1633 // Initialize the simple file parsing routines. Then open
1634 // the primary package file for parsing.
1637 if (SFPOpenFile (mGlobals
.PrimaryPackagePath
) != STATUS_SUCCESS
) {
1638 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
1642 // First token in the file must be "PACKAGE.INF"
1644 if (!SFPIsToken ("PACKAGE.INF")) {
1645 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL
);
1649 // Find the [.] section
1651 if (!SFPSkipToToken ("[.]")) {
1652 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "could not locate [.] section in package file", NULL
);
1656 // Start parsing the data. The algorithm is essentially the same for each keyword:
1657 // 1. Identify the keyword
1658 // 2. Verify that the keyword/value pair has not already been defined
1659 // 3. Set some flag indicating that the keyword/value pair has been defined
1660 // 4. Skip over the "="
1661 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1664 if (SFPIsToken ("BASE_NAME")) {
1666 // Found BASE_NAME, format:
1667 // BASE_NAME = MyBaseName
1669 if (BaseName
[0] != 0) {
1670 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL
);
1674 if (!SFPIsToken ("=")) {
1675 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1679 if (!SFPGetNextToken (BaseName
, sizeof (BaseName
))) {
1680 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid base name", NULL
);
1683 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1685 // Found IMAGE_SCRIPT. Break out and process below.
1688 } else if (SFPIsToken ("FFS_FILEGUID")) {
1690 // found FILEGUID, format:
1691 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1693 if (GuidString
[0] != 0) {
1694 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL
);
1698 if (!SFPIsToken ("=")) {
1699 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1703 if (SFPGetGuidToken (GuidString
, sizeof (GuidString
)) != TRUE
) {
1704 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected file GUID", NULL
);
1708 Status
= StringToGuid (GuidString
, &FfsGuid
);
1710 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid file GUID", NULL
);
1713 } else if (SFPIsToken ("FFS_FILETYPE")) {
1715 // ***********************************************************************
1717 // Found FFS_FILETYPE, format:
1718 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1720 if (FileType
[0] != 0) {
1721 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL
);
1725 if (!SFPIsToken ("=")) {
1726 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1730 if (!SFPGetNextToken (FileType
, sizeof (FileType
))) {
1731 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL
);
1735 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1736 else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1738 // ***********************************************************************
1740 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1741 // Spec says the bit is for future expansion, and must be false.
1743 if (FfsAttribDefined
& FFS_ATTRIB_HEADER_EXTENSION
) {
1745 mGlobals
.PrimaryPackagePath
,
1746 SFPGetLineNumber (),
1748 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1754 FfsAttribDefined
|= FFS_ATTRIB_HEADER_EXTENSION
;
1755 if (!SFPIsToken ("=")) {
1756 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1760 if (SFPIsToken ("TRUE")) {
1762 mGlobals
.PrimaryPackagePath
,
1763 SFPGetLineNumber (),
1765 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1769 } else if (SFPIsToken ("FALSE")) {
1774 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL
);
1779 else if (SFPIsToken ("FFS_ATTRIB_FIXED")) {
1781 // ***********************************************************************
1783 // Found: FFS_ATTRIB_FIXED = TRUE | FALSE
1785 if (FfsAttribDefined
& FFS_ATTRIB_FIXED
) {
1786 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_FIXED previously defined", NULL
);
1790 FfsAttribDefined
|= FFS_ATTRIB_FIXED
;
1791 if (!SFPIsToken ("=")) {
1792 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1796 if (SFPIsToken ("TRUE")) {
1797 FfsAttrib
|= FFS_ATTRIB_FIXED
;
1798 } else if (SFPIsToken ("FALSE")) {
1803 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1808 else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1810 // ***********************************************************************
1812 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1814 if (FfsAttribDefined
& FFS_ATTRIB_TAIL_PRESENT
) {
1815 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL
);
1819 FfsAttribDefined
|= FFS_ATTRIB_TAIL_PRESENT
;
1820 if (!SFPIsToken ("=")) {
1821 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1825 if (SFPIsToken ("TRUE")) {
1826 FfsAttrib
|= FFS_ATTRIB_TAIL_PRESENT
;
1827 } else if (SFPIsToken ("FALSE")) {
1832 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1835 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1837 // ***********************************************************************
1839 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1841 if (FfsAttribDefined
& FFS_ATTRIB_RECOVERY
) {
1842 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL
);
1846 FfsAttribDefined
|= FFS_ATTRIB_RECOVERY
;
1847 if (!SFPIsToken ("=")) {
1848 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1852 if (SFPIsToken ("TRUE")) {
1853 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
1854 } else if (SFPIsToken ("FALSE")) {
1859 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1862 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1864 // ***********************************************************************
1866 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1868 if (FfsAttribDefined
& FFS_ATTRIB_CHECKSUM
) {
1869 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL
);
1873 FfsAttribDefined
|= FFS_ATTRIB_CHECKSUM
;
1874 if (!SFPIsToken ("=")) {
1875 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1879 if (SFPIsToken ("TRUE")) {
1880 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
1881 } else if (SFPIsToken ("FALSE")) {
1886 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1889 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1891 // ***********************************************************************
1893 // Found FFS_ALIGNMENT, formats:
1894 // FFS_ALIGNMENT = 0-7
1895 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1897 if (FfsAttribDefined
& FFS_ATTRIB_DATA_ALIGNMENT
) {
1899 mGlobals
.PrimaryPackagePath
,
1900 SFPGetLineNumber (),
1902 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1908 FfsAttribDefined
|= FFS_ATTRIB_DATA_ALIGNMENT
;
1909 if (!SFPIsToken ("=")) {
1910 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1914 if (!SFPGetNumber (&FfsAlignment32
)) {
1915 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL
);
1919 if (FfsAlignment32
> 7) {
1920 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL
);
1924 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment32
) << 3);
1926 SFPGetNextToken (InputString
, sizeof (InputString
));
1927 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, InputString
, "unrecognized/unexpected token");
1932 // Close the primary package file
1936 // TODO: replace code below with basically a copy of the code above. Don't
1937 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1938 // to somehow keep track of whether or not the basename is defined multiple
1939 // times in the override package. Ditto on the file GUID.
1941 if (mGlobals
.OverridePackagePath
[0] != 0) {
1942 OverridePackage
= fopen (mGlobals
.OverridePackagePath
, "r");
1944 // NOTE: For package override to work correctly, the code below must be modified to
1945 // SET or CLEAR bits properly. For example, if the primary package set
1946 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1947 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1948 // the override functionality is not being used, so should be made obsolete. If I'm
1949 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1950 // used, and we'll address it then. 4/10/2003
1952 Error (__FILE__
, __LINE__
, 0, "package override functionality is not implemented correctly", NULL
);
1955 OverridePackage
= NULL
;
1958 #ifdef OVERRIDE_SUPPORTED
1959 if (OverridePackage
!= NULL
) {
1961 // Parse override package file
1963 fscanf (OverridePackage
, "%s", &InputString
);
1964 if (_strcmpi (InputString
, "PACKAGE.INF") != 0) {
1965 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
1969 // Match [dir] to Build Directory
1971 if (FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
) != 0) {
1972 Error (mGlobals
.OverridePackagePath
, 1, 0, mGlobals
.BuildDirectory
, "section not found in package file");
1977 while ((InputString
[0] != '[') && (!feof (OverridePackage
))) {
1978 if (GetNextLine (InputString
, OverridePackage
, &LineNumber
) != -1) {
1979 if (InputString
[0] != '[') {
1981 if (_strcmpi (InputString
, "BASE_NAME") == 0) {
1983 // found BASE_NAME, next is = and string.
1985 fscanf (OverridePackage
, "%s", &InputString
);
1986 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1987 if (strlen (InputString
) == 1) {
1991 fscanf (OverridePackage
, "%s", &InputString
);
1992 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1993 strcpy (BaseName
, InputString
);
1995 BreakString (InputString
, InputString
, 1);
1996 strcpy (BaseName
, InputString
);
1998 } else if (_strcmpi (InputString
, "IMAGE_SCRIPT") == 0) {
2000 // found IMAGE_SCRIPT, come back later to process it
2002 ImageScriptInOveride
= TRUE
;
2003 fscanf (OverridePackage
, "%s", &InputString
);
2004 } else if (_strcmpi (InputString
, "FFS_FILEGUID") == 0) {
2006 // found FILEGUID, next is = and string.
2008 fscanf (OverridePackage
, "%s", &InputString
);
2009 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2010 if (strlen (InputString
) == 1) {
2014 fscanf (OverridePackage
, "%s", &InputString
);
2015 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2016 Status
= StringToGuid (InputString
, &FfsGuid
);
2018 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2022 BreakString (InputString
, InputString
, 1);
2023 Status
= StringToGuid (InputString
, &FfsGuid
);
2025 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2029 } else if (_strcmpi (InputString
, "FFS_FILETYPE") == 0) {
2031 // found FILETYPE, next is = and string.
2033 fscanf (OverridePackage
, "%s", &InputString
);
2034 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2035 if (strlen (InputString
) == 1) {
2039 fscanf (OverridePackage
, "%s", &InputString
);
2040 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2041 strcpy (FileType
, InputString
);
2043 BreakString (InputString
, InputString
, 1);
2044 strcpy (FileType
, InputString
);
2047 } else if (_strcmpi (InputString
, "FFS_ATTRIB_RECOVERY") == 0) {
2049 // found FFS_ATTRIB_RECOVERY, next is = and string.
2051 fscanf (OverridePackage
, "%s", &InputString
);
2052 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2053 if (strlen (InputString
) == 1) {
2057 fscanf (OverridePackage
, "%s", &InputString
);
2058 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2059 if (_strcmpi (InputString
, "TRUE") == 0) {
2060 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2063 BreakString (InputString
, InputString
, 1);
2064 if (_strcmpi (InputString
, "TRUE") == 0) {
2065 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2068 } else if (_strcmpi (InputString
, "FFS_ATTRIB_CHECKSUM") == 0) {
2070 // found FFS_ATTRIB_CHECKSUM, 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_CHECKSUM
;
2084 BreakString (InputString
, InputString
, 1);
2085 if (_strcmpi (InputString
, "TRUE") == 0) {
2086 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2089 } else if (_strcmpi (InputString
, "FFS_ALIGNMENT") == 0) {
2091 // found FFS_ALIGNMENT, 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
);
2102 BreakString (InputString
, InputString
, 1);
2105 AsciiStringToUint64 (InputString
, FALSE
, &FfsAlignment
);
2106 if (FfsAlignment
> 7) {
2107 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "invalid FFS_ALIGNMENT value");
2111 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment
) << 3);
2112 } else if (strchr (InputString
, '=') != NULL
) {
2113 BreakString (InputString
, String
, 1);
2114 fseek (OverridePackage
, (-1 * (strlen (String
) + 1)), SEEK_CUR
);
2115 BreakString (InputString
, InputString
, 0);
2122 #endif // #ifdef OVERRIDE_SUPPORTED
2124 // Require that they specified a file GUID at least, since that's how we're
2127 if (GuidString
[0] == 0) {
2128 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "FFS_FILEGUID must be specified", NULL
);
2129 return STATUS_ERROR
;
2132 // Build Header and process image script
2134 FileBuffer
= (UINT8
*) malloc ((1024 * 1024 * 16) * sizeof (UINT8
));
2135 if (FileBuffer
== NULL
) {
2136 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
2141 if (ImageScriptInOveride
) {
2142 #ifdef OVERRIDE_SUPPORTED
2143 rewind (OverridePackage
);
2145 FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
);
2146 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2147 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2148 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2149 if (strchr (InputString
, '=') != NULL
) {
2150 BreakString (InputString
, InputString
, 0);
2154 while (InputString
[0] != '{') {
2155 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2156 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2159 // Found start of image script, process it
2161 FileSize
+= ProcessScript (FileBuffer
, OverridePackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2162 if (FileSize
== -1) {
2163 Error (NULL
, 0, 0, "failed to process script", NULL
);
2167 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2168 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2171 if (BaseName
[0] == '\"') {
2172 StripQuotes (BaseName
);
2175 if (mGlobals
.OutputFilePath
[0]) {
2177 // Use user specified output file name
2179 strcpy (InputString
, mGlobals
.OutputFilePath
);
2182 // Construct the output file name according to FileType
2184 if (BaseName
[0] != 0) {
2185 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2187 strcpy (InputString
, GuidString
);
2190 switch (StringToType (FileType
)) {
2192 case EFI_FV_FILETYPE_SECURITY_CORE
:
2193 strcat (InputString
, ".SEC");
2196 case EFI_FV_FILETYPE_PEIM
:
2197 case EFI_FV_FILETYPE_PEI_CORE
:
2198 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2199 strcat (InputString
, ".PEI");
2202 case EFI_FV_FILETYPE_DRIVER
:
2203 case EFI_FV_FILETYPE_DXE_CORE
:
2204 strcat (InputString
, ".DXE");
2207 case EFI_FV_FILETYPE_APPLICATION
:
2208 strcat (InputString
, ".APP");
2211 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2212 strcat (InputString
, ".FVI");
2215 case EFI_FV_FILETYPE_RAW
:
2216 strcat (InputString
, ".RAW");
2219 case EFI_FV_FILETYPE_ALL
:
2220 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2224 strcat (InputString
, ".FFS");
2229 if (ForceUncompress
) {
2230 strcat (InputString
, ".ORG");
2233 Out
= fopen (InputString
, "wb");
2235 Error (NULL
, 0, 0, InputString
, "could not open output file for writing");
2239 // create ffs header
2241 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2242 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2243 FileHeader
.Type
= StringToType (FileType
);
2244 if (((FfsAttrib
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3) < MinFfsDataAlignOverride
) {
2245 FfsAttrib
= (FfsAttrib
& ~FFS_ATTRIB_DATA_ALIGNMENT
) | (MinFfsDataAlignOverride
<< 3);
2247 FileHeader
.Attributes
= FfsAttrib
;
2249 // Now FileSize includes the EFI_FFS_FILE_HEADER
2251 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2252 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2253 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2254 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2256 // Fill in checksums and state, these must be zero for checksumming
2258 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2259 // FileHeader.IntegrityCheck.Checksum.File = 0;
2260 // FileHeader.State = 0;
2262 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2263 (UINT8
*) &FileHeader
,
2264 sizeof (EFI_FFS_FILE_HEADER
)
2266 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2267 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2268 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) &FileHeader
, FileSize
);
2270 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) ((UINTN
)&FileHeader
+ sizeof (EFI_FFS_FILE_HEADER
)), FileSize
- sizeof (EFI_FFS_FILE_HEADER
));
2273 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2276 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2280 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2281 Error (NULL
, 0, 0, "failed to write file header to output file", NULL
);
2287 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2288 Error (NULL
, 0, 0, "failed to write all bytes to output file", NULL
);
2294 #endif // #ifdef OVERRIDE_SUPPORTED
2297 // Open primary package file and process the IMAGE_SCRIPT section
2299 PrimaryPackage
= fopen (mGlobals
.PrimaryPackagePath
, "r");
2300 if (PrimaryPackage
== NULL
) {
2301 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
2306 FindSectionInPackage (".", PrimaryPackage
, &LineNumber
);
2307 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2308 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2309 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2310 if (strchr (InputString
, '=') != NULL
) {
2311 BreakString (InputString
, InputString
, 0);
2315 while (InputString
[0] != '{') {
2316 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2317 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2320 // Found start of image script, process it
2322 FileSize
+= ProcessScript (FileBuffer
, PrimaryPackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2323 if (FileSize
== -1) {
2324 Error (NULL
, 0, 0, "failed to process script", NULL
);
2328 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2329 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2332 if (BaseName
[0] == '\"') {
2333 StripQuotes (BaseName
);
2336 if (mGlobals
.OutputFilePath
[0]) {
2338 // Use user specified output file name
2340 strcpy (InputString
, mGlobals
.OutputFilePath
);
2343 // Construct the output file name according to FileType
2345 if (BaseName
[0] != 0) {
2346 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2348 strcpy (InputString
, GuidString
);
2351 switch (StringToType (FileType
)) {
2353 case EFI_FV_FILETYPE_SECURITY_CORE
:
2354 strcat (InputString
, ".SEC");
2357 case EFI_FV_FILETYPE_PEIM
:
2358 case EFI_FV_FILETYPE_PEI_CORE
:
2359 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2360 strcat (InputString
, ".PEI");
2363 case EFI_FV_FILETYPE_DRIVER
:
2364 case EFI_FV_FILETYPE_DXE_CORE
:
2365 strcat (InputString
, ".DXE");
2368 case EFI_FV_FILETYPE_APPLICATION
:
2369 strcat (InputString
, ".APP");
2372 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2373 strcat (InputString
, ".FVI");
2376 case EFI_FV_FILETYPE_RAW
:
2377 strcat (InputString
, ".RAW");
2380 case EFI_FV_FILETYPE_ALL
:
2381 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2385 strcat (InputString
, ".FFS");
2390 if (ForceUncompress
) {
2391 strcat (InputString
, ".ORG");
2394 Out
= fopen (InputString
, "wb");
2396 Error (NULL
, 0, 0, InputString
, "failed to open output file for writing");
2400 // Initialize the FFS file header
2402 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2403 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2404 FileHeader
.Type
= StringToType (FileType
);
2405 if (((FfsAttrib
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3) < MinFfsDataAlignOverride
) {
2406 FfsAttrib
= (FfsAttrib
& ~FFS_ATTRIB_DATA_ALIGNMENT
) | (MinFfsDataAlignOverride
<< 3);
2408 FileHeader
.Attributes
= FfsAttrib
;
2410 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2412 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2414 // If using a tail, then it adds two bytes
2416 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2418 // Tail is not allowed for pad and 0-length files
2420 if ((FileHeader
.Type
== EFI_FV_FILETYPE_FFS_PAD
) || (FileSize
== sizeof (EFI_FFS_FILE_HEADER
))) {
2422 mGlobals
.PrimaryPackagePath
,
2425 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2431 FileSize
+= sizeof (EFI_FFS_FILE_TAIL
);
2434 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2435 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2436 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2438 // Fill in checksums and state, they must be 0 for checksumming.
2440 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2441 // FileHeader.IntegrityCheck.Checksum.File = 0;
2442 // FileHeader.State = 0;
2444 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2445 (UINT8
*) &FileHeader
,
2446 sizeof (EFI_FFS_FILE_HEADER
)
2448 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2450 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2451 // Checksum does not include the tail
2453 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2454 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2456 FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
)
2459 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2461 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2465 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2468 // Set the state now. Spec says the checksum assumes the state is 0
2470 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2472 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2475 // If there is a tail, then set it
2477 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2478 TailValue
= FileHeader
.IntegrityCheck
.TailReference
;
2479 TailValue
= (UINT16
) (~TailValue
);
2481 (UINT8
*) FileBuffer
+ FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
),
2488 // Write the FFS file header
2490 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2491 Error (NULL
, 0, 0, "failed to write file header contents", NULL
);
2497 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2498 Error (NULL
, 0, 0, "failed to write file contents", NULL
);
2509 if (PrimaryPackage
!= NULL
) {
2510 fclose (PrimaryPackage
);
2513 if (FileBuffer
!= NULL
) {
2517 if (OverridePackage
!= NULL
) {
2518 fclose (OverridePackage
);
2521 return GetUtilityStatus ();
2531 Routine Description:
2537 argc - Number of command line parameters.
2538 argv - Array of pointers to parameter strings.
2541 STATUS_SUCCESS - Utility exits successfully.
2542 STATUS_ERROR - Some error occurred during execution.
2548 // Set the name of our utility for error reporting purposes.
2550 SetUtilityName (UTILITY_NAME
);
2551 Status
= ProcessCommandLineArgs (argc
, argv
);
2553 if (Status
!= STATUS_SUCCESS
) {
2557 Status
= MainEntry (argc
, argv
, TRUE
);
2558 if (Status
== STATUS_SUCCESS
) {
2559 MainEntry (argc
, argv
, FALSE
);
2562 // If any errors were reported via the standard error reporting
2563 // routines, then the status has been saved. Get the value and
2564 // return it to the caller.
2566 return GetUtilityStatus ();
2571 ProcessCommandLineArgs (
2577 Routine Description:
2578 Process the command line arguments.
2581 Argc - as passed in to main()
2582 Argv - as passed in to main()
2585 STATUS_SUCCESS - arguments all ok
2586 STATUS_ERROR - problem with args, so caller should exit
2591 UINT8
*OriginalPrimaryPackagePath
;
2592 UINT8
*OriginalOverridePackagePath
;
2596 // If no args, then print usage instructions and return an error
2600 return STATUS_ERROR
;
2603 OriginalPrimaryPackagePath
= NULL
;
2604 OriginalOverridePackagePath
= NULL
;
2605 memset (&mGlobals
, 0, sizeof (mGlobals
));
2609 if (_strcmpi (Argv
[0], "-b") == 0) {
2611 // OPTION: -b BuildDirectory
2612 // Make sure there is another argument, then save it to our globals.
2615 Error (NULL
, 0, 0, "-b option requires the build directory name", NULL
);
2616 return STATUS_ERROR
;
2619 if (mGlobals
.BuildDirectory
[0]) {
2620 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2621 return STATUS_ERROR
;
2624 strcpy (mGlobals
.BuildDirectory
, Argv
[1]);
2627 } else if (_strcmpi (Argv
[0], "-p1") == 0) {
2629 // OPTION: -p1 PrimaryPackageFile
2630 // Make sure there is another argument, then save it to our globals.
2633 Error (NULL
, 0, 0, Argv
[0], "option requires the primary package file name");
2634 return STATUS_ERROR
;
2637 if (OriginalPrimaryPackagePath
) {
2638 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2639 return STATUS_ERROR
;
2642 OriginalPrimaryPackagePath
= Argv
[1];
2645 } else if (_strcmpi (Argv
[0], "-p2") == 0) {
2647 // OPTION: -p2 OverridePackageFile
2648 // Make sure there is another argument, then save it to our globals.
2651 Error (NULL
, 0, 0, Argv
[0], "option requires the override package file name");
2652 return STATUS_ERROR
;
2655 if (OriginalOverridePackagePath
) {
2656 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2657 return STATUS_ERROR
;
2660 OriginalOverridePackagePath
= Argv
[1];
2663 } else if (_strcmpi (Argv
[0], "-o") == 0) {
2665 // OPTION: -o OutputFilePath
2666 // Make sure there is another argument, then save it to out globals.
2669 Error (NULL
, 0, 0, Argv
[0], "option requires the output file name");
2670 return STATUS_ERROR
;
2672 if (mGlobals
.OutputFilePath
[0]) {
2673 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2674 return STATUS_ERROR
;
2677 strcpy (mGlobals
.OutputFilePath
, Argv
[1]);
2680 } else if (_strcmpi (Argv
[0], "-v") == 0) {
2682 // OPTION: -v verbose
2684 mGlobals
.Verbose
= TRUE
;
2685 } else if (_strcmpi (Argv
[0], "-d") == 0) {
2687 // OPTION: -d name=value
2688 // Make sure there is another argument, then add it to our macro list.
2691 Error (NULL
, 0, 0, Argv
[0], "option requires the macro definition");
2692 return STATUS_ERROR
;
2698 } else if (_strcmpi (Argv
[0], "-h") == 0) {
2703 return STATUS_ERROR
;
2704 } else if (_strcmpi (Argv
[0], "-?") == 0) {
2709 return STATUS_ERROR
;
2711 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
2713 return STATUS_ERROR
;
2721 // Must have at least specified the build directory
2723 if (!mGlobals
.BuildDirectory
[0]) {
2724 Error (NULL
, 0, 0, "must specify build directory", NULL
);
2725 return STATUS_ERROR
;
2729 // Must have at least specified the package file name
2731 if (OriginalPrimaryPackagePath
== NULL
) {
2732 Error (NULL
, 0, 0, "must specify primary package file", NULL
);
2733 return STATUS_ERROR
;
2736 PackageName
= OriginalPrimaryPackagePath
+ strlen (OriginalPrimaryPackagePath
);
2737 while ((*PackageName
!= '\\') && (*PackageName
!= '/') &&
2738 (PackageName
!= OriginalPrimaryPackagePath
)) {
2742 // Skip the '\' or '/'
2744 if (PackageName
!= OriginalPrimaryPackagePath
) {
2747 sprintf (mGlobals
.PrimaryPackagePath
, "%s\\%s.new", mGlobals
.BuildDirectory
, PackageName
);
2748 Status
= ReplaceMacros (OriginalPrimaryPackagePath
, mGlobals
.PrimaryPackagePath
);
2749 if (Status
== STATUS_WARNING
) {
2751 // No macro replacement, use the previous package file
2753 strcpy (mGlobals
.PrimaryPackagePath
, OriginalPrimaryPackagePath
);
2754 } else if (Status
!= STATUS_SUCCESS
) {
2758 if (OriginalOverridePackagePath
!= NULL
) {
2759 PackageName
= OriginalOverridePackagePath
+ strlen (OriginalOverridePackagePath
);
2760 while ((*PackageName
!= '\\') && (*PackageName
!= '/') &&
2761 (PackageName
!= OriginalOverridePackagePath
)) {
2765 // Skip the '\' or '/'
2767 if (PackageName
!= OriginalOverridePackagePath
) {
2770 sprintf (mGlobals
.OverridePackagePath
, "%s\\%s.new", mGlobals
.BuildDirectory
, PackageName
);
2771 Status
= ReplaceMacros (OriginalOverridePackagePath
, mGlobals
.OverridePackagePath
);
2772 if (Status
== STATUS_WARNING
) {
2774 // No macro replacement, use the previous package file
2776 strcpy (mGlobals
.OverridePackagePath
, OriginalOverridePackagePath
);
2777 } else if (Status
!= STATUS_SUCCESS
) {
2782 return STATUS_SUCCESS
;
2792 Routine Description:
2794 Add or override a macro definition.
2798 MacroString - macro definition string: name=value
2811 // Seperate macro name and value by '\0'
2813 for (Value
= MacroString
; *Value
&& (*Value
!= '='); Value
++);
2815 if (*Value
== '=') {
2821 // We now have a macro name and value.
2822 // Look for an existing macro and overwrite it.
2824 Macro
= mGlobals
.MacroList
;
2826 if (_strcmpi (MacroString
, Macro
->Name
) == 0) {
2827 Macro
->Value
= Value
;
2831 Macro
= Macro
->Next
;
2835 // Does not exist, create a new one
2837 NewMacro
= (MACRO
*) malloc (sizeof (MACRO
));
2838 memset ((UINT8
*) NewMacro
, 0, sizeof (MACRO
));
2839 NewMacro
->Name
= MacroString
;
2840 NewMacro
->Value
= Value
;
2843 // Add it to the head of the list.
2845 NewMacro
->Next
= mGlobals
.MacroList
;
2846 mGlobals
.MacroList
= NewMacro
;
2858 Routine Description:
2864 MacroName - The name of macro
2868 Pointer to the value of the macro if found
2869 NULL if the macro is not found
2880 Macro
= mGlobals
.MacroList
;
2882 if (_strcmpi (MacroName
, Macro
->Name
) == 0) {
2883 return Macro
->Value
;
2885 Macro
= Macro
->Next
;
2889 // Try environment variable
2891 Value
= getenv (MacroName
);
2892 if (Value
== NULL
) {
2893 printf ("Environment variable %s not found!\n", MacroName
);
2904 Routine Description:
2906 Free the macro list.
2921 Macro
= mGlobals
.MacroList
;
2923 NextMacro
= Macro
->Next
;
2927 mGlobals
.MacroList
= NULL
;
2940 Routine Description:
2942 Replace all the macros in InputFile to create the OutputFile.
2946 InputFile - Input package file for macro replacement
2947 OutputFile - Output package file after macro replacement
2951 STATUS_SUCCESS - Output package file is created successfully after the macro replacement.
2952 STATUS_WARNING - Output package file is not created because of no macro replacement.
2953 STATUS_ERROR - Some error occurred during execution.
2966 // Get the file size, and then read the entire thing into memory.
2967 // Allocate extra space for a terminator character.
2969 if ((Fptr
= fopen (InputFile
, "r")) == NULL
) {
2970 Error (NULL
, 0, 0, InputFile
, "can't open input file");
2971 return STATUS_ERROR
;
2973 fseek (Fptr
, 0, SEEK_END
);
2974 FileSize
= ftell (Fptr
);
2975 fseek (Fptr
, 0, SEEK_SET
);
2976 FileBuffer
= malloc (FileSize
+ 1);
2977 if (FileBuffer
== NULL
) {
2979 Error (NULL
, 0, 0, InputFile
, "file buffer memory allocation failure");
2980 return STATUS_ERROR
;
2982 fread (FileBuffer
, FileSize
, 1, Fptr
);
2983 FileBuffer
[FileSize
] = '\0';
2987 // Walk the entire file, replacing $(MACRO_NAME).
2990 FromPtr
= FileBuffer
;
2991 SaveStart
= FromPtr
;
2993 if ((*FromPtr
== '$') && (*(FromPtr
+ 1) == '(')) {
2995 for (ToPtr
= FromPtr
; *ToPtr
&& (*ToPtr
!= ')'); ToPtr
++);
2998 // Find an $(MACRO_NAME), replace it
3001 Value
= GetMacroValue (FromPtr
);
3004 if ((Fptr
= fopen (OutputFile
, "w")) == NULL
) {
3006 Error (NULL
, 0, 0, OutputFile
, "can't open output file");
3007 return STATUS_ERROR
;
3010 if (Value
!= NULL
) {
3011 fprintf (Fptr
, "%s%s", SaveStart
, Value
);
3013 fprintf (Fptr
, "%s", SaveStart
);
3016 // Continue macro replacement for the remaining string line
3019 SaveStart
= FromPtr
;
3029 fprintf (Fptr
, "%s", SaveStart
);
3035 return STATUS_SUCCESS
;
3037 return STATUS_WARNING
;