Sync basetools' source and binary files with r1707 of the basetools project.
[edk2.git] / BaseTools / Source / C / EfiLdrImage / EfiLdrImage.c
blobc2c8111d31be31c35c5e3cdbe012b4e956c312a0
1 /** @file
3 Copyright 2006 - 2008, Intel Corporation
4 All rights reserved. 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
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.
12 Module Name:
14 efildrimage.c
16 Abstract:
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.
25 Revision History
27 **/
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include "ParseInf.h"
34 #include "CommonLib.h"
35 #include "EfiUtilityMsgs.h"
37 #define MAX_PE_IMAGES 63
38 #define FILE_TYPE_FIXED_LOADER 0
39 #define FILE_TYPE_RELOCATABLE_PE_IMAGE 1
41 typedef struct {
42 UINT32 CheckSum;
43 UINT32 Offset;
44 UINT32 Length;
45 UINT8 FileName[52];
46 } EFILDR_IMAGE;
48 typedef struct {
49 UINT32 Signature;
50 UINT32 HeaderCheckSum;
51 UINT32 FileLength;
52 UINT32 NumberOfImages;
53 } EFILDR_HEADER;
56 // Utility Name
58 #define UTILITY_NAME "EfiLdrImage"
61 // Utility version information
63 #define UTILITY_MAJOR_VERSION 0
64 #define UTILITY_MINOR_VERSION 1
66 void
67 Version (
68 void
70 /*++
72 Routine Description:
74 Displays the standard utility information to SDTOUT
76 Arguments:
78 None
80 Returns:
82 None
84 --*/
86 printf ("%s v%d.%d -Utility to break a file into two pieces at the request offset.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
87 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
90 VOID
91 Usage (
92 VOID
95 printf ("Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN\n");
96 exit (1);
99 EFI_STATUS
100 CountVerboseLevel (
101 IN CONST CHAR8* VerboseLevelString,
102 IN CONST UINT64 Length,
103 OUT UINT64 *ReturnValue
106 UINT64 i = 0;
107 for (;i < Length; ++i) {
108 if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {
109 return EFI_ABORTED;
111 ++(*ReturnValue);
114 return EFI_SUCCESS;
117 UINT64
118 FCopyFile (
119 FILE *in,
120 FILE *out
122 /*++
123 Routine Description:
124 Write all the content of input file to output file.
126 Arguments:
127 in - input file pointer
128 out - output file pointer
130 Return:
131 UINT64 : file size of input file
132 --*/
134 UINT32 filesize, offset, length;
135 CHAR8 Buffer[8*1024];
137 fseek (in, 0, SEEK_END);
138 filesize = ftell(in);
140 fseek (in, 0, SEEK_SET);
142 offset = 0;
143 while (offset < filesize) {
144 length = sizeof(Buffer);
145 if (filesize-offset < length) {
146 length = filesize-offset;
149 fread (Buffer, length, 1, in);
150 fwrite (Buffer, length, 1, out);
151 offset += length;
154 return filesize;
159 main (
160 int argc,
161 char *argv[]
163 /*++
165 Routine Description:
168 Arguments:
171 Returns:
174 --*/
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;
189 SetUtilityName (UTILITY_NAME);
191 if (argc == 1) {
192 Usage();
193 return STATUS_ERROR;
196 argc --;
197 argv ++;
199 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
200 Usage();
201 return STATUS_SUCCESS;
204 if (stricmp (argv[0], "--version") == 0) {
205 Version();
206 return STATUS_SUCCESS;
209 while (argc > 0) {
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;
217 argc -= 2;
218 argv += 2;
219 continue;
222 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
223 QuietFlag = TRUE;
224 argc --;
225 argv ++;
226 continue;
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;
239 argc --;
240 argv ++;
241 continue;
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;
250 argc -= 2;
251 argv += 2;
252 continue;
255 // Don't recognize the parameter, should be regarded as the input file name.
257 InputFileNames[InputFileCount] = argv[0];
258 InputFileCount++;
259 argc--;
260 argv++;
263 if (InputFileCount == 0) {
264 Error (NULL, 0, 1001, "Missing option", "No input file");
265 return STATUS_ERROR;
268 // Open output file for write
270 if (OutputFileName == NULL) {
271 Error (NULL, 0, 1001, "Missing option", "No output file");
272 return STATUS_ERROR;
275 fpOut = fopen(OutputFileName, "w+b");
276 if (!fpOut) {
277 Error (NULL, 0, 0001, "Could not open output file", OutputFileName);
278 return STATUS_ERROR;
281 memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader));
282 memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (InputFileCount));
284 memcpy (&EfiLdrHeader.Signature, "EFIL", 4);
285 EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(InputFileCount);
288 // Skip the file header first
290 fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET);
293 // copy all the input files to the output file
295 for(i=0;i<InputFileCount;i++) {
297 // Copy the content of PeImage file to output file
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;
305 filesize = FCopyFile (fpIn, fpOut);
306 fclose(fpIn);
309 // And in the same time update the EfiLdrHeader and EfiLdrImage array
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++;
319 // Write the image header to the output file finally
321 fseek (fpOut, 0, SEEK_SET);
322 fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut);
323 fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(InputFileCount), 1, fpOut);
325 fclose (fpOut);
326 printf ("Created %s\n", OutputFileName);
327 return 0;