2 Creates and EFILDR image.
3 This tool combines several PE Image files together using following format denoted as EBNF:
7 The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent.
9 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
10 This program and the accompanying materials
11 are licensed and made available under the terms and conditions of the BSD License
12 which accompanies this distribution. The full text of the license may be found at
13 http://opensource.org/licenses/bsd-license.php
15 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 #include "CommonLib.h"
26 #include "EfiUtilityMsgs.h"
28 #define MAX_PE_IMAGES 63
29 #define FILE_TYPE_FIXED_LOADER 0
30 #define FILE_TYPE_RELOCATABLE_PE_IMAGE 1
41 UINT32 HeaderCheckSum
;
43 UINT32 NumberOfImages
;
49 #define UTILITY_NAME "EfiLdrImage"
52 // Utility version information
54 #define UTILITY_MAJOR_VERSION 1
55 #define UTILITY_MINOR_VERSION 0
65 Displays the standard utility information to SDTOUT
77 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
86 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
87 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
88 printf ("Copyright (c) 1999-2016 Intel Corporation. All rights reserved.\n");
89 printf ("\n The EfiLdrImage tool is used to combine PE files into EFILDR image with Efi loader header.\n");
94 IN CONST CHAR8
* VerboseLevelString
,
95 IN CONST UINT64 Length
,
96 OUT UINT64
*ReturnValue
100 for (;i
< Length
; ++i
) {
101 if (VerboseLevelString
[i
] != 'v' && VerboseLevelString
[i
] != 'V') {
117 Write all the content of input file to output file.
120 in - input file pointer
121 out - output file pointer
124 UINT64 : file size of input file
127 UINT32 filesize
, offset
, length
;
128 CHAR8 Buffer
[8*1024];
130 fseek (in
, 0, SEEK_END
);
131 filesize
= ftell(in
);
133 fseek (in
, 0, SEEK_SET
);
136 while (offset
< filesize
) {
137 length
= sizeof(Buffer
);
138 if (filesize
-offset
< length
) {
139 length
= filesize
-offset
;
142 fread (Buffer
, length
, 1, in
);
143 fwrite (Buffer
, length
, 1, out
);
172 EFILDR_HEADER EfiLdrHeader
;
173 EFILDR_IMAGE EfiLdrImage
[MAX_PE_IMAGES
];
174 CHAR8
* OutputFileName
= NULL
;
175 CHAR8
* InputFileNames
[MAX_PE_IMAGES
+ 1];
176 UINT8 InputFileCount
= 0;
177 UINT64 DebugLevel
= 0;
178 UINT64 VerboseLevel
= 0;
179 EFI_STATUS Status
= EFI_SUCCESS
;
181 SetUtilityName (UTILITY_NAME
);
184 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
191 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
193 return STATUS_SUCCESS
;
196 if (stricmp (argv
[0], "--version") == 0) {
198 return STATUS_SUCCESS
;
203 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
204 OutputFileName
= argv
[1];
205 if (OutputFileName
== NULL
) {
206 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be null");
214 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
220 if ((strlen(argv
[0]) >= 2 && argv
[0][0] == '-' && (argv
[0][1] == 'v' || argv
[0][1] == 'V')) || (stricmp (argv
[0], "--verbose") == 0)) {
222 if (strlen(argv
[0]) > 2) {
223 Status
= CountVerboseLevel (&argv
[0][2], strlen(argv
[0]) - 2, &VerboseLevel
);
224 if (EFI_ERROR (Status
)) {
225 Error (NULL
, 0, 1003, "Invalid option value", argv
[0]);
235 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
236 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &DebugLevel
);
237 if (EFI_ERROR (Status
)) {
238 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
246 // Don't recognize the parameter, should be regarded as the input file name.
248 InputFileNames
[InputFileCount
] = argv
[0];
254 if (InputFileCount
== 0) {
255 Error (NULL
, 0, 1001, "Missing option", "No input file");
259 // Open output file for write
261 if (OutputFileName
== NULL
) {
262 Error (NULL
, 0, 1001, "Missing option", "No output file");
266 fpOut
= fopen (LongFilePath (OutputFileName
), "w+b");
268 Error (NULL
, 0, 0001, "Could not open output file", OutputFileName
);
272 memset (&EfiLdrHeader
, 0, sizeof (EfiLdrHeader
));
273 memset (&EfiLdrImage
, 0, sizeof (EFILDR_IMAGE
) * (InputFileCount
));
275 memcpy (&EfiLdrHeader
.Signature
, "EFIL", 4);
276 EfiLdrHeader
.FileLength
= sizeof(EFILDR_HEADER
) + sizeof(EFILDR_IMAGE
)*(InputFileCount
);
279 // Skip the file header first
281 fseek (fpOut
, EfiLdrHeader
.FileLength
, SEEK_SET
);
284 // copy all the input files to the output file
286 for(i
=0;i
<InputFileCount
;i
++) {
288 // Copy the content of PeImage file to output file
290 fpIn
= fopen (LongFilePath (InputFileNames
[i
]), "rb");
292 Error (NULL
, 0, 0001, "Could not open input file", InputFileNames
[i
]);
296 filesize
= FCopyFile (fpIn
, fpOut
);
300 // And in the same time update the EfiLdrHeader and EfiLdrImage array
302 EfiLdrImage
[i
].Offset
= EfiLdrHeader
.FileLength
;
303 EfiLdrImage
[i
].Length
= (UINT32
) filesize
;
304 strncpy ((CHAR8
*) EfiLdrImage
[i
].FileName
, InputFileNames
[i
], sizeof (EfiLdrImage
[i
].FileName
) - 1);
305 EfiLdrHeader
.FileLength
+= (UINT32
) filesize
;
306 EfiLdrHeader
.NumberOfImages
++;
310 // Write the image header to the output file finally
312 fseek (fpOut
, 0, SEEK_SET
);
313 fwrite (&EfiLdrHeader
, sizeof(EFILDR_HEADER
) , 1, fpOut
);
314 fwrite (&EfiLdrImage
, sizeof(EFILDR_IMAGE
)*(InputFileCount
), 1, fpOut
);
317 printf ("Created %s\n", OutputFileName
);