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"
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 TOOLVERSION "0.32"
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
];
130 static EFI_GUID mZeroGuid
= { 0 };
132 static UINT8 MinFfsDataAlignOverride
= 0;
143 Removes quotes and/or whitespace from around a string
147 String - String to remove quotes from
159 Index2
= strspn (String
, "\" \t\n");
160 StrLen
= strlen (String
);
162 for (Index
= Index2
; String
[Index
] != '\"', Index
< StrLen
; Index
++) {
163 String
[Index
- Index2
] = String
[Index
];
166 String
[Index
- Index2
] = 0;
178 Print Error / Help message.
191 printf (UTILITY_NAME
" -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\"\n");
192 printf (" -d \"name=value\" -v\n");
193 printf (" -b \"build directory\":\n");
194 printf (" specifies the full path to the component build directory.\n");
195 printf (" -p1 \"P1_path\":\n");
196 printf (" specifies fully qualified file name to the primary package file.\n");
197 printf (" This file will normally exist in the same directory as the makefile\n");
198 printf (" for the component. Required.\n");
199 printf (" -p2 \"P2_path\":\n");
200 printf (" specifies fully qualified file name to the override package file.\n");
201 printf (" This file will normally exist in the build tip. Optional.\n");
202 printf (" -d \"name=value\":\n");
203 printf (" add a macro definition for package file. Optional.\n");
205 printf (" verbose. Optional.\n");
218 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
222 String - String to test
224 In - Open file to move pointer within
228 -1 - End of file reached
237 if ((String
[0] == '/') && (String
[1] == '/')) {
238 while (CharBuffer
!= '\n') {
239 fscanf (In
, "%c", &CharBuffer
);
254 IN CONST CHAR8
*Source
,
255 OUT CHAR8
*Destination
,
262 Takes an input string and returns either the part before the =, or the part after the =, depending on direction
266 Source - String to break
268 Destination - Buffer to place new string in
270 Direction - 0 to return all of source string before =
271 1 to return all of source string after =
285 if (strchr (Source
, '=') == NULL
) {
286 strcpy (Destination
, Source
);
291 if (Direction
== 0) {
293 // return part of string before =
295 while (Source
[Index
] != '=') {
296 Destination
[Index
] = Source
[Index
++];
299 Destination
[Index
] = 0;
302 // return part of string after =
304 strcpy (Destination
, strchr (Source
, '=') + 1);
311 OUT CHAR8
*Destination
,
313 IN OUT UINT32
*LineNumber
319 Gets the next non-commented line from the file
323 Destination - Where to put string
325 Package - Package to get string from
327 LineNumber - The actual line number.
331 -1 - End of file reached
336 CHAR8 String
[_MAX_PATH
];
337 fscanf (Package
, "%s", &String
);
338 if (feof (Package
)) {
342 while (TestComment (String
, Package
) == 1) {
343 fscanf (Package
, "%s", &String
);
344 if (feof (Package
)) {
349 strcpy (Destination
, String
);
356 IN OUT CHAR8
*String
,
358 IN OUT UINT32
*LineNumber
364 Checks to see if string is line continuation character, if so goes to next valid line
368 String - String to test
370 In - Open file to move pointer within
372 LineNumber - The line number.
386 while (String
[0] == '\\') {
387 while (ByteBuffer
!= '\n') {
388 fscanf (In
, "%c", &ByteBuffer
);
391 if (GetNextLine (String
, In
, LineNumber
) == -1) {
399 while (String
[0] == '\n') {
400 if (GetNextLine (String
, In
, LineNumber
) == -1) {
415 FindSectionInPackage (
416 IN CHAR8
*BuildDirectory
,
417 IN
FILE *OverridePackage
,
418 IN OUT UINT32
*LineNumber
424 Finds the matching section within the package
428 BuildDirectory - name of section to find
430 OverridePackage - Package file to search within
432 LineNumber - The line number.
436 -1 - End of file reached
441 CHAR8 String
[_MAX_PATH
];
442 CHAR8 NewString
[_MAX_PATH
];
445 while (strcmp (BuildDirectory
, String
) != 0) {
446 if (GetNextLine (NewString
, OverridePackage
, LineNumber
) != 0) {
450 if (NewString
[0] == '[') {
451 if (NewString
[strlen (NewString
) - 1] != ']') {
453 // have to construct string.
455 strcpy (String
, NewString
+ 1);
458 fscanf (OverridePackage
, "%s", &NewString
);
459 if (feof (OverridePackage
)) {
463 if (NewString
[0] != ']') {
464 if (strlen (String
) != 0) {
465 strcat (String
, " ");
468 strcat (String
, NewString
);
469 if (String
[strlen (String
) - 1] == ']') {
470 String
[strlen (String
) - 1] = 0;
478 NewString
[strlen (NewString
) - 1] = 0;
479 strcpy (String
, NewString
+ 1);
489 GenSimpleGuidSection (
490 IN OUT UINT8
*FileBuffer
,
491 IN OUT UINT32
*BufferSize
,
493 IN EFI_GUID SignGuid
,
494 IN UINT16 GuidedSectionAttributes
500 add GUIDed section header for the data buffer.
501 data stays in same location (overwrites source data).
505 FileBuffer - Buffer containing data to sign
507 BufferSize - On input, the size of FileBuffer. On output, the size of
508 actual section data (including added section header).
510 DataSize - Length of data to Sign
512 SignGuid - Guid to be add.
514 GuidedSectionAttributes - The section attribute.
518 EFI_SUCCESS - Successful
519 EFI_OUT_OF_RESOURCES - Not enough resource.
525 EFI_GUID_DEFINED_SECTION GuidSectionHeader
;
536 TotalSize
= DataSize
+ sizeof (EFI_GUID_DEFINED_SECTION
);
537 GuidSectionHeader
.CommonHeader
.Type
= EFI_SECTION_GUID_DEFINED
;
538 GuidSectionHeader
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
539 GuidSectionHeader
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
540 GuidSectionHeader
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
541 memcpy (&(GuidSectionHeader
.SectionDefinitionGuid
), &SignGuid
, sizeof (EFI_GUID
));
542 GuidSectionHeader
.Attributes
= GuidedSectionAttributes
;
543 GuidSectionHeader
.DataOffset
= sizeof (EFI_GUID_DEFINED_SECTION
);
545 SwapBuffer
= (UINT8
*) malloc (DataSize
);
546 if (SwapBuffer
== NULL
) {
547 return EFI_OUT_OF_RESOURCES
;
550 memcpy (SwapBuffer
, FileBuffer
, DataSize
);
551 memcpy (FileBuffer
, &GuidSectionHeader
, sizeof (EFI_GUID_DEFINED_SECTION
));
552 memcpy (FileBuffer
+ sizeof (EFI_GUID_DEFINED_SECTION
), SwapBuffer
, DataSize
);
555 // Make sure section ends on a DWORD boundary
557 while ((TotalSize
& 0x03) != 0) {
558 FileBuffer
[TotalSize
] = 0;
562 *BufferSize
= TotalSize
;
564 if (SwapBuffer
!= NULL
) {
583 Compress the data and add section header for the compressed data.
584 Compressed data (with section header) stays in same location as the source
585 (overwrites source data).
589 FileBuffer - Buffer containing data to Compress
591 BufferSize - On input, the size of FileBuffer. On output, the size of
592 actual compressed data (including added section header).
593 When buffer is too small, this value indicates the size needed.
595 DataSize - The size of data to compress
597 Type - The compression type (not used currently).
598 Assume EFI_HEAVY_COMPRESSION.
602 EFI_BUFFER_TOO_SMALL - Buffer size is too small.
603 EFI_UNSUPPORTED - Compress type can not be supported.
604 EFI_SUCCESS - Successful
605 EFI_OUT_OF_RESOURCES - Not enough resource.
613 EFI_COMPRESSION_SECTION CompressionSet
;
614 UINT8 CompressionType
;
615 COMPRESS_FUNCTION CompressFunction
;
617 Status
= EFI_SUCCESS
;
621 CompressFunction
= NULL
;
624 // Get the compress type
626 if (_strcmpi (Type
, "Dummy") == 0) {
628 // Added "Dummy" to keep backward compatibility.
630 CompressionType
= EFI_STANDARD_COMPRESSION
;
631 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
633 } else if (_strcmpi (Type
, "LZH") == 0) {
635 // EFI stardard compression (LZH)
637 CompressionType
= EFI_STANDARD_COMPRESSION
;
638 CompressFunction
= (COMPRESS_FUNCTION
) TianoCompress
;
642 // Customized compression
644 Status
= SetCustomizedCompressionType (Type
);
645 if (EFI_ERROR (Status
)) {
649 CompressionType
= EFI_CUSTOMIZED_COMPRESSION
;
650 CompressFunction
= (COMPRESS_FUNCTION
) CustomizedCompress
;
653 // Compress the raw data
655 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
656 if (Status
== EFI_BUFFER_TOO_SMALL
) {
657 CompData
= malloc (CompSize
);
659 return EFI_OUT_OF_RESOURCES
;
662 Status
= CompressFunction (FileBuffer
, DataSize
, CompData
, &CompSize
);
665 if (EFI_ERROR (Status
)) {
666 if (CompData
!= NULL
) {
673 TotalSize
= CompSize
+ sizeof (EFI_COMPRESSION_SECTION
);
678 if (TotalSize
> *BufferSize
) {
679 *BufferSize
= TotalSize
;
680 if (CompData
!= NULL
) {
684 return EFI_BUFFER_TOO_SMALL
;
687 // Add the section header for the compressed data
689 CompressionSet
.CommonHeader
.Type
= EFI_SECTION_COMPRESSION
;
690 CompressionSet
.CommonHeader
.Size
[0] = (UINT8
) (TotalSize
& 0xff);
691 CompressionSet
.CommonHeader
.Size
[1] = (UINT8
) ((TotalSize
& 0xff00) >> 8);
692 CompressionSet
.CommonHeader
.Size
[2] = (UINT8
) ((TotalSize
& 0xff0000) >> 16);
693 CompressionSet
.CompressionType
= CompressionType
;
694 CompressionSet
.UncompressedLength
= DataSize
;
697 // Copy header and data to the buffer
699 memcpy (FileBuffer
, &CompressionSet
, sizeof (EFI_COMPRESSION_SECTION
));
700 memcpy (FileBuffer
+ sizeof (CompressionSet
), CompData
, CompSize
);
703 // Make sure section ends on a DWORD boundary
705 while ((TotalSize
& 0x03) != 0) {
706 FileBuffer
[TotalSize
] = 0;
710 *BufferSize
= TotalSize
;
712 if (CompData
!= NULL
) {
728 Removes Parenthesis from around a string
732 String - String to remove parens from
742 if (String
[0] != '(') {
746 for (Index
= 1; String
[Index
] != ')'; Index
++) {
747 String
[Index
- 1] = String
[Index
];
748 if (String
[Index
] == 0) {
753 String
[Index
- 1] = 0;
767 Removes Equal Mark from around a string
771 String - String to remove equal mark from
781 if (String
[0] != '=' && String
[strlen (String
) - 1] != '=') {
785 if (String
[0] == '=') {
787 for (Index
= 1; String
[Index
] != 0; Index
++) {
788 String
[Index
- 1] = String
[Index
];
791 String
[Index
- 1] = 0;
794 if (String
[strlen (String
) - 1] == '=') {
795 String
[strlen (String
) - 1] = 0;
803 SplitAttributesField (
805 IN CHAR8
*AttributesArray
[],
806 IN OUT UINT32
*NumberOfAttributes
809 NumberOfAttributes: on input, it specifies the current number of attributes
810 stored in AttributeArray.
811 on output, it is updated to the latest number of attributes
812 stored in AttributesArray.
821 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
822 ZeroMem (CharBuffer
, _MAX_PATH
);
824 for (Index
= 0, z
= 0, Index2
= 0; Index
< strlen (Buffer
); Index
++) {
826 if (Buffer
[Index
] != '|') {
827 CharBuffer
[z
] = Buffer
[Index
];
832 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
836 // allocate new char buffer for the next attributes string
838 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
839 ZeroMem (CharBuffer
, _MAX_PATH
);
846 // record the last attributes string in the Buffer
848 AttributesArray
[*NumberOfAttributes
+ Index2
] = CharBuffer
;
851 *NumberOfAttributes
+= Index2
;
859 CHAR8
*ToolArgumentsArray
[],
861 CHAR8
**PtrInputFileName
,
862 CHAR8
**PtrOutputFileName
,
864 UINT16
*GuidedSectionAttributes
867 CHAR8 Buffer
[_MAX_PATH
];
868 BOOLEAN ArgumentsFlag
;
872 BOOLEAN AttributesFlag
;
880 CHAR8
*AttributesArray
[MAX_ARRAY_SIZE
];
881 UINT32 NumberOfAttributes
;
882 CHAR8
*InputFileName
;
883 CHAR8
*OutputFileName
;
887 ArgumentsFlag
= FALSE
;
891 AttributesFlag
= FALSE
;
893 // Start at 1, since ToolArgumentsArray[0]
894 // is the program name.
901 NumberOfAttributes
= 0;
902 InputFileName
= NULL
;
903 OutputFileName
= NULL
;
905 ZeroMem (Buffer
, _MAX_PATH
);
906 ZeroMem (AttributesArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
908 while (Buffer
[0] != ')') {
910 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
911 CheckSlash (Buffer
, Package
, &LineNumber
);
912 StripEqualMark (Buffer
);
914 Error (NULL
, 0, 0, "failed to get next line from package file", NULL
);
918 if (Buffer
[0] == ')') {
920 } else if (_strcmpi (Buffer
, "ARGS") == 0) {
922 ArgumentsFlag
= TRUE
;
923 AttributesFlag
= FALSE
;
926 } else if (_strcmpi (Buffer
, "INPUT") == 0) {
929 ArgumentsFlag
= FALSE
;
930 AttributesFlag
= FALSE
;
933 } else if (_strcmpi (Buffer
, "OUTPUT") == 0) {
936 ArgumentsFlag
= FALSE
;
937 AttributesFlag
= FALSE
;
940 } else if (_strcmpi (Buffer
, "GUID") == 0) {
943 ArgumentsFlag
= FALSE
;
944 AttributesFlag
= FALSE
;
946 // fetch the GUID for the section
950 } else if (_strcmpi (Buffer
, "ATTRIBUTES") == 0) {
952 AttributesFlag
= TRUE
;
953 ArgumentsFlag
= FALSE
;
955 // fetch the GUIDed Section's Attributes
959 } else if (_strcmpi (Buffer
, "") == 0) {
963 // get all command arguments into ToolArgumentsArray
967 StripEqualMark (Buffer
);
969 CharBuffer
= (CHAR8
*) malloc (_MAX_PATH
);
970 if (CharBuffer
== NULL
) {
974 ZeroMem (CharBuffer
, sizeof (_MAX_PATH
));
976 ToolArgumentsArray
[argc
] = CharBuffer
;
978 strcpy (ToolArgumentsArray
[argc
], Buffer
);
981 ToolArgumentsArray
[argc
] = NULL
;
987 StripEqualMark (Buffer
);
989 InputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
990 if (InputFileName
== NULL
) {
994 ZeroMem (InputFileName
, sizeof (_MAX_PATH
));
996 strcpy (InputFileName
, Buffer
);
1004 StripEqualMark (Buffer
);
1006 OutputFileName
= (CHAR8
*) malloc (_MAX_PATH
);
1007 if (OutputFileName
== NULL
) {
1011 ZeroMem (OutputFileName
, sizeof (_MAX_PATH
));
1013 strcpy (OutputFileName
, Buffer
);
1021 StripEqualMark (Buffer
);
1023 Status
= StringToGuid (Buffer
, Guid
);
1024 if (EFI_ERROR (Status
)) {
1032 if (AttributesFlag
) {
1034 StripEqualMark (Buffer
);
1037 // there might be no space between each attribute in the statement,
1038 // split them aside and return each attribute string
1039 // in the AttributesArray
1041 SplitAttributesField (Buffer
, AttributesArray
, &NumberOfAttributes
);
1045 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j);
1046 // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1);
1048 for (z
= 0; z
< NumberOfAttributes
; z
++) {
1049 if (_strcmpi (AttributesArray
[z
], "PROCESSING_REQUIRED") == 0) {
1050 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_PROCESSING_REQUIRED
;
1051 } else if (_strcmpi (AttributesArray
[z
], "AUTH_STATUS_VALID") == 0) {
1052 *GuidedSectionAttributes
|= EFI_GUIDED_SECTION_AUTH_STATUS_VALID
;
1058 for (Index2
= 0; Index2
< MAX_ARRAY_SIZE
; Index2
++) {
1059 if (AttributesArray
[Index2
] == NULL
) {
1063 free (AttributesArray
[Index2
]);
1066 *PtrInputFileName
= InputFileName
;
1067 *PtrOutputFileName
= OutputFileName
;
1075 IN OUT UINT8
*FileBuffer
,
1077 IN CHAR8
*BuildDirectory
,
1078 IN BOOLEAN ForceUncompress
1082 Routine Description:
1084 Signs the section, data stays in same location
1088 FileBuffer - Data Buffer
1090 Package - Points to curly brace in Image Script
1092 BuildDirectory - Name of the source directory parameter
1094 ForceUncompress - Whether to force uncompress.
1098 Number of bytes added to file buffer
1107 UINT16 TeStrippedSize
;
1108 CHAR8 Buffer
[_MAX_PATH
];
1109 CHAR8 Type
[_MAX_PATH
];
1110 CHAR8 FileName
[_MAX_PATH
];
1116 UINT32 SourceDataSize
;
1117 CHAR8
*ToolArgumentsArray
[MAX_ARRAY_SIZE
];
1118 CHAR8
*OutputFileName
;
1119 CHAR8
*InputFileName
;
1120 CHAR8 ToolName
[_MAX_PATH
];
1128 UINT16 GuidedSectionAttributes
;
1129 UINT8
*TargetFileBuffer
;
1131 OutputFileName
= NULL
;
1132 InputFileName
= NULL
;
1136 GuidedSectionAttributes
= 0;
1137 TargetFileBuffer
= NULL
;
1142 for (Index3
= 0; Index3
< MAX_ARRAY_SIZE
; ++Index3
) {
1143 ToolArgumentsArray
[Index3
] = NULL
;
1146 while (Buffer
[0] != '}') {
1147 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1148 CheckSlash (Buffer
, Package
, &LineNumber
);
1150 printf ("ERROR in IMAGE SCRIPT!\n");
1155 if (_strcmpi (Buffer
, "Compress") == 0) {
1160 // read compression type
1162 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1163 CheckSlash (Buffer
, Package
, &LineNumber
);
1166 StripParens (Buffer
);
1167 strcpy (Type
, Buffer
);
1171 while (Buffer
[0] != '{') {
1172 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1173 CheckSlash (Buffer
, Package
, &LineNumber
);
1177 ReturnValue
= ProcessScript (&FileBuffer
[Size
], Package
, BuildDirectory
, ForceUncompress
);
1178 if (ReturnValue
== -1) {
1183 // Call compress routine on buffer.
1184 // Occasionally, compressed data + section header would
1185 // be largere than the source and EFI_BUFFER_TOO_SMALL is
1186 // returned from CompressSection()
1188 SourceDataSize
= ReturnValue
;
1190 if (!ForceUncompress
) {
1192 Status
= CompressSection (
1199 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1200 Status
= CompressSection (
1208 if (EFI_ERROR (Status
)) {
1214 Size
+= ReturnValue
;
1216 } else if (_strcmpi (Buffer
, "Tool") == 0) {
1218 ZeroMem (ToolName
, _MAX_PATH
);
1219 ZeroMem (ToolArgumentsArray
, sizeof (CHAR8
*) * MAX_ARRAY_SIZE
);
1220 ZeroMem (&SignGuid
, sizeof (EFI_GUID
));
1223 // handle signing Tool
1225 while (Buffer
[0] != '(') {
1226 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1227 CheckSlash (Buffer
, Package
, &LineNumber
);
1231 if (_strcmpi (Buffer
, "(") == 0) {
1232 if (GetNextLine (Buffer
, Package
, &LineNumber
) != -1) {
1233 CheckSlash (Buffer
, Package
, &LineNumber
);
1237 StripParens (Buffer
);
1238 strcpy (ToolName
, Buffer
);
1239 ToolArgumentsArray
[0] = ToolName
;
1244 if (GetToolArguments (
1250 &GuidedSectionAttributes
1256 // if the tool need input file,
1257 // dump the file buffer to the specified input file.
1259 if (InputFileName
!= NULL
) {
1260 InputFile
= fopen (InputFileName
, "wb");
1261 if (InputFile
== NULL
) {
1262 Error (NULL
, 0, 0, InputFileName
, "failed to open output file for writing");
1267 fwrite (FileBuffer
, sizeof (UINT8
), Size
, InputFile
);
1270 free (InputFileName
);
1271 InputFileName
= NULL
;
1274 // dispatch signing tool
1276 returnint
= _spawnv (_P_WAIT
, ToolName
, ToolArgumentsArray
);
1277 if (returnint
!= 0) {
1278 Error (NULL
, 0, 0, ToolName
, "external tool failed");
1283 // if the tool has output file,
1284 // dump the output file to the file buffer
1286 if (OutputFileName
!= NULL
) {
1288 OutputFile
= fopen (OutputFileName
, "rb");
1289 if (OutputFile
== NULL
) {
1290 Error (NULL
, 0, 0, OutputFileName
, "failed to open output file for writing");
1295 TargetFileBuffer
= &FileBuffer
[Size
];
1296 SourceDataSize
= Size
;
1298 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1299 while (!feof (OutputFile
)) {
1300 FileBuffer
[Size
++] = Temp
;
1301 fread (&Temp
, sizeof (UINT8
), 1, OutputFile
);
1304 while ((Size
& 0x03) != 0) {
1305 FileBuffer
[Size
] = 0;
1309 SourceDataSize
= Size
- SourceDataSize
;
1311 fclose (OutputFile
);
1313 free (OutputFileName
);
1314 OutputFileName
= NULL
;
1316 if (CompareGuid (&SignGuid
, &mZeroGuid
) != 0) {
1317 ReturnValue
= SourceDataSize
;
1318 Status
= GenSimpleGuidSection (
1323 GuidedSectionAttributes
1325 if (EFI_ERROR (Status
)) {
1334 } else if (Buffer
[0] != '}') {
1336 // if we are here, we should see either a file name,
1342 // Prepend the build directory to the file name if the
1343 // file name does not already contain a full path.
1345 if (!isalpha (Buffer
[0]) || (Buffer
[1] != ':')) {
1346 sprintf (FileName
, "%s\\", BuildDirectory
);
1349 while (Buffer
[Index3
] != '\n') {
1350 if (Buffer
[Index3
] == 0) {
1353 Index2
= strlen (FileName
);
1354 FileName
[Index2
++] = Buffer
[Index3
++];
1355 FileName
[Index2
] = 0;
1359 InFile
= fopen (FileName
, "rb");
1360 if (InFile
== NULL
) {
1361 Error (NULL
, 0, 0, FileName
, "failed to open file for reading");
1367 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1368 while (!feof (InFile
)) {
1369 FileBuffer
[Size
++] = ByteBuffer
;
1370 fread (&ByteBuffer
, sizeof (UINT8
), 1, InFile
);
1377 // Adjust the TE Section for IPF so that the function entries are 16-byte aligned.
1379 if (Size
- OldSize
>= sizeof (EFI_COMMON_SECTION_HEADER
) + sizeof (EFI_TE_IMAGE_HEADER
) &&
1380 ((EFI_COMMON_SECTION_HEADER
*) &FileBuffer
[OldSize
])->Type
== EFI_SECTION_TE
&&
1381 ((EFI_TE_IMAGE_HEADER
*) &FileBuffer
[OldSize
+ 4])->Machine
== EFI_IMAGE_MACHINE_IA64
) {
1382 TeStrippedSize
= ((EFI_TE_IMAGE_HEADER
*) &FileBuffer
[OldSize
+ 4])->StrippedSize
;
1383 Adjust
= TeStrippedSize
- (OldSize
+ sizeof (EFI_COMMON_SECTION_HEADER
) + sizeof (EFI_TE_IMAGE_HEADER
));
1386 memmove (&FileBuffer
[OldSize
+ Adjust
], &FileBuffer
[OldSize
], Size
- OldSize
);
1388 // Pad with RAW Section type
1390 *(UINT32
*)&FileBuffer
[OldSize
] = 0x19000000 | Adjust
;
1393 // Make sure the Data alignment in FFS header is no less than 1 (16-byte aligned)
1395 MinFfsDataAlignOverride
= 1;
1400 // Make sure section ends on a DWORD boundary
1402 while ((Size
& 0x03) != 0) {
1403 FileBuffer
[Size
] = 0;
1411 for (Index3
= 1; Index3
< MAX_ARRAY_SIZE
; Index3
++) {
1412 if (ToolArgumentsArray
[Index3
] == NULL
) {
1416 free (ToolArgumentsArray
[Index3
]);
1434 Routine Description:
1436 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
1437 unrecognized file type was specified.
1441 String - File type string
1449 if (_strcmpi (String
, "EFI_FV_FILETYPE_RAW") == 0) {
1450 return EFI_FV_FILETYPE_RAW
;
1453 if (_strcmpi (String
, "EFI_FV_FILETYPE_FREEFORM") == 0) {
1454 return EFI_FV_FILETYPE_FREEFORM
;
1457 if (_strcmpi (String
, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) {
1458 return EFI_FV_FILETYPE_SECURITY_CORE
;
1461 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEI_CORE") == 0) {
1462 return EFI_FV_FILETYPE_PEI_CORE
;
1465 if (_strcmpi (String
, "EFI_FV_FILETYPE_DXE_CORE") == 0) {
1466 return EFI_FV_FILETYPE_DXE_CORE
;
1469 if (_strcmpi (String
, "EFI_FV_FILETYPE_PEIM") == 0) {
1470 return EFI_FV_FILETYPE_PEIM
;
1473 if (_strcmpi (String
, "EFI_FV_FILETYPE_DRIVER") == 0) {
1474 return EFI_FV_FILETYPE_DRIVER
;
1477 if (_strcmpi (String
, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) {
1478 return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
;
1481 if (_strcmpi (String
, "EFI_FV_FILETYPE_APPLICATION") == 0) {
1482 return EFI_FV_FILETYPE_APPLICATION
;
1485 if (_strcmpi (String
, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) {
1486 return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
;
1489 return EFI_FV_FILETYPE_ALL
;
1495 IN UINT8
*FileBuffer
,
1500 Routine Description:
1501 Adjusts file size to insure sectioned file is exactly the right length such
1502 that it ends on exactly the last byte of the last section. ProcessScript()
1503 may have padded beyond the end of the last section out to a 4 byte boundary.
1504 This padding is stripped.
1507 FileBuffer - Data Buffer - contains a section stream
1508 FileSize - Size of FileBuffer as returned from ProcessScript()
1511 Corrected size of file.
1516 UINT32 CurrentLength
;
1517 UINT32 SectionLength
;
1518 UINT32 SectionStreamLength
;
1519 EFI_COMMON_SECTION_HEADER
*SectionHeader
;
1520 EFI_COMMON_SECTION_HEADER
*NextSectionHeader
;
1524 SectionStreamLength
= FileSize
;
1526 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) FileBuffer
;
1528 while (TotalLength
< SectionStreamLength
) {
1529 SectionLength
= *((UINT32
*) SectionHeader
->Size
) & 0x00ffffff;
1530 TotalLength
+= SectionLength
;
1532 if (TotalLength
== SectionStreamLength
) {
1536 // Move to the next byte following the section...
1538 SectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ SectionLength
);
1539 CurrentLength
= (UINTN
) SectionHeader
- (UINTN
) FileBuffer
;
1542 // Figure out where the next section begins
1544 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINT8
*) SectionHeader
+ 3);
1545 NextSectionHeader
= (EFI_COMMON_SECTION_HEADER
*) ((UINTN
) NextSectionHeader
&~ (UINTN
) 3);
1546 TotalLength
+= (UINTN
) NextSectionHeader
- (UINTN
) SectionHeader
;
1547 SectionHeader
= NextSectionHeader
;
1550 return CurrentLength
;
1558 BOOLEAN ForceUncompress
1562 Routine Description:
1568 argc - Number of command line parameters.
1569 argv - Array of pointers to command line parameter strings.
1570 ForceUncompress - If TRUE, force to do not compress the sections even if compression
1571 is specified in the script. Otherwise, FALSE.
1574 STATUS_SUCCESS - Function exits successfully.
1575 STATUS_ERROR - Some error occurred during execution.
1579 FILE *PrimaryPackage
;
1580 FILE *OverridePackage
;
1582 CHAR8 BaseName
[_MAX_PATH
];
1584 CHAR8 GuidString
[_MAX_PATH
];
1585 EFI_FFS_FILE_HEADER FileHeader
;
1586 CHAR8 FileType
[_MAX_PATH
];
1587 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
1588 EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined
;
1589 UINT64 FfsAlignment
;
1590 UINT32 FfsAlignment32
;
1591 CHAR8 InputString
[_MAX_PATH
];
1592 BOOLEAN ImageScriptInOveride
;
1597 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1598 EFI_FFS_FILE_TAIL TailValue
;
1603 FfsAttribDefined
= 0;
1606 PrimaryPackage
= NULL
;
1608 OverridePackage
= NULL
;
1611 strcpy (GuidString
, "00000000-0000-0000-0000-000000000000");
1612 Status
= StringToGuid (GuidString
, &FfsGuid
);
1614 Error (NULL
, 0, 0, GuidString
, "error parsing GUID string");
1615 return STATUS_ERROR
;
1619 ImageScriptInOveride
= FALSE
;
1621 // Initialize the simple file parsing routines. Then open
1622 // the primary package file for parsing.
1625 if (SFPOpenFile (mGlobals
.PrimaryPackagePath
) != STATUS_SUCCESS
) {
1626 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
1630 // First token in the file must be "PACKAGE.INF"
1632 if (!SFPIsToken ("PACKAGE.INF")) {
1633 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL
);
1637 // Find the [.] section
1639 if (!SFPSkipToToken ("[.]")) {
1640 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "could not locate [.] section in package file", NULL
);
1644 // Start parsing the data. The algorithm is essentially the same for each keyword:
1645 // 1. Identify the keyword
1646 // 2. Verify that the keyword/value pair has not already been defined
1647 // 3. Set some flag indicating that the keyword/value pair has been defined
1648 // 4. Skip over the "="
1649 // 5. Get the value, which may be a number, TRUE, FALSE, or a string.
1652 if (SFPIsToken ("BASE_NAME")) {
1654 // Found BASE_NAME, format:
1655 // BASE_NAME = MyBaseName
1657 if (BaseName
[0] != 0) {
1658 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL
);
1662 if (!SFPIsToken ("=")) {
1663 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1667 if (!SFPGetNextToken (BaseName
, sizeof (BaseName
))) {
1668 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid base name", NULL
);
1671 } else if (SFPIsToken ("IMAGE_SCRIPT")) {
1673 // Found IMAGE_SCRIPT. Break out and process below.
1676 } else if (SFPIsToken ("FFS_FILEGUID")) {
1678 // found FILEGUID, format:
1679 // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A
1681 if (GuidString
[0] != 0) {
1682 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL
);
1686 if (!SFPIsToken ("=")) {
1687 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1691 if (SFPGetGuidToken (GuidString
, sizeof (GuidString
)) != TRUE
) {
1692 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected file GUID", NULL
);
1696 Status
= StringToGuid (GuidString
, &FfsGuid
);
1698 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid file GUID", NULL
);
1701 } else if (SFPIsToken ("FFS_FILETYPE")) {
1703 // ***********************************************************************
1705 // Found FFS_FILETYPE, format:
1706 // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION
1708 if (FileType
[0] != 0) {
1709 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL
);
1713 if (!SFPIsToken ("=")) {
1714 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1718 if (!SFPGetNextToken (FileType
, sizeof (FileType
))) {
1719 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL
);
1723 #if (PI_SPECIFICATION_VERSION < 0x00010000)
1724 else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) {
1726 // ***********************************************************************
1728 // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE
1729 // Spec says the bit is for future expansion, and must be false.
1731 if (FfsAttribDefined
& FFS_ATTRIB_HEADER_EXTENSION
) {
1733 mGlobals
.PrimaryPackagePath
,
1734 SFPGetLineNumber (),
1736 "FFS_ATTRIB_HEADER_EXTENSION previously defined",
1742 FfsAttribDefined
|= FFS_ATTRIB_HEADER_EXTENSION
;
1743 if (!SFPIsToken ("=")) {
1744 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1748 if (SFPIsToken ("TRUE")) {
1750 mGlobals
.PrimaryPackagePath
,
1751 SFPGetLineNumber (),
1753 "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported",
1757 } else if (SFPIsToken ("FALSE")) {
1762 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL
);
1767 else if (SFPIsToken ("FFS_ATTRIB_FIXED")) {
1769 // ***********************************************************************
1771 // Found: FFS_ATTRIB_FIXED = TRUE | FALSE
1773 if (FfsAttribDefined
& FFS_ATTRIB_FIXED
) {
1774 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_FIXED previously defined", NULL
);
1778 FfsAttribDefined
|= FFS_ATTRIB_FIXED
;
1779 if (!SFPIsToken ("=")) {
1780 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1784 if (SFPIsToken ("TRUE")) {
1785 FfsAttrib
|= FFS_ATTRIB_FIXED
;
1786 } else if (SFPIsToken ("FALSE")) {
1791 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1796 else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) {
1798 // ***********************************************************************
1800 // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE
1802 if (FfsAttribDefined
& FFS_ATTRIB_TAIL_PRESENT
) {
1803 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL
);
1807 FfsAttribDefined
|= FFS_ATTRIB_TAIL_PRESENT
;
1808 if (!SFPIsToken ("=")) {
1809 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1813 if (SFPIsToken ("TRUE")) {
1814 FfsAttrib
|= FFS_ATTRIB_TAIL_PRESENT
;
1815 } else if (SFPIsToken ("FALSE")) {
1820 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1823 } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) {
1825 // ***********************************************************************
1827 // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE
1829 if (FfsAttribDefined
& FFS_ATTRIB_RECOVERY
) {
1830 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL
);
1834 FfsAttribDefined
|= FFS_ATTRIB_RECOVERY
;
1835 if (!SFPIsToken ("=")) {
1836 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1840 if (SFPIsToken ("TRUE")) {
1841 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
1842 } else if (SFPIsToken ("FALSE")) {
1847 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1850 } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) {
1852 // ***********************************************************************
1854 // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE
1856 if (FfsAttribDefined
& FFS_ATTRIB_CHECKSUM
) {
1857 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL
);
1861 FfsAttribDefined
|= FFS_ATTRIB_CHECKSUM
;
1862 if (!SFPIsToken ("=")) {
1863 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1867 if (SFPIsToken ("TRUE")) {
1868 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
1869 } else if (SFPIsToken ("FALSE")) {
1874 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL
);
1877 } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) {
1879 // ***********************************************************************
1881 // Found FFS_ALIGNMENT, formats:
1882 // FFS_ALIGNMENT = 0-7
1883 // FFS_ATTRIB_DATA_ALIGNMENT = 0-7
1885 if (FfsAttribDefined
& FFS_ATTRIB_DATA_ALIGNMENT
) {
1887 mGlobals
.PrimaryPackagePath
,
1888 SFPGetLineNumber (),
1890 "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined",
1896 FfsAttribDefined
|= FFS_ATTRIB_DATA_ALIGNMENT
;
1897 if (!SFPIsToken ("=")) {
1898 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected '='", NULL
);
1902 if (!SFPGetNumber (&FfsAlignment32
)) {
1903 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL
);
1907 if (FfsAlignment32
> 7) {
1908 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL
);
1912 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment32
) << 3);
1914 SFPGetNextToken (InputString
, sizeof (InputString
));
1915 Error (mGlobals
.PrimaryPackagePath
, SFPGetLineNumber (), 0, InputString
, "unrecognized/unexpected token");
1920 // Close the primary package file
1924 // TODO: replace code below with basically a copy of the code above. Don't
1925 // forget to reset the FfsAttribDefined variable first. Also, you'll need
1926 // to somehow keep track of whether or not the basename is defined multiple
1927 // times in the override package. Ditto on the file GUID.
1929 if (mGlobals
.OverridePackagePath
[0] != 0) {
1930 OverridePackage
= fopen (mGlobals
.OverridePackagePath
, "r");
1932 // NOTE: For package override to work correctly, the code below must be modified to
1933 // SET or CLEAR bits properly. For example, if the primary package set
1934 // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then
1935 // we'd need to clear the bit below. Since this is not happening, I'm guessing that
1936 // the override functionality is not being used, so should be made obsolete. If I'm
1937 // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is
1938 // used, and we'll address it then. 4/10/2003
1940 Error (__FILE__
, __LINE__
, 0, "package override functionality is not implemented correctly", NULL
);
1943 OverridePackage
= NULL
;
1946 #ifdef OVERRIDE_SUPPORTED
1947 if (OverridePackage
!= NULL
) {
1949 // Parse override package file
1951 fscanf (OverridePackage
, "%s", &InputString
);
1952 if (_strcmpi (InputString
, "PACKAGE.INF") != 0) {
1953 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid package file", "expected 'PACKAGE.INF'");
1957 // Match [dir] to Build Directory
1959 if (FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
) != 0) {
1960 Error (mGlobals
.OverridePackagePath
, 1, 0, mGlobals
.BuildDirectory
, "section not found in package file");
1965 while ((InputString
[0] != '[') && (!feof (OverridePackage
))) {
1966 if (GetNextLine (InputString
, OverridePackage
, &LineNumber
) != -1) {
1967 if (InputString
[0] != '[') {
1969 if (_strcmpi (InputString
, "BASE_NAME") == 0) {
1971 // found BASE_NAME, next is = and string.
1973 fscanf (OverridePackage
, "%s", &InputString
);
1974 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1975 if (strlen (InputString
) == 1) {
1979 fscanf (OverridePackage
, "%s", &InputString
);
1980 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1981 strcpy (BaseName
, InputString
);
1983 BreakString (InputString
, InputString
, 1);
1984 strcpy (BaseName
, InputString
);
1986 } else if (_strcmpi (InputString
, "IMAGE_SCRIPT") == 0) {
1988 // found IMAGE_SCRIPT, come back later to process it
1990 ImageScriptInOveride
= TRUE
;
1991 fscanf (OverridePackage
, "%s", &InputString
);
1992 } else if (_strcmpi (InputString
, "FFS_FILEGUID") == 0) {
1994 // found FILEGUID, next is = and string.
1996 fscanf (OverridePackage
, "%s", &InputString
);
1997 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
1998 if (strlen (InputString
) == 1) {
2002 fscanf (OverridePackage
, "%s", &InputString
);
2003 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2004 Status
= StringToGuid (InputString
, &FfsGuid
);
2006 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2010 BreakString (InputString
, InputString
, 1);
2011 Status
= StringToGuid (InputString
, &FfsGuid
);
2013 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "bad FFS_FILEGUID format");
2017 } else if (_strcmpi (InputString
, "FFS_FILETYPE") == 0) {
2019 // found FILETYPE, next is = and string.
2021 fscanf (OverridePackage
, "%s", &InputString
);
2022 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2023 if (strlen (InputString
) == 1) {
2027 fscanf (OverridePackage
, "%s", &InputString
);
2028 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2029 strcpy (FileType
, InputString
);
2031 BreakString (InputString
, InputString
, 1);
2032 strcpy (FileType
, InputString
);
2035 } else if (_strcmpi (InputString
, "FFS_ATTRIB_RECOVERY") == 0) {
2037 // found FFS_ATTRIB_RECOVERY, next is = and string.
2039 fscanf (OverridePackage
, "%s", &InputString
);
2040 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2041 if (strlen (InputString
) == 1) {
2045 fscanf (OverridePackage
, "%s", &InputString
);
2046 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2047 if (_strcmpi (InputString
, "TRUE") == 0) {
2048 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2051 BreakString (InputString
, InputString
, 1);
2052 if (_strcmpi (InputString
, "TRUE") == 0) {
2053 FfsAttrib
|= FFS_ATTRIB_RECOVERY
;
2056 } else if (_strcmpi (InputString
, "FFS_ATTRIB_CHECKSUM") == 0) {
2058 // found FFS_ATTRIB_CHECKSUM, next is = and string.
2060 fscanf (OverridePackage
, "%s", &InputString
);
2061 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2062 if (strlen (InputString
) == 1) {
2066 fscanf (OverridePackage
, "%s", &InputString
);
2067 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2068 if (_strcmpi (InputString
, "TRUE") == 0) {
2069 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2072 BreakString (InputString
, InputString
, 1);
2073 if (_strcmpi (InputString
, "TRUE") == 0) {
2074 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
2077 } else if (_strcmpi (InputString
, "FFS_ALIGNMENT") == 0) {
2079 // found FFS_ALIGNMENT, next is = and string.
2081 fscanf (OverridePackage
, "%s", &InputString
);
2082 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2083 if (strlen (InputString
) == 1) {
2087 fscanf (OverridePackage
, "%s", &InputString
);
2088 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2090 BreakString (InputString
, InputString
, 1);
2093 AsciiStringToUint64 (InputString
, FALSE
, &FfsAlignment
);
2094 if (FfsAlignment
> 7) {
2095 Error (mGlobals
.OverridePackagePath
, 1, 0, InputString
, "invalid FFS_ALIGNMENT value");
2099 FfsAttrib
|= (((EFI_FFS_FILE_ATTRIBUTES
) FfsAlignment
) << 3);
2100 } else if (strchr (InputString
, '=') != NULL
) {
2101 BreakString (InputString
, String
, 1);
2102 fseek (OverridePackage
, (-1 * (strlen (String
) + 1)), SEEK_CUR
);
2103 BreakString (InputString
, InputString
, 0);
2110 #endif // #ifdef OVERRIDE_SUPPORTED
2112 // Require that they specified a file GUID at least, since that's how we're
2115 if (GuidString
[0] == 0) {
2116 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "FFS_FILEGUID must be specified", NULL
);
2117 return STATUS_ERROR
;
2120 // Build Header and process image script
2122 FileBuffer
= (UINT8
*) malloc ((1024 * 1024 * 16) * sizeof (UINT8
));
2123 if (FileBuffer
== NULL
) {
2124 Error (__FILE__
, __LINE__
, 0, "memory allocation failed", NULL
);
2129 if (ImageScriptInOveride
) {
2130 #ifdef OVERRIDE_SUPPORTED
2131 rewind (OverridePackage
);
2133 FindSectionInPackage (mGlobals
.BuildDirectory
, OverridePackage
, &LineNumber
);
2134 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2135 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2136 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2137 if (strchr (InputString
, '=') != NULL
) {
2138 BreakString (InputString
, InputString
, 0);
2142 while (InputString
[0] != '{') {
2143 GetNextLine (InputString
, OverridePackage
, &LineNumber
);
2144 CheckSlash (InputString
, OverridePackage
, &LineNumber
);
2147 // Found start of image script, process it
2149 FileSize
+= ProcessScript (FileBuffer
, OverridePackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2150 if (FileSize
== -1) {
2151 Error (NULL
, 0, 0, "failed to process script", NULL
);
2155 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2156 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2159 if (BaseName
[0] == '\"') {
2160 StripQuotes (BaseName
);
2163 if (BaseName
[0] != 0) {
2164 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2166 strcpy (InputString
, GuidString
);
2169 switch (StringToType (FileType
)) {
2171 case EFI_FV_FILETYPE_SECURITY_CORE
:
2172 strcat (InputString
, ".SEC");
2175 case EFI_FV_FILETYPE_PEIM
:
2176 case EFI_FV_FILETYPE_PEI_CORE
:
2177 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2178 strcat (InputString
, ".PEI");
2181 case EFI_FV_FILETYPE_DRIVER
:
2182 case EFI_FV_FILETYPE_DXE_CORE
:
2183 strcat (InputString
, ".DXE");
2186 case EFI_FV_FILETYPE_APPLICATION
:
2187 strcat (InputString
, ".APP");
2190 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2191 strcat (InputString
, ".FVI");
2194 case EFI_FV_FILETYPE_RAW
:
2195 strcat (InputString
, ".RAW");
2198 case EFI_FV_FILETYPE_ALL
:
2199 Error (mGlobals
.OverridePackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2203 strcat (InputString
, ".FFS");
2207 if (ForceUncompress
) {
2208 strcat (InputString
, ".ORG");
2211 Out
= fopen (InputString
, "wb");
2213 Error (NULL
, 0, 0, InputString
, "could not open output file for writing");
2217 // create ffs header
2219 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2220 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2221 FileHeader
.Type
= StringToType (FileType
);
2222 if (((FfsAttrib
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3) < MinFfsDataAlignOverride
) {
2223 FfsAttrib
= (FfsAttrib
& ~FFS_ATTRIB_DATA_ALIGNMENT
) | (MinFfsDataAlignOverride
<< 3);
2225 FileHeader
.Attributes
= FfsAttrib
;
2227 // Now FileSize includes the EFI_FFS_FILE_HEADER
2229 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2230 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2231 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2232 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2234 // Fill in checksums and state, these must be zero for checksumming
2236 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2237 // FileHeader.IntegrityCheck.Checksum.File = 0;
2238 // FileHeader.State = 0;
2240 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2241 (UINT8
*) &FileHeader
,
2242 sizeof (EFI_FFS_FILE_HEADER
)
2244 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2245 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 ((UINT8
*) &FileHeader
, FileSize
);
2247 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2250 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2254 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2255 Error (NULL
, 0, 0, "failed to write file header to output file", NULL
);
2261 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2262 Error (NULL
, 0, 0, "failed to write all bytes to output file", NULL
);
2268 #endif // #ifdef OVERRIDE_SUPPORTED
2271 // Open primary package file and process the IMAGE_SCRIPT section
2273 PrimaryPackage
= fopen (mGlobals
.PrimaryPackagePath
, "r");
2274 if (PrimaryPackage
== NULL
) {
2275 Error (NULL
, 0, 0, mGlobals
.PrimaryPackagePath
, "unable to open primary package file");
2280 FindSectionInPackage (".", PrimaryPackage
, &LineNumber
);
2281 while (_strcmpi (InputString
, "IMAGE_SCRIPT") != 0) {
2282 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2283 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2284 if (strchr (InputString
, '=') != NULL
) {
2285 BreakString (InputString
, InputString
, 0);
2289 while (InputString
[0] != '{') {
2290 GetNextLine (InputString
, PrimaryPackage
, &LineNumber
);
2291 CheckSlash (InputString
, PrimaryPackage
, &LineNumber
);
2294 // Found start of image script, process it
2296 FileSize
+= ProcessScript (FileBuffer
, PrimaryPackage
, mGlobals
.BuildDirectory
, ForceUncompress
);
2297 if (FileSize
== -1) {
2298 Error (NULL
, 0, 0, "failed to process script", NULL
);
2302 if (StringToType (FileType
) != EFI_FV_FILETYPE_RAW
) {
2303 FileSize
= AdjustFileSize (FileBuffer
, FileSize
);
2306 if (BaseName
[0] == '\"') {
2307 StripQuotes (BaseName
);
2310 if (BaseName
[0] != 0) {
2311 sprintf (InputString
, "%s-%s", GuidString
, BaseName
);
2313 strcpy (InputString
, GuidString
);
2316 switch (StringToType (FileType
)) {
2318 case EFI_FV_FILETYPE_SECURITY_CORE
:
2319 strcat (InputString
, ".SEC");
2322 case EFI_FV_FILETYPE_PEIM
:
2323 case EFI_FV_FILETYPE_PEI_CORE
:
2324 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
:
2325 strcat (InputString
, ".PEI");
2328 case EFI_FV_FILETYPE_DRIVER
:
2329 case EFI_FV_FILETYPE_DXE_CORE
:
2330 strcat (InputString
, ".DXE");
2333 case EFI_FV_FILETYPE_APPLICATION
:
2334 strcat (InputString
, ".APP");
2337 case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
:
2338 strcat (InputString
, ".FVI");
2341 case EFI_FV_FILETYPE_RAW
:
2342 strcat (InputString
, ".RAW");
2345 case EFI_FV_FILETYPE_ALL
:
2346 Error (mGlobals
.PrimaryPackagePath
, 1, 0, "invalid FFS file type for this utility", NULL
);
2350 strcat (InputString
, ".FFS");
2354 if (ForceUncompress
) {
2355 strcat (InputString
, ".ORG");
2358 Out
= fopen (InputString
, "wb");
2360 Error (NULL
, 0, 0, InputString
, "failed to open output file for writing");
2364 // Initialize the FFS file header
2366 memset (&FileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
2367 memcpy (&FileHeader
.Name
, &FfsGuid
, sizeof (EFI_GUID
));
2368 FileHeader
.Type
= StringToType (FileType
);
2369 if (((FfsAttrib
& FFS_ATTRIB_DATA_ALIGNMENT
) >> 3) < MinFfsDataAlignOverride
) {
2370 FfsAttrib
= (FfsAttrib
& ~FFS_ATTRIB_DATA_ALIGNMENT
) | (MinFfsDataAlignOverride
<< 3);
2372 FileHeader
.Attributes
= FfsAttrib
;
2374 // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER
2376 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
2378 // If using a tail, then it adds two bytes
2380 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2382 // Tail is not allowed for pad and 0-length files
2384 if ((FileHeader
.Type
== EFI_FV_FILETYPE_FFS_PAD
) || (FileSize
== sizeof (EFI_FFS_FILE_HEADER
))) {
2386 mGlobals
.PrimaryPackagePath
,
2389 "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files",
2395 FileSize
+= sizeof (EFI_FFS_FILE_TAIL
);
2398 FileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
2399 FileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
2400 FileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
2402 // Fill in checksums and state, they must be 0 for checksumming.
2404 // FileHeader.IntegrityCheck.Checksum.Header = 0;
2405 // FileHeader.IntegrityCheck.Checksum.File = 0;
2406 // FileHeader.State = 0;
2408 FileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
2409 (UINT8
*) &FileHeader
,
2410 sizeof (EFI_FFS_FILE_HEADER
)
2412 if (FileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
2414 // Cheating here. Since the header checksums, just calculate the checksum of the body.
2415 // Checksum does not include the tail
2417 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2418 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2420 FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
)
2423 FileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
2425 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
2429 FileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
2432 // Set the state now. Spec says the checksum assumes the state is 0
2434 FileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
2436 #if (PI_SPECIFICATION_VERSION < 0x00010000)
2439 // If there is a tail, then set it
2441 if (FileHeader
.Attributes
& FFS_ATTRIB_TAIL_PRESENT
) {
2442 TailValue
= FileHeader
.IntegrityCheck
.TailReference
;
2443 TailValue
= (UINT16
) (~TailValue
);
2445 (UINT8
*) FileBuffer
+ FileSize
- sizeof (EFI_FFS_FILE_HEADER
) - sizeof (EFI_FFS_FILE_TAIL
),
2452 // Write the FFS file header
2454 if (fwrite (&FileHeader
, sizeof (FileHeader
), 1, Out
) != 1) {
2455 Error (NULL
, 0, 0, "failed to write file header contents", NULL
);
2461 if (fwrite (FileBuffer
, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), 1, Out
) != 1) {
2462 Error (NULL
, 0, 0, "failed to write file contents", NULL
);
2473 if (PrimaryPackage
!= NULL
) {
2474 fclose (PrimaryPackage
);
2477 if (FileBuffer
!= NULL
) {
2481 if (OverridePackage
!= NULL
) {
2482 fclose (OverridePackage
);
2485 return GetUtilityStatus ();
2495 Routine Description:
2501 argc - Number of command line parameters.
2502 argv - Array of pointers to parameter strings.
2505 STATUS_SUCCESS - Utility exits successfully.
2506 STATUS_ERROR - Some error occurred during execution.
2512 // Set the name of our utility for error reporting purposes.
2514 SetUtilityName (UTILITY_NAME
);
2515 Status
= ProcessCommandLineArgs (argc
, argv
);
2517 if (Status
!= STATUS_SUCCESS
) {
2521 Status
= MainEntry (argc
, argv
, TRUE
);
2522 if (Status
== STATUS_SUCCESS
) {
2523 MainEntry (argc
, argv
, FALSE
);
2526 // If any errors were reported via the standard error reporting
2527 // routines, then the status has been saved. Get the value and
2528 // return it to the caller.
2530 return GetUtilityStatus ();
2535 ProcessCommandLineArgs (
2541 Routine Description:
2542 Process the command line arguments.
2545 Argc - as passed in to main()
2546 Argv - as passed in to main()
2549 STATUS_SUCCESS - arguments all ok
2550 STATUS_ERROR - problem with args, so caller should exit
2555 UINT8
*OriginalPrimaryPackagePath
;
2556 UINT8
*OriginalOverridePackagePath
;
2560 // If no args, then print usage instructions and return an error
2564 return STATUS_ERROR
;
2567 OriginalPrimaryPackagePath
= NULL
;
2568 OriginalOverridePackagePath
= NULL
;
2569 memset (&mGlobals
, 0, sizeof (mGlobals
));
2573 if (_strcmpi (Argv
[0], "-b") == 0) {
2575 // OPTION: -b BuildDirectory
2576 // Make sure there is another argument, then save it to our globals.
2579 Error (NULL
, 0, 0, "-b option requires the build directory name", NULL
);
2580 return STATUS_ERROR
;
2583 if (mGlobals
.BuildDirectory
[0]) {
2584 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2585 return STATUS_ERROR
;
2588 strcpy (mGlobals
.BuildDirectory
, Argv
[1]);
2591 } else if (_strcmpi (Argv
[0], "-p1") == 0) {
2593 // OPTION: -p1 PrimaryPackageFile
2594 // Make sure there is another argument, then save it to our globals.
2597 Error (NULL
, 0, 0, Argv
[0], "option requires the primary package file name");
2598 return STATUS_ERROR
;
2601 if (OriginalPrimaryPackagePath
) {
2602 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2603 return STATUS_ERROR
;
2606 OriginalPrimaryPackagePath
= Argv
[1];
2609 } else if (_strcmpi (Argv
[0], "-p2") == 0) {
2611 // OPTION: -p2 OverridePackageFile
2612 // Make sure there is another argument, then save it to our globals.
2615 Error (NULL
, 0, 0, Argv
[0], "option requires the override package file name");
2616 return STATUS_ERROR
;
2619 if (OriginalOverridePackagePath
) {
2620 Error (NULL
, 0, 0, Argv
[0], "option can only be specified once");
2621 return STATUS_ERROR
;
2624 OriginalOverridePackagePath
= Argv
[1];
2627 } else if (_strcmpi (Argv
[0], "-v") == 0) {
2629 // OPTION: -v verbose
2631 mGlobals
.Verbose
= TRUE
;
2632 } else if (_strcmpi (Argv
[0], "-d") == 0) {
2634 // OPTION: -d name=value
2635 // Make sure there is another argument, then add it to our macro list.
2638 Error (NULL
, 0, 0, Argv
[0], "option requires the macro definition");
2639 return STATUS_ERROR
;
2645 } else if (_strcmpi (Argv
[0], "-h") == 0) {
2650 return STATUS_ERROR
;
2651 } else if (_strcmpi (Argv
[0], "-?") == 0) {
2656 return STATUS_ERROR
;
2658 Error (NULL
, 0, 0, Argv
[0], "unrecognized option");
2660 return STATUS_ERROR
;
2668 // Must have at least specified the build directory
2670 if (!mGlobals
.BuildDirectory
[0]) {
2671 Error (NULL
, 0, 0, "must specify build directory", NULL
);
2672 return STATUS_ERROR
;
2676 // Must have at least specified the package file name
2678 if (OriginalPrimaryPackagePath
== NULL
) {
2679 Error (NULL
, 0, 0, "must specify primary package file", NULL
);
2680 return STATUS_ERROR
;
2683 PackageName
= OriginalPrimaryPackagePath
+ strlen (OriginalPrimaryPackagePath
);
2684 while ((*PackageName
!= '\\') && (*PackageName
!= '/') &&
2685 (PackageName
!= OriginalPrimaryPackagePath
)) {
2689 // Skip the '\' or '/'
2691 if (PackageName
!= OriginalPrimaryPackagePath
) {
2694 sprintf (mGlobals
.PrimaryPackagePath
, "%s\\%s.new", mGlobals
.BuildDirectory
, PackageName
);
2695 Status
= ReplaceMacros (OriginalPrimaryPackagePath
, mGlobals
.PrimaryPackagePath
);
2696 if (Status
== STATUS_WARNING
) {
2698 // No macro replacement, use the previous package file
2700 strcpy (mGlobals
.PrimaryPackagePath
, OriginalPrimaryPackagePath
);
2701 } else if (Status
!= STATUS_SUCCESS
) {
2705 if (OriginalOverridePackagePath
!= NULL
) {
2706 PackageName
= OriginalOverridePackagePath
+ strlen (OriginalOverridePackagePath
);
2707 while ((*PackageName
!= '\\') && (*PackageName
!= '/') &&
2708 (PackageName
!= OriginalOverridePackagePath
)) {
2712 // Skip the '\' or '/'
2714 if (PackageName
!= OriginalOverridePackagePath
) {
2717 sprintf (mGlobals
.OverridePackagePath
, "%s\\%s.new", mGlobals
.BuildDirectory
, PackageName
);
2718 Status
= ReplaceMacros (OriginalOverridePackagePath
, mGlobals
.OverridePackagePath
);
2719 if (Status
== STATUS_WARNING
) {
2721 // No macro replacement, use the previous package file
2723 strcpy (mGlobals
.OverridePackagePath
, OriginalOverridePackagePath
);
2724 } else if (Status
!= STATUS_SUCCESS
) {
2729 return STATUS_SUCCESS
;
2739 Routine Description:
2741 Add or override a macro definition.
2745 MacroString - macro definition string: name=value
2758 // Seperate macro name and value by '\0'
2760 for (Value
= MacroString
; *Value
&& (*Value
!= '='); Value
++);
2762 if (*Value
== '=') {
2768 // We now have a macro name and value.
2769 // Look for an existing macro and overwrite it.
2771 Macro
= mGlobals
.MacroList
;
2773 if (_strcmpi (MacroString
, Macro
->Name
) == 0) {
2774 Macro
->Value
= Value
;
2778 Macro
= Macro
->Next
;
2782 // Does not exist, create a new one
2784 NewMacro
= (MACRO
*) malloc (sizeof (MACRO
));
2785 memset ((UINT8
*) NewMacro
, 0, sizeof (MACRO
));
2786 NewMacro
->Name
= MacroString
;
2787 NewMacro
->Value
= Value
;
2790 // Add it to the head of the list.
2792 NewMacro
->Next
= mGlobals
.MacroList
;
2793 mGlobals
.MacroList
= NewMacro
;
2805 Routine Description:
2811 MacroName - The name of macro
2815 Pointer to the value of the macro if found
2816 NULL if the macro is not found
2827 Macro
= mGlobals
.MacroList
;
2829 if (_strcmpi (MacroName
, Macro
->Name
) == 0) {
2830 return Macro
->Value
;
2832 Macro
= Macro
->Next
;
2836 // Try environment variable
2838 Value
= getenv (MacroName
);
2839 if (Value
== NULL
) {
2840 printf ("Environment variable %s not found!\n", MacroName
);
2851 Routine Description:
2853 Free the macro list.
2868 Macro
= mGlobals
.MacroList
;
2870 NextMacro
= Macro
->Next
;
2874 mGlobals
.MacroList
= NULL
;
2887 Routine Description:
2889 Replace all the macros in InputFile to create the OutputFile.
2893 InputFile - Input package file for macro replacement
2894 OutputFile - Output package file after macro replacement
2898 STATUS_SUCCESS - Output package file is created successfully after the macro replacement.
2899 STATUS_WARNING - Output package file is not created because of no macro replacement.
2900 STATUS_ERROR - Some error occurred during execution.
2913 // Get the file size, and then read the entire thing into memory.
2914 // Allocate extra space for a terminator character.
2916 if ((Fptr
= fopen (InputFile
, "r")) == NULL
) {
2917 Error (NULL
, 0, 0, InputFile
, "can't open input file");
2918 return STATUS_ERROR
;
2920 fseek (Fptr
, 0, SEEK_END
);
2921 FileSize
= ftell (Fptr
);
2922 fseek (Fptr
, 0, SEEK_SET
);
2923 FileBuffer
= malloc (FileSize
+ 1);
2924 if (FileBuffer
== NULL
) {
2926 Error (NULL
, 0, 0, InputFile
, "file buffer memory allocation failure");
2927 return STATUS_ERROR
;
2929 fread (FileBuffer
, FileSize
, 1, Fptr
);
2930 FileBuffer
[FileSize
] = '\0';
2934 // Walk the entire file, replacing $(MACRO_NAME).
2937 FromPtr
= FileBuffer
;
2938 SaveStart
= FromPtr
;
2940 if ((*FromPtr
== '$') && (*(FromPtr
+ 1) == '(')) {
2942 for (ToPtr
= FromPtr
; *ToPtr
&& (*ToPtr
!= ')'); ToPtr
++);
2945 // Find an $(MACRO_NAME), replace it
2948 Value
= GetMacroValue (FromPtr
);
2951 if ((Fptr
= fopen (OutputFile
, "w")) == NULL
) {
2953 Error (NULL
, 0, 0, OutputFile
, "can't open output file");
2954 return STATUS_ERROR
;
2957 if (Value
!= NULL
) {
2958 fprintf (Fptr
, "%s%s", SaveStart
, Value
);
2960 fprintf (Fptr
, "%s", SaveStart
);
2963 // Continue macro replacement for the remaining string line
2966 SaveStart
= FromPtr
;
2976 fprintf (Fptr
, "%s", SaveStart
);
2982 return STATUS_SUCCESS
;
2984 return STATUS_WARNING
;