]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
Sync BaseTools Trunk (version r2387) to EDKII main trunk.
[mirror_edk2.git] / BaseTools / Source / C / EfiLdrImage / EfiLdrImage.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
0d2711a6 3Copyright (c) 2006 - 2011, 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
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
30fdf114
LG
184 UINT64 DebugLevel = 0;\r
185 UINT64 VerboseLevel = 0;\r
186 EFI_STATUS Status = EFI_SUCCESS;\r
187 \r
188 SetUtilityName (UTILITY_NAME);\r
189\r
190 if (argc == 1) {\r
191 Usage();\r
192 return STATUS_ERROR;\r
193 }\r
194 \r
195 argc --;\r
196 argv ++;\r
197\r
198 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
199 Usage();\r
200 return STATUS_SUCCESS; \r
201 }\r
202\r
203 if (stricmp (argv[0], "--version") == 0) {\r
204 Version();\r
205 return STATUS_SUCCESS; \r
206 }\r
207\r
208 while (argc > 0) {\r
209 \r
210 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
211 OutputFileName = argv[1];\r
212 if (OutputFileName == NULL) {\r
213 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");\r
214 return STATUS_ERROR;\r
215 }\r
216 argc -= 2;\r
217 argv += 2;\r
218 continue; \r
219 }\r
220 \r
221 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
30fdf114
LG
222 argc --;\r
223 argv ++;\r
224 continue; \r
225 }\r
226 \r
227 if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {\r
228 VerboseLevel = 1;\r
229 if (strlen(argv[0]) > 2) {\r
230 Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);\r
231 if (EFI_ERROR (Status)) {\r
232 Error (NULL, 0, 1003, "Invalid option value", argv[0]);\r
233 return STATUS_ERROR; \r
234 }\r
235 }\r
236 \r
237 argc --;\r
238 argv ++;\r
239 continue; \r
240 }\r
241 \r
242 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
243 Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);\r
244 if (EFI_ERROR (Status)) {\r
245 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
246 return STATUS_ERROR; \r
247 }\r
248 argc -= 2;\r
249 argv += 2;\r
250 continue; \r
251 }\r
252 //\r
fd171542 253 // Don't recognize the parameter, should be regarded as the input file name.\r
30fdf114
LG
254 //\r
255 InputFileNames[InputFileCount] = argv[0];\r
256 InputFileCount++;\r
257 argc--;\r
258 argv++;\r
259 }\r
260\r
261 if (InputFileCount == 0) {\r
262 Error (NULL, 0, 1001, "Missing option", "No input file");\r
263 return STATUS_ERROR;\r
264 }\r
265 //\r
266 // Open output file for write\r
267 //\r
268 if (OutputFileName == NULL) {\r
269 Error (NULL, 0, 1001, "Missing option", "No output file");\r
270 return STATUS_ERROR;\r
271 }\r
272\r
273 fpOut = fopen(OutputFileName, "w+b");\r
274 if (!fpOut) {\r
275 Error (NULL, 0, 0001, "Could not open output file", OutputFileName);\r
276 return STATUS_ERROR;\r
277 }\r
278\r
279 memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));\r
280 memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));\r
281\r
282 memcpy (&EfiLdrHeader.Signature, "EFIL", 4);\r
283 EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);\r
284\r
285 //\r
286 // Skip the file header first\r
287 //\r
288 fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);\r
289\r
290 //\r
291 // copy all the input files to the output file\r
292 //\r
293 for(i=0;i<InputFileCount;i++) {\r
294 //\r
295 // Copy the content of PeImage file to output file\r
296 //\r
297 fpIn = fopen (InputFileNames[i], "rb");\r
298 if (!fpIn) {\r
299 Error (NULL, 0, 0001, "Could not open input file", InputFileNames[i]);\r
300 fclose (fpOut);\r
301 return STATUS_ERROR;\r
302 }\r
303 filesize = FCopyFile (fpIn, fpOut);\r
304 fclose(fpIn);\r
305\r
306 //\r
307 // And in the same time update the EfiLdrHeader and EfiLdrImage array\r
308 //\r
309 EfiLdrImage[i].Offset = EfiLdrHeader.FileLength;\r
fd171542 310 EfiLdrImage[i].Length = (UINT32) filesize;\r
30fdf114 311 strncpy ((CHAR8*) EfiLdrImage[i].FileName, InputFileNames[i], sizeof (EfiLdrImage[i].FileName) - 1);\r
fd171542 312 EfiLdrHeader.FileLength += (UINT32) filesize;\r
30fdf114
LG
313 EfiLdrHeader.NumberOfImages++;\r
314 }\r
315\r
316 //\r
317 // Write the image header to the output file finally\r
318 //\r
319 fseek (fpOut, 0, SEEK_SET);\r
320 fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);\r
321 fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);\r
322\r
323 fclose (fpOut);\r
324 printf ("Created %s\n", OutputFileName);\r
325 return 0;\r
326}\r
327\r