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