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
);
85 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
86 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
87 printf ("Copyright (c) 1999-2016 Intel Corporation. All rights reserved.\n");
88 printf ("\n The EfiLdrImage tool is used to combine PE files into EFILDR image with Efi loader header.\n");
93 IN CONST CHAR8
* VerboseLevelString
,
94 IN CONST UINT64 Length
,
95 OUT UINT64
*ReturnValue
99 for (;i
< Length
; ++i
) {
100 if (VerboseLevelString
[i
] != 'v' && VerboseLevelString
[i
] != 'V') {
116 Write all the content of input file to output file.
119 in - input file pointer
120 out - output file pointer
123 UINT64 : file size of input file
126 UINT32 filesize
, offset
, length
;
127 CHAR8 Buffer
[8*1024];
129 fseek (in
, 0, SEEK_END
);
130 filesize
= ftell(in
);
132 fseek (in
, 0, SEEK_SET
);
135 while (offset
< filesize
) {
136 length
= sizeof(Buffer
);
137 if (filesize
-offset
< length
) {
138 length
= filesize
-offset
;
141 fread (Buffer
, length
, 1, in
);
142 fwrite (Buffer
, length
, 1, out
);
171 EFILDR_HEADER EfiLdrHeader
;
172 EFILDR_IMAGE EfiLdrImage
[MAX_PE_IMAGES
];
173 CHAR8
* OutputFileName
= NULL
;
174 CHAR8
* InputFileNames
[MAX_PE_IMAGES
+ 1];
175 UINT8 InputFileCount
= 0;
176 UINT64 DebugLevel
= 0;
177 UINT64 VerboseLevel
= 0;
178 EFI_STATUS Status
= EFI_SUCCESS
;
180 SetUtilityName (UTILITY_NAME
);
183 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
190 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
192 return STATUS_SUCCESS
;
195 if (stricmp (argv
[0], "--version") == 0) {
197 return STATUS_SUCCESS
;
202 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--output") == 0)) {
203 OutputFileName
= argv
[1];
204 if (OutputFileName
== NULL
) {
205 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be null");
213 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
219 if ((strlen(argv
[0]) >= 2 && argv
[0][0] == '-' && (argv
[0][1] == 'v' || argv
[0][1] == 'V')) || (stricmp (argv
[0], "--verbose") == 0)) {
221 if (strlen(argv
[0]) > 2) {
222 Status
= CountVerboseLevel (&argv
[0][2], strlen(argv
[0]) - 2, &VerboseLevel
);
223 if (EFI_ERROR (Status
)) {
224 Error (NULL
, 0, 1003, "Invalid option value", argv
[0]);
234 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
235 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &DebugLevel
);
236 if (EFI_ERROR (Status
)) {
237 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
245 // Don't recognize the parameter, should be regarded as the input file name.
247 InputFileNames
[InputFileCount
] = argv
[0];
253 if (InputFileCount
== 0) {
254 Error (NULL
, 0, 1001, "Missing option", "No input file");
258 // Open output file for write
260 if (OutputFileName
== NULL
) {
261 Error (NULL
, 0, 1001, "Missing option", "No output file");
265 fpOut
= fopen (LongFilePath (OutputFileName
), "w+b");
267 Error (NULL
, 0, 0001, "Could not open output file", OutputFileName
);
271 memset (&EfiLdrHeader
, 0, sizeof (EfiLdrHeader
));
272 memset (&EfiLdrImage
, 0, sizeof (EFILDR_IMAGE
) * (InputFileCount
));
274 memcpy (&EfiLdrHeader
.Signature
, "EFIL", 4);
275 EfiLdrHeader
.FileLength
= sizeof(EFILDR_HEADER
) + sizeof(EFILDR_IMAGE
)*(InputFileCount
);
278 // Skip the file header first
280 fseek (fpOut
, EfiLdrHeader
.FileLength
, SEEK_SET
);
283 // copy all the input files to the output file
285 for(i
=0;i
<InputFileCount
;i
++) {
287 // Copy the content of PeImage file to output file
289 fpIn
= fopen (LongFilePath (InputFileNames
[i
]), "rb");
291 Error (NULL
, 0, 0001, "Could not open input file", InputFileNames
[i
]);
295 filesize
= FCopyFile (fpIn
, fpOut
);
299 // And in the same time update the EfiLdrHeader and EfiLdrImage array
301 EfiLdrImage
[i
].Offset
= EfiLdrHeader
.FileLength
;
302 EfiLdrImage
[i
].Length
= (UINT32
) filesize
;
303 strncpy ((CHAR8
*) EfiLdrImage
[i
].FileName
, InputFileNames
[i
], sizeof (EfiLdrImage
[i
].FileName
) - 1);
304 EfiLdrHeader
.FileLength
+= (UINT32
) filesize
;
305 EfiLdrHeader
.NumberOfImages
++;
309 // Write the image header to the output file finally
311 fseek (fpOut
, 0, SEEK_SET
);
312 fwrite (&EfiLdrHeader
, sizeof(EFILDR_HEADER
) , 1, fpOut
);
313 fwrite (&EfiLdrImage
, sizeof(EFILDR_IMAGE
)*(InputFileCount
), 1, fpOut
);
316 printf ("Created %s\n", OutputFileName
);