]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
BootSectImage.exe, EfiLdrImage.exe and Split.exe tools have incorrect output from...
[mirror_edk2.git] / BaseTools / Source / C / EfiLdrImage / EfiLdrImage.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
1be2ed90 3Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>\r
40d841f6 4This program and the accompanying materials \r
30fdf114
LG
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 efildrimage.c\r
15\r
16Abstract:\r
17\r
18 Creates and EFILDR image.\r
19 This tool combines several PE Image files together using following format denoted as EBNF:\r
20 FILE := EFILDR_HEADER\r
21 EFILDR_IMAGE +\r
22 <PeImageFileContent> +\r
23 The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent.\r
24\r
25Revision History\r
26\r
27**/\r
28\r
29\r
30#include <stdio.h>\r
31#include <stdlib.h>\r
32#include <string.h>\r
33#include "ParseInf.h"\r
34#include "CommonLib.h"\r
35#include "EfiUtilityMsgs.h"\r
36\r
37#define MAX_PE_IMAGES 63\r
38#define FILE_TYPE_FIXED_LOADER 0\r
39#define FILE_TYPE_RELOCATABLE_PE_IMAGE 1\r
40\r
41typedef struct {\r
42 UINT32 CheckSum;\r
43 UINT32 Offset;\r
44 UINT32 Length;\r
45 UINT8 FileName[52];\r
46} EFILDR_IMAGE;\r
47\r
48typedef struct { \r
49 UINT32 Signature; \r
50 UINT32 HeaderCheckSum;\r
51 UINT32 FileLength;\r
52 UINT32 NumberOfImages;\r
53} EFILDR_HEADER;\r
54\r
55//\r
56// Utility Name\r
57//\r
58#define UTILITY_NAME "EfiLdrImage"\r
59\r
60//\r
61// Utility version information\r
62//\r
63#define UTILITY_MAJOR_VERSION 0\r
64#define UTILITY_MINOR_VERSION 1\r
65\r
66void\r
67Version (\r
68 void\r
69 )\r
70/*++\r
71\r
72Routine Description:\r
73\r
74 Displays the standard utility information to SDTOUT\r
75\r
76Arguments:\r
77\r
78 None\r
79\r
80Returns:\r
81\r
82 None\r
83\r
84--*/\r
85{\r
d90aa462 86 printf ("%s Version %d.%d %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
1be2ed90 87 printf ("Copyright (c) 1999-2014 Intel Corporation. All rights reserved.\n");\r
d90aa462 88 printf ("\n The EfiLdrImage tool is used to combine PE files into EFILDR image with Efi loader header.\n");\r
30fdf114
LG
89}\r
90\r
91VOID\r
92Usage (\r
93 VOID\r
94 )\r
95{\r
96 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");\r
97 exit (1);\r
98}\r
99\r
100EFI_STATUS\r
101CountVerboseLevel (\r
102 IN CONST CHAR8* VerboseLevelString,\r
103 IN CONST UINT64 Length,\r
104 OUT UINT64 *ReturnValue\r
105)\r
106{\r
107 UINT64 i = 0;\r
108 for (;i < Length; ++i) {\r
109 if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {\r
110 return EFI_ABORTED;\r
111 }\r
112 ++(*ReturnValue);\r
113 }\r
114 \r
115 return EFI_SUCCESS;\r
116}\r
117\r
118UINT64\r
119FCopyFile (\r
120 FILE *in,\r
121 FILE *out\r
122 )\r
123/*++\r
124Routine Description:\r
125 Write all the content of input file to output file.\r
126\r
127Arguments:\r
128 in - input file pointer\r
129 out - output file pointer\r
130\r
131Return:\r
132 UINT64 : file size of input file\r
133--*/\r
134{\r
fd171542 135 UINT32 filesize, offset, length;\r
30fdf114
LG
136 CHAR8 Buffer[8*1024];\r
137\r
138 fseek (in, 0, SEEK_END);\r
139 filesize = ftell(in);\r
140\r
141 fseek (in, 0, SEEK_SET);\r
142\r
143 offset = 0;\r
144 while (offset < filesize) {\r
145 length = sizeof(Buffer);\r
146 if (filesize-offset < length) {\r
147 length = filesize-offset;\r
148 }\r
149\r
150 fread (Buffer, length, 1, in);\r
151 fwrite (Buffer, length, 1, out);\r
152 offset += length;\r
153 }\r
154\r
155 return filesize;\r
156}\r
157\r
158\r
159int\r
160main (\r
161 int argc,\r
162 char *argv[]\r
163 )\r
164/*++\r
165\r
166Routine Description:\r
167\r
168\r
169Arguments:\r
170\r
171\r
172Returns:\r
173\r
174\r
175--*/\r
176{\r
177 UINT64 i;\r
178 UINT64 filesize;\r
179 FILE *fpIn, *fpOut;\r
180 EFILDR_HEADER EfiLdrHeader;\r
181 EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES];\r
182 CHAR8* OutputFileName = NULL;\r
183 CHAR8* InputFileNames[MAX_PE_IMAGES + 1];\r
184 UINT8 InputFileCount = 0;\r
30fdf114
LG
185 UINT64 DebugLevel = 0;\r
186 UINT64 VerboseLevel = 0;\r
187 EFI_STATUS Status = EFI_SUCCESS;\r
188 \r
189 SetUtilityName (UTILITY_NAME);\r
190\r
191 if (argc == 1) {\r
192 Usage();\r
193 return STATUS_ERROR;\r
194 }\r
195 \r
196 argc --;\r
197 argv ++;\r
198\r
199 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
200 Usage();\r
201 return STATUS_SUCCESS; \r
202 }\r
203\r
204 if (stricmp (argv[0], "--version") == 0) {\r
205 Version();\r
206 return STATUS_SUCCESS; \r
207 }\r
208\r
209 while (argc > 0) {\r
210 \r
211 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
212 OutputFileName = argv[1];\r
213 if (OutputFileName == NULL) {\r
214 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");\r
215 return STATUS_ERROR;\r
216 }\r
217 argc -= 2;\r
218 argv += 2;\r
219 continue; \r
220 }\r
221 \r
222 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
30fdf114
LG
223 argc --;\r
224 argv ++;\r
225 continue; \r
226 }\r
227 \r
228 if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {\r
229 VerboseLevel = 1;\r
230 if (strlen(argv[0]) > 2) {\r
231 Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);\r
232 if (EFI_ERROR (Status)) {\r
233 Error (NULL, 0, 1003, "Invalid option value", argv[0]);\r
234 return STATUS_ERROR; \r
235 }\r
236 }\r
237 \r
238 argc --;\r
239 argv ++;\r
240 continue; \r
241 }\r
242 \r
243 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
244 Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);\r
245 if (EFI_ERROR (Status)) {\r
246 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
247 return STATUS_ERROR; \r
248 }\r
249 argc -= 2;\r
250 argv += 2;\r
251 continue; \r
252 }\r
253 //\r
fd171542 254 // Don't recognize the parameter, should be regarded as the input file name.\r
30fdf114
LG
255 //\r
256 InputFileNames[InputFileCount] = argv[0];\r
257 InputFileCount++;\r
258 argc--;\r
259 argv++;\r
260 }\r
261\r
262 if (InputFileCount == 0) {\r
263 Error (NULL, 0, 1001, "Missing option", "No input file");\r
264 return STATUS_ERROR;\r
265 }\r
266 //\r
267 // Open output file for write\r
268 //\r
269 if (OutputFileName == NULL) {\r
270 Error (NULL, 0, 1001, "Missing option", "No output file");\r
271 return STATUS_ERROR;\r
272 }\r
273\r
1be2ed90 274 fpOut = fopen (LongFilePath (OutputFileName), "w+b");\r
30fdf114
LG
275 if (!fpOut) {\r
276 Error (NULL, 0, 0001, "Could not open output file", OutputFileName);\r
277 return STATUS_ERROR;\r
278 }\r
279\r
280 memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));\r
281 memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));\r
282\r
283 memcpy (&EfiLdrHeader.Signature, "EFIL", 4);\r
284 EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);\r
285\r
286 //\r
287 // Skip the file header first\r
288 //\r
289 fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);\r
290\r
291 //\r
292 // copy all the input files to the output file\r
293 //\r
294 for(i=0;i<InputFileCount;i++) {\r
295 //\r
296 // Copy the content of PeImage file to output file\r
297 //\r
1be2ed90 298 fpIn = fopen (LongFilePath (InputFileNames[i]), "rb");\r
30fdf114
LG
299 if (!fpIn) {\r
300 Error (NULL, 0, 0001, "Could not open input file", InputFileNames[i]);\r
301 fclose (fpOut);\r
302 return STATUS_ERROR;\r
303 }\r
304 filesize = FCopyFile (fpIn, fpOut);\r
305 fclose(fpIn);\r
306\r
307 //\r
308 // And in the same time update the EfiLdrHeader and EfiLdrImage array\r
309 //\r
310 EfiLdrImage[i].Offset = EfiLdrHeader.FileLength;\r
fd171542 311 EfiLdrImage[i].Length = (UINT32) filesize;\r
30fdf114 312 strncpy ((CHAR8*) EfiLdrImage[i].FileName, InputFileNames[i], sizeof (EfiLdrImage[i].FileName) - 1);\r
fd171542 313 EfiLdrHeader.FileLength += (UINT32) filesize;\r
30fdf114
LG
314 EfiLdrHeader.NumberOfImages++;\r
315 }\r
316\r
317 //\r
318 // Write the image header to the output file finally\r
319 //\r
320 fseek (fpOut, 0, SEEK_SET);\r
321 fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);\r
322 fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);\r
323\r
324 fclose (fpOut);\r
325 printf ("Created %s\n", OutputFileName);\r
326 return 0;\r
327}\r
328\r