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