]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
Sync BaseTools Branch (version r2321) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / EfiLdrImage / EfiLdrImage.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
40d841f6
LG
3Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
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
b36d134f 86 printf ("%s v%d.%d %s -Utility to break a file into two pieces at the request offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
52302d4d 87 printf ("Copyright (c) 1999-2010 Intel Corporation. All rights reserved.\n");\r
30fdf114
LG
88}\r
89\r
90VOID\r
91Usage (\r
92 VOID\r
93 )\r
94{\r
95 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");\r
96 exit (1);\r
97}\r
98\r
99EFI_STATUS\r
100CountVerboseLevel (\r
101 IN CONST CHAR8* VerboseLevelString,\r
102 IN CONST UINT64 Length,\r
103 OUT UINT64 *ReturnValue\r
104)\r
105{\r
106 UINT64 i = 0;\r
107 for (;i < Length; ++i) {\r
108 if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {\r
109 return EFI_ABORTED;\r
110 }\r
111 ++(*ReturnValue);\r
112 }\r
113 \r
114 return EFI_SUCCESS;\r
115}\r
116\r
117UINT64\r
118FCopyFile (\r
119 FILE *in,\r
120 FILE *out\r
121 )\r
122/*++\r
123Routine Description:\r
124 Write all the content of input file to output file.\r
125\r
126Arguments:\r
127 in - input file pointer\r
128 out - output file pointer\r
129\r
130Return:\r
131 UINT64 : file size of input file\r
132--*/\r
133{\r
fd171542 134 UINT32 filesize, offset, length;\r
30fdf114
LG
135 CHAR8 Buffer[8*1024];\r
136\r
137 fseek (in, 0, SEEK_END);\r
138 filesize = ftell(in);\r
139\r
140 fseek (in, 0, SEEK_SET);\r
141\r
142 offset = 0;\r
143 while (offset < filesize) {\r
144 length = sizeof(Buffer);\r
145 if (filesize-offset < length) {\r
146 length = filesize-offset;\r
147 }\r
148\r
149 fread (Buffer, length, 1, in);\r
150 fwrite (Buffer, length, 1, out);\r
151 offset += length;\r
152 }\r
153\r
154 return filesize;\r
155}\r
156\r
157\r
158int\r
159main (\r
160 int argc,\r
161 char *argv[]\r
162 )\r
163/*++\r
164\r
165Routine Description:\r
166\r
167\r
168Arguments:\r
169\r
170\r
171Returns:\r
172\r
173\r
174--*/\r
175{\r
176 UINT64 i;\r
177 UINT64 filesize;\r
178 FILE *fpIn, *fpOut;\r
179 EFILDR_HEADER EfiLdrHeader;\r
180 EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES];\r
181 CHAR8* OutputFileName = NULL;\r
182 CHAR8* InputFileNames[MAX_PE_IMAGES + 1];\r
183 UINT8 InputFileCount = 0;\r
184 BOOLEAN QuietFlag = FALSE;\r
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
223 QuietFlag = TRUE;\r
224 argc --;\r
225 argv ++;\r
226 continue; \r
227 }\r
228 \r
229 if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {\r
230 VerboseLevel = 1;\r
231 if (strlen(argv[0]) > 2) {\r
232 Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);\r
233 if (EFI_ERROR (Status)) {\r
234 Error (NULL, 0, 1003, "Invalid option value", argv[0]);\r
235 return STATUS_ERROR; \r
236 }\r
237 }\r
238 \r
239 argc --;\r
240 argv ++;\r
241 continue; \r
242 }\r
243 \r
244 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
245 Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);\r
246 if (EFI_ERROR (Status)) {\r
247 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
248 return STATUS_ERROR; \r
249 }\r
250 argc -= 2;\r
251 argv += 2;\r
252 continue; \r
253 }\r
254 //\r
fd171542 255 // Don't recognize the parameter, should be regarded as the input file name.\r
30fdf114
LG
256 //\r
257 InputFileNames[InputFileCount] = argv[0];\r
258 InputFileCount++;\r
259 argc--;\r
260 argv++;\r
261 }\r
262\r
263 if (InputFileCount == 0) {\r
264 Error (NULL, 0, 1001, "Missing option", "No input file");\r
265 return STATUS_ERROR;\r
266 }\r
267 //\r
268 // Open output file for write\r
269 //\r
270 if (OutputFileName == NULL) {\r
271 Error (NULL, 0, 1001, "Missing option", "No output file");\r
272 return STATUS_ERROR;\r
273 }\r
274\r
275 fpOut = fopen(OutputFileName, "w+b");\r
276 if (!fpOut) {\r
277 Error (NULL, 0, 0001, "Could not open output file", OutputFileName);\r
278 return STATUS_ERROR;\r
279 }\r
280\r
281 memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));\r
282 memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));\r
283\r
284 memcpy (&EfiLdrHeader.Signature, "EFIL", 4);\r
285 EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);\r
286\r
287 //\r
288 // Skip the file header first\r
289 //\r
290 fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);\r
291\r
292 //\r
293 // copy all the input files to the output file\r
294 //\r
295 for(i=0;i<InputFileCount;i++) {\r
296 //\r
297 // Copy the content of PeImage file to output file\r
298 //\r
299 fpIn = fopen (InputFileNames[i], "rb");\r
300 if (!fpIn) {\r
301 Error (NULL, 0, 0001, "Could not open input file", InputFileNames[i]);\r
302 fclose (fpOut);\r
303 return STATUS_ERROR;\r
304 }\r
305 filesize = FCopyFile (fpIn, fpOut);\r
306 fclose(fpIn);\r
307\r
308 //\r
309 // And in the same time update the EfiLdrHeader and EfiLdrImage array\r
310 //\r
311 EfiLdrImage[i].Offset = EfiLdrHeader.FileLength;\r
fd171542 312 EfiLdrImage[i].Length = (UINT32) filesize;\r
30fdf114 313 strncpy ((CHAR8*) EfiLdrImage[i].FileName, InputFileNames[i], sizeof (EfiLdrImage[i].FileName) - 1);\r
fd171542 314 EfiLdrHeader.FileLength += (UINT32) filesize;\r
30fdf114
LG
315 EfiLdrHeader.NumberOfImages++;\r
316 }\r
317\r
318 //\r
319 // Write the image header to the output file finally\r
320 //\r
321 fseek (fpOut, 0, SEEK_SET);\r
322 fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);\r
323 fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);\r
324\r
325 fclose (fpOut);\r
326 printf ("Created %s\n", OutputFileName);\r
327 return 0;\r
328}\r
329\r