]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/EfiLdrImage/EfiLdrImage.c
BaseTools EfiLdrImage: Remove unnecessary exit (0)
[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 77 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
30fdf114
LG
78}\r
79\r
80VOID\r
81Usage (\r
82 VOID\r
83 )\r
84{\r
85 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");\r
45258285
LG
86 printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
87 printf ("Copyright (c) 1999-2016 Intel Corporation. All rights reserved.\n");\r
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
91EFI_STATUS\r
92CountVerboseLevel (\r
93 IN CONST CHAR8* VerboseLevelString,\r
94 IN CONST UINT64 Length,\r
95 OUT UINT64 *ReturnValue\r
96)\r
97{\r
98 UINT64 i = 0;\r
99 for (;i < Length; ++i) {\r
100 if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {\r
101 return EFI_ABORTED;\r
102 }\r
103 ++(*ReturnValue);\r
104 }\r
105 \r
106 return EFI_SUCCESS;\r
107}\r
108\r
109UINT64\r
110FCopyFile (\r
111 FILE *in,\r
112 FILE *out\r
113 )\r
114/*++\r
115Routine Description:\r
116 Write all the content of input file to output file.\r
117\r
118Arguments:\r
119 in - input file pointer\r
120 out - output file pointer\r
121\r
122Return:\r
123 UINT64 : file size of input file\r
124--*/\r
125{\r
fd171542 126 UINT32 filesize, offset, length;\r
30fdf114
LG
127 CHAR8 Buffer[8*1024];\r
128\r
129 fseek (in, 0, SEEK_END);\r
130 filesize = ftell(in);\r
131\r
132 fseek (in, 0, SEEK_SET);\r
133\r
134 offset = 0;\r
135 while (offset < filesize) {\r
136 length = sizeof(Buffer);\r
137 if (filesize-offset < length) {\r
138 length = filesize-offset;\r
139 }\r
140\r
141 fread (Buffer, length, 1, in);\r
142 fwrite (Buffer, length, 1, out);\r
143 offset += length;\r
144 }\r
145\r
146 return filesize;\r
147}\r
148\r
149\r
150int\r
151main (\r
152 int argc,\r
153 char *argv[]\r
154 )\r
155/*++\r
156\r
157Routine Description:\r
158\r
159\r
160Arguments:\r
161\r
162\r
163Returns:\r
164\r
165\r
166--*/\r
167{\r
168 UINT64 i;\r
169 UINT64 filesize;\r
170 FILE *fpIn, *fpOut;\r
171 EFILDR_HEADER EfiLdrHeader;\r
172 EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES];\r
173 CHAR8* OutputFileName = NULL;\r
174 CHAR8* InputFileNames[MAX_PE_IMAGES + 1];\r
175 UINT8 InputFileCount = 0;\r
30fdf114
LG
176 UINT64 DebugLevel = 0;\r
177 UINT64 VerboseLevel = 0;\r
178 EFI_STATUS Status = EFI_SUCCESS;\r
179 \r
180 SetUtilityName (UTILITY_NAME);\r
181\r
182 if (argc == 1) {\r
45258285 183 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");\r
30fdf114
LG
184 return STATUS_ERROR;\r
185 }\r
186 \r
187 argc --;\r
188 argv ++;\r
189\r
190 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
191 Usage();\r
192 return STATUS_SUCCESS; \r
193 }\r
194\r
195 if (stricmp (argv[0], "--version") == 0) {\r
196 Version();\r
197 return STATUS_SUCCESS; \r
198 }\r
199\r
200 while (argc > 0) {\r
201 \r
202 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {\r
203 OutputFileName = argv[1];\r
204 if (OutputFileName == NULL) {\r
205 Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");\r
206 return STATUS_ERROR;\r
207 }\r
208 argc -= 2;\r
209 argv += 2;\r
210 continue; \r
211 }\r
212 \r
213 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
30fdf114
LG
214 argc --;\r
215 argv ++;\r
216 continue; \r
217 }\r
218 \r
219 if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {\r
220 VerboseLevel = 1;\r
221 if (strlen(argv[0]) > 2) {\r
222 Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);\r
223 if (EFI_ERROR (Status)) {\r
224 Error (NULL, 0, 1003, "Invalid option value", argv[0]);\r
225 return STATUS_ERROR; \r
226 }\r
227 }\r
228 \r
229 argc --;\r
230 argv ++;\r
231 continue; \r
232 }\r
233 \r
234 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
235 Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);\r
236 if (EFI_ERROR (Status)) {\r
237 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
238 return STATUS_ERROR; \r
239 }\r
240 argc -= 2;\r
241 argv += 2;\r
242 continue; \r
243 }\r
244 //\r
fd171542 245 // Don't recognize the parameter, should be regarded as the input file name.\r
30fdf114
LG
246 //\r
247 InputFileNames[InputFileCount] = argv[0];\r
248 InputFileCount++;\r
249 argc--;\r
250 argv++;\r
251 }\r
252\r
253 if (InputFileCount == 0) {\r
254 Error (NULL, 0, 1001, "Missing option", "No input file");\r
255 return STATUS_ERROR;\r
256 }\r
257 //\r
258 // Open output file for write\r
259 //\r
260 if (OutputFileName == NULL) {\r
261 Error (NULL, 0, 1001, "Missing option", "No output file");\r
262 return STATUS_ERROR;\r
263 }\r
264\r
1be2ed90 265 fpOut = fopen (LongFilePath (OutputFileName), "w+b");\r
30fdf114
LG
266 if (!fpOut) {\r
267 Error (NULL, 0, 0001, "Could not open output file", OutputFileName);\r
268 return STATUS_ERROR;\r
269 }\r
270\r
271 memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));\r
272 memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));\r
273\r
274 memcpy (&EfiLdrHeader.Signature, "EFIL", 4);\r
275 EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);\r
276\r
277 //\r
278 // Skip the file header first\r
279 //\r
280 fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);\r
281\r
282 //\r
283 // copy all the input files to the output file\r
284 //\r
285 for(i=0;i<InputFileCount;i++) {\r
286 //\r
287 // Copy the content of PeImage file to output file\r
288 //\r
1be2ed90 289 fpIn = fopen (LongFilePath (InputFileNames[i]), "rb");\r
30fdf114
LG
290 if (!fpIn) {\r
291 Error (NULL, 0, 0001, "Could not open input file", InputFileNames[i]);\r
292 fclose (fpOut);\r
293 return STATUS_ERROR;\r
294 }\r
295 filesize = FCopyFile (fpIn, fpOut);\r
296 fclose(fpIn);\r
297\r
298 //\r
299 // And in the same time update the EfiLdrHeader and EfiLdrImage array\r
300 //\r
301 EfiLdrImage[i].Offset = EfiLdrHeader.FileLength;\r
fd171542 302 EfiLdrImage[i].Length = (UINT32) filesize;\r
30fdf114 303 strncpy ((CHAR8*) EfiLdrImage[i].FileName, InputFileNames[i], sizeof (EfiLdrImage[i].FileName) - 1);\r
fd171542 304 EfiLdrHeader.FileLength += (UINT32) filesize;\r
30fdf114
LG
305 EfiLdrHeader.NumberOfImages++;\r
306 }\r
307\r
308 //\r
309 // Write the image header to the output file finally\r
310 //\r
311 fseek (fpOut, 0, SEEK_SET);\r
312 fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);\r
313 fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);\r
314\r
315 fclose (fpOut);\r
316 printf ("Created %s\n", OutputFileName);\r
317 return 0;\r
318}\r
319\r