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