]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/GenFw/GenFw.c
Sync EDKII BaseTools to BaseTools project r1937.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / GenFw.c
CommitLineData
30fdf114
LG
1/** @file\r
2\r
52302d4d 3Copyright (c) 2004 - 2010, Intel Corporation\r
30fdf114
LG
4All rights reserved. This program and the accompanying materials\r
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 GenFw.c\r
15\r
16Abstract:\r
17\r
18 Converts a pe32+ image to an FW, Te image type, or other specific image.\r
19\r
20**/\r
21\r
22#include "WinNtInclude.h"\r
23\r
24#ifndef __GNUC__\r
25#include <windows.h>\r
fd171542 26#include <io.h>\r
636f2be6
LG
27#include <sys/types.h>\r
28#include <sys/stat.h>\r
30fdf114
LG
29#endif\r
30#include <stdio.h>\r
31#include <stdlib.h>\r
32#include <string.h>\r
33#include <time.h>\r
34#include <ctype.h>\r
35\r
36#include <Common/UefiBaseTypes.h>\r
37#include <IndustryStandard/PeImage.h>\r
b303ea72 38#include <Common/UefiInternalFormRepresentation.h>\r
30fdf114
LG
39\r
40//\r
41// Acpi Table definition\r
42//\r
43#include <IndustryStandard/Acpi.h>\r
44#include <IndustryStandard/Acpi1_0.h>\r
45#include <IndustryStandard/Acpi2_0.h>\r
46#include <IndustryStandard/Acpi3_0.h>\r
47#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>\r
48\r
49#include "CommonLib.h"\r
fd171542 50#include "PeCoffLib.h"\r
51#include "ParseInf.h"\r
30fdf114
LG
52#include "EfiUtilityMsgs.h"\r
53\r
54#include "elf_common.h"\r
55#include "elf32.h"\r
56#include "elf64.h"\r
57\r
58\r
59//\r
60// Version of this utility\r
61//\r
62#define UTILITY_NAME "GenFw"\r
63#define UTILITY_MAJOR_VERSION 0\r
64#define UTILITY_MINOR_VERSION 2\r
65\r
b303ea72
LG
66#define HII_RESOURCE_SECTION_INDEX 1\r
67#define HII_RESOURCE_SECTION_NAME "HII"\r
30fdf114
LG
68//\r
69// Action for this tool.\r
70//\r
71#define FW_DUMMY_IMAGE 0\r
72#define FW_EFI_IMAGE 1\r
73#define FW_TE_IMAGE 2\r
74#define FW_ACPI_IMAGE 3\r
75#define FW_BIN_IMAGE 4\r
76#define FW_ZERO_DEBUG_IMAGE 5\r
77#define FW_SET_STAMP_IMAGE 6\r
78#define FW_MCI_IMAGE 7\r
79#define FW_MERGE_IMAGE 8\r
80#define FW_RELOC_STRIPEED_IMAGE 9\r
b303ea72 81#define FW_HII_PACKAGE_LIST_RCIMAGE 10\r
a709adfa 82#define FW_HII_PACKAGE_LIST_BINIMAGE 11\r
52302d4d
LG
83#define FW_REBASE_IMAGE 12\r
84#define FW_SET_ADDRESS_IMAGE 13\r
30fdf114
LG
85\r
86#define DUMP_TE_HEADER 0x11\r
87\r
88#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF\r
89#define DEFAULT_MC_ALIGNMENT 16\r
90\r
91#ifndef _MAX_PATH\r
92#define _MAX_PATH 500\r
93#endif\r
94\r
95#define STATUS_IGNORE 0xA\r
96//\r
97// Structure definition for a microcode header\r
98//\r
99typedef struct {\r
100 UINT32 HeaderVersion;\r
101 UINT32 PatchId;\r
102 UINT32 Date;\r
103 UINT32 CpuId;\r
104 UINT32 Checksum;\r
105 UINT32 LoaderVersion;\r
106 UINT32 PlatformId;\r
107 UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid\r
108 UINT32 TotalSize; // number of bytes\r
109 UINT32 Reserved[3];\r
110} MICROCODE_IMAGE_HEADER;\r
111\r
b303ea72
LG
112static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};\r
113\r
114static const char *gHiiPackageRCFileHeader[] = {\r
115 "//",\r
116 "// DO NOT EDIT -- auto-generated file",\r
117 "//",\r
118 NULL\r
119};\r
120\r
30fdf114
LG
121STATIC CHAR8 *mInImageName;\r
122\r
52302d4d
LG
123//\r
124// Module image information\r
125//\r
126STATIC UINT32 mImageTimeStamp = 0;\r
127STATIC UINT32 mImageSize = 0;\r
128\r
30fdf114
LG
129STATIC\r
130EFI_STATUS\r
131ZeroDebugData (\r
132 IN OUT UINT8 *FileBuffer,\r
133 BOOLEAN ZeroDebug\r
134 );\r
135\r
136STATIC\r
137EFI_STATUS\r
138SetStamp (\r
139 IN OUT UINT8 *FileBuffer,\r
140 IN CHAR8 *TimeStamp\r
141 );\r
142\r
143STATIC\r
144STATUS\r
145MicrocodeReadData (\r
146 FILE *InFptr,\r
147 UINT32 *Data\r
148 );\r
149\r
150STATIC\r
151VOID\r
152Version (\r
153 VOID\r
154 )\r
155/*++\r
156\r
157Routine Description:\r
158\r
159 Print out version information for this utility.\r
160\r
161Arguments:\r
162\r
163 None\r
164\r
165Returns:\r
166\r
167 None\r
168\r
169--*/\r
170{\r
171 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
172}\r
173\r
174STATIC\r
175VOID\r
176Usage (\r
177 VOID\r
178 )\r
179/*++\r
180\r
181Routine Description:\r
182\r
183 Print Help message.\r
184\r
185Arguments:\r
186\r
187 VOID\r
188\r
189Returns:\r
190\r
191 None\r
192\r
193--*/\r
194{\r
195 //\r
196 // Summary usage\r
197 //\r
198 fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);\r
199\r
200 //\r
201 // Copyright declaration\r
202 //\r
52302d4d 203 fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");\r
30fdf114
LG
204\r
205 //\r
206 // Details Option\r
207 //\r
208 fprintf (stdout, "Options:\n");\r
209 fprintf (stdout, " -o FileName, --outputfile FileName\n\\r
210 File will be created to store the ouput content.\n");\r
211 fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\\r
a709adfa 212 Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\\r
30fdf114 213 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\\r
a709adfa
LG
214 SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\\r
215 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\\r
30fdf114
LG
216 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\\r
217 APPLICATION, SAL_RT_DRIVER to support all module types\n\\r
218 It can only be used together with --keepexceptiontable,\n\\r
219 --keepzeropending, -r, -o option.It is a action option.\n\\r
220 If it is combined with other action options, the later\n\\r
221 input action option will override the previous one.\n");\r
222 fprintf (stdout, " -c, --acpi Create Acpi table.\n\\r
223 It can't be combined with other action options\n\\r
224 except for -o, -r option. It is a action option.\n\\r
225 If it is combined with other action options, the later\n\\r
226 input action option will override the previous one.\n");\r
227 fprintf (stdout, " -t, --terse Create Te Image.\n\\r
228 It can only be used together with --keepexceptiontable,\n\\r
229 --keepzeropending, -r, -o option.It is a action option.\n\\r
230 If it is combined with other action options, the later\n\\r
231 input action option will override the previous one.\n");\r
232 fprintf (stdout, " -u, --dump Dump TeImage Header.\n\\r
233 It can't be combined with other action options\n\\r
234 except for -o, -r option. It is a action option.\n\\r
235 If it is combined with other action options, the later\n\\r
236 input action option will override the previous one.\n");\r
237 fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\\r
238 It also zeros the time stamp fields.\n\\r
239 This option can be used to compare the binary efi image.\n\\r
240 It can't be combined with other action options\n\\r
241 except for -o, -r option. It is a action option.\n\\r
242 If it is combined with other action options, the later\n\\r
243 input action option will override the previous one.\n");\r
244 fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\\r
245 It can't be combined with other action options\n\\r
246 except for -o, -r option. It is a action option.\n\\r
247 If it is combined with other action options, the later\n\\r
248 input action option will override the previous one.\n");;\r
a709adfa 249 fprintf (stdout, " -l, --stripped Strip off the relocation info from PE or TE image.\n\\r
30fdf114
LG
250 It can't be combined with other action options\n\\r
251 except for -o, -r option. It is a action option.\n\\r
252 If it is combined with other action options, the later\n\\r
253 input action option will override the previous one.\n");\r
254 fprintf (stdout, " -s timedate, --stamp timedate\n\\r
255 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\\r
256 is set to NOW, current system time is used. The support\n\\r
52302d4d
LG
257 date scope is 1970-01-01 00+timezone:00:00\n\\r
258 ~ 2038-01-19 03+timezone:14:07\n\\r
259 The scope is adjusted according to the different zones.\n\\r
30fdf114
LG
260 It can't be combined with other action options\n\\r
261 except for -o, -r option. It is a action option.\n\\r
262 If it is combined with other action options, the later\n\\r
263 input action option will override the previous one.\n");\r
264 fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\\r
265 It can't be combined with other action options\n\\r
266 except for -o option. It is a action option.\n\\r
267 If it is combined with other action options, the later\n\\r
268 input action option will override the previous one.\n");\r
269 fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\\r
270 It can be specified with -a, -p, -o option.\n\\r
271 No other options can be combined with it.\n\\r
272 If it is combined with other action options, the later\n\\r
273 input action option will override the previous one.\n");\r
274 fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\\r
275 This option is only used together with -j option.\n"); \r
276 fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\\r
277 This option is only used together with -j option.\n");\r
278 fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\\r
279 This option can be used together with -e or -t.\n\\r
280 It doesn't work for other options.\n");\r
281 fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\\r
282 This option can be used together with -e or -t.\n\\r
283 It doesn't work for other options.\n");\r
284 fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\\r
285 If more input files are specified,\n\\r
286 the last input file will be as the output file.\n");\r
b303ea72 287 fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\\r
a709adfa 288 Guid is used to specify hii package list guid.\n\\r
b303ea72
LG
289 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\\r
290 If not specified, the first Form FormSet guid is used.\n");\r
291 fprintf (stdout, " --hiipackage Combine all input binary hii pacakges into \n\\r
292 a single package list as the text resource data(RC).\n\\r
293 It can't be combined with other action options\n\\r
294 except for -o option. It is a action option.\n\\r
295 If it is combined with other action options, the later\n\\r
296 input action option will override the previous one.\n");\r
a709adfa
LG
297 fprintf (stdout, " --hiibinpackage Combine all input binary hii pacakges into \n\\r
298 a single package list as the binary resource section.\n\\r
299 It can't be combined with other action options\n\\r
300 except for -o option. It is a action option.\n\\r
301 If it is combined with other action options, the later\n\\r
302 input action option will override the previous one.\n");\r
52302d4d
LG
303 fprintf (stdout, " --rebase NewAddress Rebase image to new base address. New address \n\\r
304 is also set to the first none code section header.\n\\r
305 It can't be combined with other action options\n\\r
306 except for -o or -r option. It is a action option.\n\\r
307 If it is combined with other action options, the later\n\\r
308 input action option will override the previous one.\n");\r
309 fprintf (stdout, " --address NewAddress Set new address into the first none code \n\\r
310 section header of the input image.\n\\r
311 It can't be combined with other action options\n\\r
312 except for -o or -r option. It is a action option.\n\\r
313 If it is combined with other action options, the later\n\\r
314 input action option will override the previous one.\n");\r
30fdf114
LG
315 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
316 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");\r
317 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");\r
318 fprintf (stdout, " --version Show program's version number and exit\n");\r
319 fprintf (stdout, " -h, --help Show this help message and exit\n");\r
320}\r
321\r
322STATIC\r
323STATUS\r
324CheckAcpiTable (\r
325 VOID *AcpiTable,\r
326 UINT32 Length\r
327 )\r
328/*++\r
329\r
330Routine Description:\r
331\r
332 Check Acpi Table\r
333\r
334Arguments:\r
335\r
336 AcpiTable Buffer for AcpiSection\r
337 Length AcpiSection Length\r
338\r
339Returns:\r
340\r
341 0 success\r
342 non-zero otherwise\r
343\r
344--*/\r
345{\r
346 EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;\r
347 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
348 UINT32 ExpectedLength;\r
349\r
350 AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
351\r
352 //\r
353 // Generic check for AcpiTable length.\r
354 //\r
355 if (AcpiHeader->Length > Length) {\r
356 Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);\r
357 return STATUS_ERROR;\r
358 }\r
359\r
360 //\r
361 // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
362 // and some important tables: MADT, MCFG.\r
363 //\r
364 switch (AcpiHeader->Signature) {\r
365\r
366 //\r
367 // "FACP" Fixed ACPI Description Table\r
368 //\r
369 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
370 switch (AcpiHeader->Revision) {\r
371 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
372 ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
373 break;\r
374 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
375 ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
376 break;\r
377 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
378 ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
379 break;\r
380 default:\r
fd171542 381 if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {\r
382 ExpectedLength = AcpiHeader->Length;\r
383 break;\r
384 }\r
30fdf114
LG
385 Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");\r
386 return STATUS_ERROR;\r
387 }\r
388 if (ExpectedLength != AcpiHeader->Length) {\r
389 Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");\r
390 return STATUS_ERROR;\r
391 }\r
392 break;\r
393\r
394 //\r
395 // "FACS" Firmware ACPI Control Structure\r
396 //\r
397 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
398 Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
fd171542 399 if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {\r
400 break;\r
401 }\r
402 if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
30fdf114
LG
403 (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
404 (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
405 Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");\r
406 return STATUS_ERROR;\r
407 }\r
408 if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
409 (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
410 (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
411 Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");\r
412 return STATUS_ERROR;\r
413 }\r
414 break;\r
415\r
416 //\r
417 // "DSDT" Differentiated System Description Table\r
418 //\r
419 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
420 if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
fd171542 421 break;\r
30fdf114
LG
422 }\r
423 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
424 Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");\r
425 return STATUS_ERROR;\r
426 }\r
427 break;\r
428\r
429 //\r
430 // "APIC" Multiple APIC Description Table\r
431 //\r
432 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
fd171542 433 if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {\r
434 break;\r
435 }\r
30fdf114
LG
436 if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
437 (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
438 (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
439 Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");\r
440 return STATUS_ERROR;\r
441 }\r
442 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
443 Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");\r
444 return STATUS_ERROR;\r
445 }\r
446 break;\r
447\r
448 //\r
449 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
450 //\r
451 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
fd171542 452 if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
453 break;\r
454 }\r
30fdf114
LG
455 if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
456 Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");\r
457 return STATUS_ERROR;\r
458 }\r
459 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
460 Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");\r
461 return STATUS_ERROR;\r
462 }\r
463 break;\r
464\r
465 //\r
466 // Other table pass check\r
467 //\r
468 default:\r
469 break;\r
470 }\r
471\r
472 return STATUS_SUCCESS;\r
473}\r
474\r
475\r
476INTN\r
477IsElfHeader(\r
478 UINT8 *FileBuffer\r
479)\r
480{\r
481 return (FileBuffer[EI_MAG0] == ELFMAG0\r
482 && FileBuffer[EI_MAG1] == ELFMAG1\r
483 && FileBuffer[EI_MAG2] == ELFMAG2\r
484 && FileBuffer[EI_MAG3] == ELFMAG3);\r
485}\r
486\r
487typedef Elf32_Shdr Elf_Shdr;\r
488typedef Elf32_Ehdr Elf_Ehdr;\r
489typedef Elf32_Rel Elf_Rel;\r
490typedef Elf32_Sym Elf_Sym;\r
491typedef Elf32_Phdr Elf_Phdr;\r
492typedef Elf32_Dyn Elf_Dyn;\r
493\r
494#define ELFCLASS ELFCLASS32\r
495#define ELF_R_TYPE(r) ELF32_R_TYPE(r)\r
496#define ELF_R_SYM(r) ELF32_R_SYM(r)\r
b303ea72 497#define ELF_HII_SECTION_NAME ".hii"\r
30fdf114
LG
498//\r
499// Well known ELF structures.\r
500//\r
501Elf_Ehdr *Ehdr;\r
502Elf_Shdr *ShdrBase;\r
503Elf_Phdr *gPhdrBase;\r
504\r
505//\r
506// PE section alignment.\r
507//\r
508const UINT32 CoffAlignment = 0x20;\r
b303ea72 509const UINT16 CoffNbrSections = 5;\r
30fdf114
LG
510\r
511//\r
512// Current offset in coff file.\r
513//\r
514UINT32 CoffOffset;\r
515\r
516//\r
517// Result Coff file in memory.\r
518//\r
519UINT8 *CoffFile = NULL;\r
520//\r
521// ELF sections to offset in Coff file.\r
522//\r
523UINT32 *CoffSectionsOffset = NULL;\r
524\r
525//\r
526// Offset in Coff file of headers and sections.\r
527//\r
528UINT32 NtHdrOffset;\r
529UINT32 TableOffset;\r
530UINT32 TextOffset;\r
531UINT32 DataOffset;\r
b303ea72 532UINT32 HiiRsrcOffset;\r
30fdf114
LG
533UINT32 RelocOffset;\r
534\r
535EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;\r
536UINT16 *CoffEntryRel;\r
537\r
538UINT32\r
539CoffAlign(\r
540 UINT32 Offset\r
541 )\r
542{\r
543 return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);\r
544}\r
545\r
546Elf_Shdr *\r
547GetShdrByIndex(\r
548 UINT32 Num\r
549 )\r
550{\r
551 if (Num >= Ehdr->e_shnum)\r
552 return NULL;\r
553 return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);\r
554}\r
555\r
556INTN\r
557CheckElfHeader(\r
558 VOID\r
559 )\r
560{\r
561 //\r
562 // Note: Magic has already been tested.\r
563 //\r
564 if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) {\r
565 Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName);\r
566 return 0;\r
567 }\r
568 if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {\r
569 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");\r
570 return 0;\r
571 }\r
572 if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) {\r
573 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");\r
574 return 0;\r
575 }\r
576 if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) { \r
577 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");\r
578 return 0;\r
579 }\r
580 if (Ehdr->e_version != EV_CURRENT) {\r
fd171542 581 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) Ehdr->e_version, EV_CURRENT);\r
30fdf114
LG
582 return 0;\r
583 }\r
584\r
585 //\r
586 // Find the section header table\r
587 //\r
588 ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);\r
589 gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff);\r
590\r
591 CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));\r
592\r
593 memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));\r
594 return 1;\r
595}\r
596\r
597int\r
598IsTextShdr(\r
599 Elf_Shdr *Shdr\r
600 )\r
601{\r
602 return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;\r
603}\r
604\r
b303ea72
LG
605int\r
606IsHiiRsrcShdr(\r
607 Elf_Shdr *Shdr\r
608 )\r
609{\r
610 Elf_Shdr *Namedr = GetShdrByIndex(Ehdr->e_shstrndx);\r
611\r
612 if (strcmp((CHAR8*)Ehdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0) {\r
613 return 1;\r
614 }\r
615\r
616 return 0;\r
617}\r
618\r
30fdf114
LG
619int\r
620IsDataShdr(\r
621 Elf_Shdr *Shdr\r
622 )\r
623{\r
b303ea72
LG
624 if (IsHiiRsrcShdr(Shdr)) {\r
625 return 0;\r
626 }\r
30fdf114
LG
627 return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);\r
628}\r
629\r
630VOID\r
631CreateSectionHeader(\r
632 const CHAR8 *Name,\r
633 UINT32 Offset,\r
634 UINT32 Size,\r
635 UINT32 Flags\r
636 )\r
637{\r
638 EFI_IMAGE_SECTION_HEADER *Hdr;\r
639 Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);\r
640\r
641 strcpy((char *)Hdr->Name, Name);\r
642 Hdr->Misc.VirtualSize = Size;\r
643 Hdr->VirtualAddress = Offset;\r
644 Hdr->SizeOfRawData = Size;\r
645 Hdr->PointerToRawData = Offset;\r
646 Hdr->PointerToRelocations = 0;\r
647 Hdr->PointerToLinenumbers = 0;\r
648 Hdr->NumberOfRelocations = 0;\r
649 Hdr->NumberOfLinenumbers = 0;\r
650 Hdr->Characteristics = Flags;\r
651\r
652 TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
653}\r
654\r
b303ea72 655VOID\r
a709adfa
LG
656SetHiiResourceHeader (\r
657 UINT8 *HiiBinData,\r
b303ea72
LG
658 UINT32 OffsetToFile\r
659 )\r
660{\r
b303ea72
LG
661 UINT32 Index;\r
662 EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;\r
663 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;\r
664 EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
665 EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;\r
666\r
b303ea72
LG
667 //\r
668 // Fill Resource section entry\r
669 //\r
a709adfa
LG
670 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData);\r
671 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
672 for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) {\r
673 if (ResourceDirectoryEntry->u1.s.NameIsString) {\r
674 ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset);\r
b303ea72 675\r
a709adfa
LG
676 if (ResourceDirectoryString->Length == 3 &&\r
677 ResourceDirectoryString->String[0] == L'H' &&\r
678 ResourceDirectoryString->String[1] == L'I' &&\r
679 ResourceDirectoryString->String[2] == L'I') {\r
680 //\r
681 // Resource Type "HII" found\r
682 //\r
683 if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
684 //\r
685 // Move to next level - resource Name\r
686 //\r
687 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
688 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
b303ea72 689\r
a709adfa
LG
690 if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
691 //\r
692 // Move to next level - resource Language\r
693 //\r
694 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);\r
695 ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);\r
696 }\r
697 }\r
b303ea72 698\r
a709adfa
LG
699 //\r
700 // Now it ought to be resource Data and update its OffsetToData value \r
701 //\r
702 if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {\r
703 ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData);\r
704 ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile;\r
705 break;\r
706 }\r
b303ea72
LG
707 }\r
708 }\r
a709adfa 709 ResourceDirectoryEntry++;\r
b303ea72
LG
710 }\r
711 \r
712 return;\r
713}\r
714\r
30fdf114
LG
715VOID\r
716ScanSections(\r
717 VOID\r
718 )\r
719{\r
720 UINT32 i;\r
721 EFI_IMAGE_DOS_HEADER *DosHdr;\r
722 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
723 UINT32 CoffEntry;\r
724\r
725 CoffEntry = 0;\r
726 CoffOffset = 0;\r
727\r
728 //\r
729 // Coff file start with a DOS header.\r
730 //\r
731 CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;\r
732 NtHdrOffset = CoffOffset;\r
58e4d800 733 switch (Ehdr->e_machine) {\r
734 case EM_386:\r
735 case EM_ARM:\r
736 CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
737 break;\r
738 case EM_X86_64:\r
739 case EM_IA_64:\r
b303ea72 740 CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64);\r
58e4d800 741 break;\r
742 default:\r
743 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
b303ea72 744 CoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32);\r
58e4d800 745 break;\r
746 }\r
747\r
30fdf114
LG
748 TableOffset = CoffOffset;\r
749 CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);\r
750\r
751 //\r
752 // First text sections.\r
753 //\r
754 CoffOffset = CoffAlign(CoffOffset);\r
755 TextOffset = CoffOffset;\r
756 for (i = 0; i < Ehdr->e_shnum; i++) {\r
757 Elf_Shdr *shdr = GetShdrByIndex(i);\r
758 if (IsTextShdr(shdr)) {\r
759 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
760 // the alignment field is valid\r
761 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
762 // if the section address is aligned we must align PE/COFF \r
763 CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
764 } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
765 // ARM RVCT tools have behavior outside of the ELF specification to try \r
766 // and make images smaller. If sh_addr is not aligned to sh_addralign \r
767 // then the section needs to preserve sh_addr MOD sh_addralign. \r
768 // Normally doing nothing here works great.\r
769 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
770 }\r
771 }\r
772 \r
773 /* Relocate entry. */\r
774 if ((Ehdr->e_entry >= shdr->sh_addr) &&\r
775 (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {\r
776 CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;\r
777 }\r
778 CoffSectionsOffset[i] = CoffOffset;\r
779 CoffOffset += shdr->sh_size;\r
780 }\r
781 }\r
782\r
783 if (Ehdr->e_machine != EM_ARM) {\r
784 CoffOffset = CoffAlign(CoffOffset);\r
785 }\r
786\r
787 //\r
788 // Then data sections.\r
789 //\r
790 DataOffset = CoffOffset;\r
791 for (i = 0; i < Ehdr->e_shnum; i++) {\r
792 Elf_Shdr *shdr = GetShdrByIndex(i);\r
793 if (IsDataShdr(shdr)) {\r
794 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
795 // the alignment field is valid\r
796 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
797 // if the section address is aligned we must align PE/COFF \r
798 CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
799 } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
800 // ARM RVCT tools have behavior outside of the ELF specification to try \r
801 // and make images smaller. If sh_addr is not aligned to sh_addralign \r
802 // then the section needs to preserve sh_addr MOD sh_addralign. \r
803 // Normally doing nothing here works great.\r
804 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
805 }\r
806 }\r
30fdf114
LG
807 CoffSectionsOffset[i] = CoffOffset;\r
808 CoffOffset += shdr->sh_size;\r
809 }\r
810 }\r
811 CoffOffset = CoffAlign(CoffOffset);\r
812\r
b303ea72
LG
813 //\r
814 // The HII resource sections.\r
815 //\r
816 HiiRsrcOffset = CoffOffset;\r
817 for (i = 0; i < Ehdr->e_shnum; i++) {\r
818 Elf_Shdr *shdr = GetShdrByIndex(i);\r
819 if (IsHiiRsrcShdr(shdr)) {\r
820 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {\r
821 // the alignment field is valid\r
822 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {\r
823 // if the section address is aligned we must align PE/COFF \r
824 CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);\r
825 } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {\r
826 // ARM RVCT tools have behavior outside of the ELF specification to try \r
827 // and make images smaller. If sh_addr is not aligned to sh_addralign \r
828 // then the section needs to preserve sh_addr MOD sh_addralign. \r
829 // Normally doing nothing here works great.\r
830 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");\r
831 }\r
832 }\r
a709adfa
LG
833 if (shdr->sh_size != 0) {\r
834 CoffSectionsOffset[i] = CoffOffset;\r
835 CoffOffset += shdr->sh_size;\r
b303ea72 836 CoffOffset = CoffAlign(CoffOffset);\r
a709adfa 837 SetHiiResourceHeader ((UINT8*) Ehdr + shdr->sh_offset, HiiRsrcOffset);\r
b303ea72
LG
838 }\r
839 break;\r
840 }\r
841 }\r
842\r
30fdf114
LG
843 RelocOffset = CoffOffset;\r
844\r
845 //\r
846 // Allocate base Coff file. Will be expanded later for relocations.\r
847 //\r
848 CoffFile = (UINT8 *)malloc(CoffOffset);\r
849 memset(CoffFile, 0, CoffOffset);\r
850\r
851 //\r
852 // Fill headers.\r
853 //\r
854 DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;\r
855 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;\r
856 DosHdr->e_lfanew = NtHdrOffset;\r
857\r
858 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset);\r
859\r
860 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;\r
861\r
862 switch (Ehdr->e_machine) {\r
863 case EM_386:\r
864 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
865 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
866 break;\r
867 case EM_X86_64:\r
868 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;\r
869 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
870 break;\r
871 case EM_IA_64:\r
872 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;\r
873 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
874 break;\r
875 case EM_ARM:\r
876 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;\r
877 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
878 break;\r
879 default:\r
880 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);\r
881 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;\r
882 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
883 }\r
884\r
885 NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;\r
fd171542 886 NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL);\r
52302d4d 887 mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp;\r
30fdf114
LG
888 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
889 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;\r
890 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);\r
891 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE\r
892 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED\r
893 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED\r
894 | EFI_IMAGE_FILE_32BIT_MACHINE;\r
895\r
896 NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset;\r
897 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;\r
898 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;\r
899 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;\r
900\r
901 NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset;\r
902\r
903 NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset;\r
904 NtHdr->Pe32.OptionalHeader.ImageBase = 0;\r
905 NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment;\r
906 NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment;\r
907 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;\r
908\r
909 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset;\r
910 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;\r
911\r
912 //\r
913 // Section headers.\r
914 //\r
915 if ((DataOffset - TextOffset) > 0) {\r
916 CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,\r
917 EFI_IMAGE_SCN_CNT_CODE\r
918 | EFI_IMAGE_SCN_MEM_EXECUTE\r
919 | EFI_IMAGE_SCN_MEM_READ);\r
920 } else {\r
921 // Don't make a section of size 0. \r
922 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
923 }\r
924\r
b303ea72
LG
925 if ((HiiRsrcOffset - DataOffset) > 0) {\r
926 CreateSectionHeader (".data", DataOffset, HiiRsrcOffset - DataOffset,\r
30fdf114
LG
927 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
928 | EFI_IMAGE_SCN_MEM_WRITE\r
929 | EFI_IMAGE_SCN_MEM_READ);\r
930 } else {\r
931 // Don't make a section of size 0. \r
932 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
933 }\r
b303ea72
LG
934\r
935 if ((RelocOffset - HiiRsrcOffset) > 0) {\r
936 CreateSectionHeader (".rsrc", HiiRsrcOffset, RelocOffset - HiiRsrcOffset,\r
937 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
938 | EFI_IMAGE_SCN_MEM_READ);\r
939\r
a709adfa 940 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = RelocOffset - HiiRsrcOffset;\r
b303ea72 941 NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = HiiRsrcOffset;\r
b303ea72
LG
942 } else {\r
943 // Don't make a section of size 0. \r
944 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
945 }\r
946\r
30fdf114
LG
947}\r
948\r
949VOID\r
950WriteSections(\r
951 int (*Filter)(Elf_Shdr *)\r
952 )\r
953{\r
954 UINT32 Idx;\r
955 Elf_Shdr *SecShdr;\r
956 UINT32 SecOffset;\r
957\r
958 //\r
959 // First: copy sections.\r
960 //\r
961 for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
962 Elf_Shdr *Shdr = GetShdrByIndex(Idx);\r
963 if ((*Filter)(Shdr)) {\r
964 switch (Shdr->sh_type) {\r
965 case SHT_PROGBITS:\r
966 /* Copy. */\r
967 memcpy(CoffFile + CoffSectionsOffset[Idx],\r
968 (UINT8*)Ehdr + Shdr->sh_offset,\r
969 Shdr->sh_size);\r
970 break;\r
971 \r
972 case SHT_NOBITS:\r
973 memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);\r
974 break;\r
975 \r
976 default:\r
977 //\r
978 // Ignore for unkown section type.\r
979 //\r
fd171542 980 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type);\r
30fdf114
LG
981 break;\r
982 }\r
983 }\r
984 }\r
985\r
986 //\r
987 // Second: apply relocations.\r
988 //\r
989 for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {\r
990 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);\r
991 if (RelShdr->sh_type != SHT_REL)\r
992 continue;\r
993 SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
994 SecOffset = CoffSectionsOffset[RelShdr->sh_info];\r
995 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {\r
996 UINT32 RelIdx;\r
997 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);\r
998 UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;\r
999\r
1000 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
1001 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
1002 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);\r
1003 Elf_Shdr *SymShdr;\r
1004 UINT8 *Targ;\r
1005\r
1006 if (Sym->st_shndx == SHN_UNDEF\r
1007 || Sym->st_shndx == SHN_ABS\r
1008 || Sym->st_shndx > Ehdr->e_shnum) {\r
1009 Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);\r
1010 }\r
1011 SymShdr = GetShdrByIndex(Sym->st_shndx);\r
1012\r
1013 //\r
1014 // Note: r_offset in a memory address.\r
1015 // Convert it to a pointer in the coff file.\r
1016 //\r
1017 Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);\r
1018\r
1019 if (Ehdr->e_machine == EM_386) {\r
1020 switch (ELF_R_TYPE(Rel->r_info)) {\r
1021 case R_386_NONE:\r
1022 break;\r
1023 case R_386_32:\r
1024 //\r
1025 // Absolute relocation.\r
1026 //\r
1027 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr\r
1028 + CoffSectionsOffset[Sym->st_shndx];\r
1029 break;\r
1030 case R_386_PC32:\r
1031 //\r
1032 // Relative relocation: Symbol - Ip + Addend\r
1033 //\r
1034 *(UINT32 *)Targ = *(UINT32 *)Targ\r
1035 + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)\r
1036 - (SecOffset - SecShdr->sh_addr);\r
1037 break;\r
1038 default:\r
636f2be6 1039 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
30fdf114
LG
1040 }\r
1041 } else if (Ehdr->e_machine == EM_ARM) {\r
1042 switch (ELF32_R_TYPE(Rel->r_info)) {\r
1043 case R_ARM_RBASE: // No relocation - no action required\r
636f2be6
LG
1044 \r
1045 // Thease are all PC-relative relocations and don't require modification\r
1046 case R_ARM_PC24: \r
1047 case R_ARM_XPC25: \r
1048 case R_ARM_THM_PC22:\r
1049 case R_ARM_THM_JUMP19:\r
1050 case R_ARM_CALL:\r
30fdf114 1051 break;\r
636f2be6 1052\r
30fdf114
LG
1053 case R_ARM_ABS32:\r
1054 case R_ARM_RABS32:\r
1055 //\r
1056 // Absolute relocation.\r
1057 //\r
1058 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];\r
1059 break;\r
1060 default:\r
636f2be6 1061 Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
30fdf114
LG
1062 }\r
1063 }\r
1064 }\r
1065 }\r
1066 }\r
1067}\r
1068\r
1069VOID\r
1070CoffAddFixupEntry(\r
1071 UINT16 Val\r
1072 )\r
1073{\r
1074 *CoffEntryRel = Val;\r
1075 CoffEntryRel++;\r
1076 CoffBaseRel->SizeOfBlock += 2;\r
1077 CoffOffset += 2;\r
1078}\r
1079\r
1080VOID\r
1081CoffAddFixup(\r
1082 UINT32 Offset,\r
1083 UINT8 Type\r
1084 )\r
1085{\r
1086 if (CoffBaseRel == NULL\r
1087 || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {\r
1088 if (CoffBaseRel != NULL) {\r
1089 //\r
1090 // Add a null entry (is it required ?)\r
1091 //\r
1092 CoffAddFixupEntry (0);\r
1093 //\r
1094 // Pad for alignment.\r
1095 //\r
1096 if (CoffOffset % 4 != 0)\r
1097 CoffAddFixupEntry (0);\r
1098 }\r
1099\r
1100 CoffFile = realloc\r
1101 (CoffFile,\r
1102 CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
1103 memset(CoffFile + CoffOffset, 0,\r
1104 sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);\r
1105\r
1106 CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);\r
1107 CoffBaseRel->VirtualAddress = Offset & ~0xfff;\r
1108 CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);\r
1109\r
1110 CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);\r
1111 CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);\r
1112 }\r
1113\r
1114 //\r
1115 // Fill the entry.\r
1116 //\r
fd171542 1117 CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff)));\r
30fdf114
LG
1118}\r
1119\r
1120\r
1121Elf_Phdr *\r
1122GetPhdrByIndex (\r
1123 UINT32 num\r
1124 )\r
1125{\r
1126 if (num >= Ehdr->e_phnum) {\r
1127 return NULL;\r
1128 }\r
1129 \r
1130 return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize);\r
1131}\r
1132\r
1133\r
1134VOID\r
636f2be6 1135WriteRelocations (\r
30fdf114
LG
1136 VOID\r
1137 )\r
1138{\r
1139 UINT32 Index;\r
1140 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1141 EFI_IMAGE_DATA_DIRECTORY *Dir;\r
1142 BOOLEAN FoundRelocations;\r
1143 Elf_Dyn *Dyn;\r
1144 Elf_Rel *Rel;\r
1145 UINTN RelElementSize;\r
1146 UINTN RelSize;\r
1147 UINTN RelOffset;\r
1148 UINTN K;\r
1149 UINT8 *Targ;\r
1150 Elf32_Phdr *DynamicSegment;\r
1151 Elf32_Phdr *TargetSegment;\r
1152\r
1153 for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {\r
1154 Elf_Shdr *RelShdr = GetShdrByIndex(Index);\r
1155 if (RelShdr->sh_type == SHT_REL) {\r
1156 Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);\r
1157 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {\r
1158 UINT32 RelIdx;\r
1159 FoundRelocations = TRUE;\r
1160 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {\r
1161 Elf_Rel *Rel = (Elf_Rel *)\r
1162 ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);\r
1163 \r
1164 if (Ehdr->e_machine == EM_386) { \r
1165 switch (ELF_R_TYPE(Rel->r_info)) {\r
1166 case R_386_NONE:\r
1167 case R_386_PC32:\r
1168 break;\r
1169 case R_386_32:\r
1170 CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]\r
1171 + (Rel->r_offset - SecShdr->sh_addr),\r
1172 EFI_IMAGE_REL_BASED_HIGHLOW);\r
1173 break;\r
1174 default:\r
636f2be6 1175 Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info));\r
30fdf114
LG
1176 }\r
1177 } else if (Ehdr->e_machine == EM_ARM) {\r
1178 switch (ELF32_R_TYPE(Rel->r_info)) {\r
636f2be6
LG
1179 case R_ARM_RBASE: // No relocation - no action required\r
1180 \r
1181 // Thease are all PC-relative relocations and don't require modification\r
30fdf114
LG
1182 case R_ARM_PC24:\r
1183 case R_ARM_XPC25:\r
636f2be6
LG
1184 case R_ARM_THM_PC22:\r
1185 case R_ARM_THM_JUMP19:\r
1186 case R_ARM_CALL:\r
30fdf114
LG
1187 break;\r
1188 case R_ARM_ABS32:\r
1189 case R_ARM_RABS32:\r
1190 CoffAddFixup (\r
1191 CoffSectionsOffset[RelShdr->sh_info]\r
1192 + (Rel->r_offset - SecShdr->sh_addr),\r
1193 EFI_IMAGE_REL_BASED_HIGHLOW\r
1194 );\r
1195 break;\r
636f2be6
LG
1196\r
1197 default:\r
1198 Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info));\r
30fdf114
LG
1199 }\r
1200 } else {\r
fd171542 1201 Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) Ehdr->e_machine);\r
30fdf114
LG
1202 }\r
1203 }\r
1204 }\r
1205 }\r
1206 }\r
1207\r
1208 if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) {\r
1209 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */\r
1210\r
1211 for (Index = 0; Index < Ehdr->e_phnum; Index++) {\r
1212 RelElementSize = 0;\r
1213 RelSize = 0;\r
1214 RelOffset = 0;\r
1215\r
1216 DynamicSegment = GetPhdrByIndex (Index);\r
1217\r
1218 if (DynamicSegment->p_type == PT_DYNAMIC) {\r
1219 Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset);\r
1220\r
1221 while (Dyn->d_tag != DT_NULL) {\r
1222 switch (Dyn->d_tag) {\r
1223 case DT_REL:\r
1224 RelOffset = Dyn->d_un.d_val;\r
1225 break;\r
1226\r
1227 case DT_RELSZ:\r
1228 RelSize = Dyn->d_un.d_val;\r
1229 break;\r
1230\r
1231 case DT_RELENT:\r
1232 RelElementSize = Dyn->d_un.d_val;\r
1233 break;\r
636f2be6
LG
1234\r
1235 default:\r
1236 break;\r
30fdf114
LG
1237 }\r
1238 Dyn++;\r
1239 }\r
1240 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {\r
1241 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);\r
1242 }\r
1243\r
1244 for (K = 0; K < RelSize; K += RelElementSize) {\r
1245\r
636f2be6
LG
1246 if (DynamicSegment->p_paddr == 0) {\r
1247 // This seems to be how it works on armcc???? Have the email in to find out?\r
1248 Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K);\r
1249 } else {\r
1250 // This is how it reads in the ELF specification\r
1251 Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + RelOffset + K);\r
1252 }\r
30fdf114
LG
1253\r
1254 switch (ELF32_R_TYPE (Rel->r_info)) {\r
1255 case R_ARM_RBASE:\r
1256 break;\r
1257 case R_ARM_RABS32:\r
1258 TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);\r
1259\r
1260 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.\r
1261 Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;\r
1262\r
1263 *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];\r
1264\r
1265 CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);\r
1266 break;\r
1267 default:\r
636f2be6
LG
1268 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info));\r
1269 break;\r
30fdf114
LG
1270 }\r
1271 }\r
1272 break;\r
1273 }\r
1274 }\r
1275 }\r
1276\r
1277 //\r
1278 // Pad by adding empty entries.\r
1279 //\r
1280 while (CoffOffset & (CoffAlignment - 1)) {\r
1281 CoffAddFixupEntry(0);\r
1282 }\r
1283\r
1284\r
1285 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1286 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1287 Dir->Size = CoffOffset - RelocOffset;\r
1288 if (Dir->Size == 0) {\r
1289 // If no relocations, null out the directory entry and don't add the .reloc section\r
1290 Dir->VirtualAddress = 0;\r
1291 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1292 } else {\r
1293 Dir->VirtualAddress = RelocOffset;\r
1294 CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,\r
1295 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1296 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1297 | EFI_IMAGE_SCN_MEM_READ);\r
1298 }\r
1299\r
1300}\r
1301\r
1302VOID\r
1303WriteDebug(\r
1304 VOID\r
1305 )\r
1306{\r
1307 UINT32 Len;\r
1308 UINT32 DebugOffset;\r
1309 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1310 EFI_IMAGE_DATA_DIRECTORY *DataDir;\r
1311 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;\r
1312 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;\r
1313\r
1314 Len = strlen(mInImageName) + 1;\r
1315 DebugOffset = CoffOffset;\r
1316\r
1317 CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)\r
1318 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)\r
1319 + Len;\r
1320 CoffOffset = CoffAlign(CoffOffset);\r
1321\r
1322 CoffFile = realloc(CoffFile, CoffOffset);\r
1323 memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);\r
1324\r
1325 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);\r
1326 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;\r
1327 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;\r
1328 Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1329 Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
1330\r
1331 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);\r
1332 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;\r
1333 strcpy ((char *)(Nb10 + 1), mInImageName);\r
1334\r
1335\r
1336 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1337 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
1338 DataDir->VirtualAddress = DebugOffset;\r
1339 DataDir->Size = CoffOffset - DebugOffset;\r
1340 if (DataDir->Size == 0) {\r
1341 // If no debug, null out the directory entry and don't add the .debug section\r
1342 DataDir->VirtualAddress = 0;\r
1343 NtHdr->Pe32.FileHeader.NumberOfSections--;\r
1344 } else {\r
1345 DataDir->VirtualAddress = DebugOffset;\r
1346 CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,\r
1347 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA\r
1348 | EFI_IMAGE_SCN_MEM_DISCARDABLE\r
1349 | EFI_IMAGE_SCN_MEM_READ);\r
1350\r
1351 }\r
1352}\r
1353\r
1354VOID\r
1355ConvertElf (\r
1356 UINT8 **FileBuffer,\r
1357 UINT32 *FileLength\r
1358 )\r
1359{\r
1360 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;\r
1361\r
1362 //\r
1363 // Check header, read section table.\r
1364 //\r
1365 Ehdr = (Elf32_Ehdr*)*FileBuffer;\r
1366 if (!CheckElfHeader())\r
1367 return;\r
1368\r
1369 VerboseMsg ("Check Efl Image Header");\r
1370 //\r
1371 // Compute sections new address.\r
1372 //\r
58e4d800 1373 \r
30fdf114
LG
1374 ScanSections();\r
1375\r
1376 VerboseMsg ("Compute sections new address.");\r
1377\r
1378 //\r
1379 // Write and relocate sections.\r
1380 //\r
1381 WriteSections(IsTextShdr);\r
1382 WriteSections(IsDataShdr);\r
a709adfa 1383 WriteSections(IsHiiRsrcShdr);\r
30fdf114
LG
1384 VerboseMsg ("Write and relocate sections.");\r
1385\r
1386 //\r
1387 // Translate and write relocations.\r
1388 //\r
1389 WriteRelocations();\r
1390 VerboseMsg ("Translate and write relocations.");\r
1391\r
1392 //\r
1393 // Write debug info.\r
1394 //\r
1395 WriteDebug();\r
1396 VerboseMsg ("Write debug info.");\r
1397\r
1398 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);\r
1399 NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset;\r
1400\r
1401 //\r
1402 // Replace.\r
1403 //\r
1404 free(*FileBuffer);\r
1405 *FileBuffer = CoffFile;\r
1406 *FileLength = CoffOffset;\r
1407\r
1408 //\r
1409 // Free memory space\r
1410 //\r
1411 if (CoffSectionsOffset != NULL) {\r
1412 free (CoffSectionsOffset);\r
1413 }\r
1414}\r
1415\r
a709adfa
LG
1416\r
1417EFI_IMAGE_OPTIONAL_HEADER_UNION *\r
1418GetPeCoffHeader (\r
1419 void *Data\r
1420 )\r
1421{\r
1422 EFI_IMAGE_DOS_HEADER *DosHdr;\r
1423 EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;\r
1424\r
1425 //\r
1426 // Read the dos & pe hdrs of the image\r
1427 //\r
1428 DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;\r
1429 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
1430 // NO DOS header, check for PE/COFF header\r
1431 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);\r
1432 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1433 return NULL;\r
1434 }\r
1435 } else {\r
1436\r
1437 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);\r
1438 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
1439 return NULL;\r
1440 }\r
1441 }\r
1442 \r
1443 return PeHdr;\r
1444}\r
1445\r
1446void\r
1447PeCoffConvertImageToXip (\r
1448 UINT8 **FileBuffer,\r
1449 UINT32 *FileLength\r
1450 )\r
1451{\r
1452 EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;\r
1453 EFI_IMAGE_OPTIONAL_HEADER_UNION *NewPeHdr;\r
1454 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1455 UINTN TotalNecessaryFileSize;\r
1456 UINTN SectionSize;\r
1457 UINT8 *XipFile;\r
1458 UINT32 XipLength;\r
1459 UINTN Index;\r
1460 UINTN FirstSectionOffset;\r
1461 BOOLEAN ConversionNeeded;\r
1462\r
1463 PeHdr = GetPeCoffHeader ((void *) *FileBuffer);\r
1464 if (PeHdr == NULL) {\r
1465 return;\r
1466 }\r
1467 \r
1468 if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {\r
1469 //\r
1470 // The only reason to expand zero fill sections is to make them compatible with XIP images.\r
1471 // If SectionAlignment is not equal to FileAlginment then it is not an XIP type image.\r
1472 //\r
1473 return;\r
1474 }\r
1475\r
1476 //\r
1477 // Calculate size of XIP file, and determine if the conversion is needed.\r
1478 //\r
1479 ConversionNeeded = FALSE;\r
1480 XipLength = 0;\r
1481 FirstSectionOffset = *FileLength;\r
1482 TotalNecessaryFileSize = 0;\r
1483 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
1484 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1485 SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);\r
1486 TotalNecessaryFileSize += SectionSize;\r
1487 if (SectionSize > 0) {\r
1488 FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);\r
1489 XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);\r
1490 if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {\r
1491 ConversionNeeded = TRUE;\r
1492 }\r
1493 }\r
1494 if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {\r
1495 ConversionNeeded = TRUE;\r
1496 }\r
1497 }\r
1498\r
1499 if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
1500 //\r
1501 // If one of the sections should be loaded to an offset overlapping with\r
1502 // the executable header, then it cannot be made into an XIP image.\r
1503 //\r
1504 VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");\r
1505 VerboseMsg ("of section data with the executable header.");\r
1506 return;\r
1507 }\r
1508\r
1509 if (FirstSectionOffset == *FileLength) {\r
1510 //\r
1511 // If we never found a section with a non-zero size, then we\r
1512 // skip the conversion.\r
1513 //\r
1514 return;\r
1515 }\r
1516\r
1517 TotalNecessaryFileSize += FirstSectionOffset;\r
1518\r
1519 if (!ConversionNeeded) {\r
1520 return;\r
1521 }\r
1522\r
1523 if (XipLength > (2 * TotalNecessaryFileSize)) {\r
1524 VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");\r
1525 VerboseMsg ("The image linking process may have left unused memory ranges.");\r
1526 }\r
1527\r
1528 if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {\r
1529 //\r
1530 // This field is obsolete and should be zero\r
1531 //\r
1532 PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;\r
1533 }\r
1534\r
1535 //\r
1536 // Allocate the extra space that we need to grow the image\r
1537 //\r
1538 XipFile = malloc (XipLength);\r
1539 memset (XipFile, 0, XipLength);\r
1540\r
1541 //\r
1542 // Copy the file headers\r
1543 //\r
1544 memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);\r
1545\r
1546 NewPeHdr = GetPeCoffHeader ((void *)XipFile);\r
1547 if (NewPeHdr == NULL) {\r
1548 free (XipFile);\r
1549 return;\r
1550 }\r
1551\r
1552 //\r
1553 // Copy the section data over to the appropriate XIP offsets\r
1554 //\r
1555 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
1556 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1557 if (SectionHeader->SizeOfRawData > 0) {\r
1558 memcpy (\r
1559 XipFile + SectionHeader->VirtualAddress,\r
1560 *FileBuffer + SectionHeader->PointerToRawData,\r
1561 SectionHeader->SizeOfRawData\r
1562 );\r
1563 }\r
1564 SectionHeader->SizeOfRawData = SectionHeader->Misc.VirtualSize;\r
1565 SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;\r
1566 }\r
1567\r
1568 free (*FileBuffer);\r
1569 *FileLength = XipLength;\r
1570 *FileBuffer = XipFile;\r
1571}\r
1572\r
1573UINT8 *\r
1574CreateHiiResouceSectionHeader (\r
1575 UINT32 *pSectionHeaderSize, \r
1576 UINT32 HiiDataSize\r
1577 )\r
1578/*++\r
1579\r
1580Routine Description:\r
1581\r
1582 Create COFF resource section header\r
1583\r
1584Arguments:\r
1585\r
1586 pSectionHeaderSize - Pointer to section header size.\r
1587 HiiDataSize - Size of the total HII data in section.\r
1588\r
1589Returns:\r
1590 The created section header buffer.\r
1591\r
1592--*/\r
1593{\r
1594 UINT32 HiiSectionHeaderSize;\r
1595 UINT32 HiiSectionOffset;\r
1596 UINT8 *HiiSectionHeader;\r
1597 EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;\r
1598 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeResourceDirectoryEntry;\r
1599 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameResourceDirectoryEntry;\r
1600 EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LanguageResourceDirectoryEntry;\r
1601 EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;\r
1602 EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;\r
1603\r
1604 //\r
1605 // Calculate the total size for the resource header (include Type, Name and Language)\r
1606 // then allocate memory for the resource header.\r
1607 //\r
1608 HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)) \r
1609 + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16)) \r
1610 + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
1611 HiiSectionHeader = malloc (HiiSectionHeaderSize);\r
1612 memset (HiiSectionHeader, 0, HiiSectionHeaderSize);\r
1613\r
1614 HiiSectionOffset = 0;\r
1615 //\r
1616 // Create Type entry \r
1617 //\r
1618 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1619 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1620 ResourceDirectory->NumberOfNamedEntries = 1;\r
1621 TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1622 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1623 TypeResourceDirectoryEntry->u1.s.NameIsString = 1;\r
1624 TypeResourceDirectoryEntry->u2.s.DataIsDirectory = 1;\r
1625 TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
1626 //\r
1627 // Create Name entry\r
1628 //\r
1629 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1630 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1631 ResourceDirectory->NumberOfNamedEntries = 1;\r
1632 NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1633 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1634 NameResourceDirectoryEntry->u1.s.NameIsString = 1;\r
1635 NameResourceDirectoryEntry->u2.s.DataIsDirectory = 1;\r
1636 NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;\r
1637 //\r
1638 // Create Language entry\r
1639 //\r
1640 ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);\r
1641 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);\r
1642 ResourceDirectory->NumberOfNamedEntries = 1;\r
1643 LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1644 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);\r
1645 LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;\r
1646 //\r
1647 // Create string entry for Type\r
1648 //\r
1649 TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1650 ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1651 ResourceDirectoryString->Length = 3;\r
1652 ResourceDirectoryString->String[0] = L'H';\r
1653 ResourceDirectoryString->String[1] = L'I';\r
1654 ResourceDirectoryString->String[2] = L'I';\r
1655 HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1656 //\r
1657 // Create string entry for Name\r
1658 //\r
1659 NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1660 ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1661 ResourceDirectoryString->Length = 3;\r
1662 ResourceDirectoryString->String[0] = L'E';\r
1663 ResourceDirectoryString->String[1] = L'F';\r
1664 ResourceDirectoryString->String[2] = L'I';\r
1665 HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1666 //\r
1667 // Create string entry for Language\r
1668 //\r
1669 LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;\r
1670 ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);\r
1671 ResourceDirectoryString->Length = 3;\r
1672 ResourceDirectoryString->String[0] = L'B';\r
1673 ResourceDirectoryString->String[1] = L'I';\r
1674 ResourceDirectoryString->String[2] = L'N';\r
1675 HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);\r
1676 //\r
1677 // Create Leaf data\r
1678 //\r
1679 LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;\r
1680 ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);\r
1681 HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);\r
1682 ResourceDataEntry->OffsetToData = HiiSectionOffset;\r
1683 ResourceDataEntry->Size = HiiDataSize;\r
1684\r
1685 *pSectionHeaderSize = HiiSectionHeaderSize;\r
1686 return HiiSectionHeader;\r
1687}\r
1688\r
52302d4d
LG
1689EFI_STATUS\r
1690RebaseImageRead (\r
1691 IN VOID *FileHandle,\r
1692 IN UINTN FileOffset,\r
1693 IN OUT UINT32 *ReadSize,\r
1694 OUT VOID *Buffer\r
1695 )\r
1696/*++\r
1697\r
1698Routine Description:\r
1699\r
1700 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
1701\r
1702Arguments:\r
1703\r
1704 FileHandle - The handle to the PE/COFF file\r
1705\r
1706 FileOffset - The offset, in bytes, into the file to read\r
1707\r
1708 ReadSize - The number of bytes to read from the file starting at FileOffset\r
1709\r
1710 Buffer - A pointer to the buffer to read the data into.\r
1711\r
1712Returns:\r
1713\r
1714 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
1715\r
1716--*/\r
1717{\r
1718 CHAR8 *Destination8;\r
1719 CHAR8 *Source8;\r
1720 UINT32 Length;\r
1721\r
1722 Destination8 = Buffer;\r
1723 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
1724 Length = *ReadSize;\r
1725 while (Length--) {\r
1726 *(Destination8++) = *(Source8++);\r
1727 }\r
1728\r
1729 return EFI_SUCCESS;\r
1730}\r
1731\r
1732EFI_STATUS\r
1733SetAddressToSectionHeader (\r
1734 IN CHAR8 *FileName,\r
1735 IN OUT UINT8 *FileBuffer,\r
1736 IN UINT64 NewPe32BaseAddress\r
1737 )\r
1738/*++\r
1739\r
1740Routine Description:\r
1741\r
1742 Set new base address into the section header of PeImage\r
1743\r
1744Arguments:\r
1745\r
1746 FileName - Name of file\r
1747 FileBuffer - Pointer to PeImage.\r
1748 NewPe32BaseAddress - New Base Address for PE image.\r
1749\r
1750Returns:\r
1751\r
1752 EFI_SUCCESS Set new base address into this image successfully.\r
1753\r
1754--*/\r
1755{\r
1756 EFI_STATUS Status;\r
1757 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1758 UINTN Index;\r
1759 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
1760 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1761\r
1762 //\r
1763 // Initialize context\r
1764 //\r
1765 memset (&ImageContext, 0, sizeof (ImageContext));\r
1766 ImageContext.Handle = (VOID *) FileBuffer;\r
1767 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
1768 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
1769 if (EFI_ERROR (Status)) {\r
1770 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
1771 return Status;\r
1772 }\r
1773\r
1774 if (ImageContext.RelocationsStripped) {\r
1775 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
1776 return Status; \r
1777 }\r
1778\r
1779 //\r
1780 // Get PeHeader pointer\r
1781 //\r
1782 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
1783\r
1784 //\r
1785 // Get section header list\r
1786 //\r
1787 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
1788 (UINTN) ImgHdr +\r
1789 sizeof (UINT32) + \r
1790 sizeof (EFI_IMAGE_FILE_HEADER) + \r
1791 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
1792 );\r
1793\r
1794 //\r
1795 // Set base address into the first section header that doesn't point to code section.\r
1796 //\r
1797 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1798 if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
1799 *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;\r
1800 break;\r
1801 }\r
1802 }\r
1803\r
1804 //\r
1805 // No available section header is found.\r
1806 //\r
1807 if (Index == ImgHdr->Pe32.FileHeader.NumberOfSections) {\r
1808 return EFI_NOT_FOUND;\r
1809 }\r
1810 \r
1811 //\r
1812 // BaseAddress is set to section header.\r
1813 //\r
1814 return EFI_SUCCESS;\r
1815}\r
1816\r
1817EFI_STATUS\r
1818RebaseImage (\r
1819 IN CHAR8 *FileName,\r
1820 IN OUT UINT8 *FileBuffer,\r
1821 IN UINT64 NewPe32BaseAddress\r
1822 )\r
1823/*++\r
1824\r
1825Routine Description:\r
1826\r
1827 Set new base address into PeImage, and fix up PeImage based on new address.\r
1828\r
1829Arguments:\r
1830\r
1831 FileName - Name of file\r
1832 FileBuffer - Pointer to PeImage.\r
1833 NewPe32BaseAddress - New Base Address for PE image.\r
1834\r
1835Returns:\r
1836\r
1837 EFI_INVALID_PARAMETER - BaseAddress is not valid.\r
1838 EFI_SUCCESS - Update PeImage is correctly.\r
1839\r
1840--*/\r
1841{\r
1842 EFI_STATUS Status;\r
1843 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
1844 UINTN Index;\r
1845 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
1846 UINT8 *MemoryImagePointer;\r
1847 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1848\r
1849 //\r
1850 // Initialize context\r
1851 //\r
1852 memset (&ImageContext, 0, sizeof (ImageContext));\r
1853 ImageContext.Handle = (VOID *) FileBuffer;\r
1854 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;\r
1855 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
1856 if (EFI_ERROR (Status)) {\r
1857 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);\r
1858 return Status;\r
1859 }\r
1860\r
1861 if (ImageContext.RelocationsStripped) {\r
1862 Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);\r
1863 return Status; \r
1864 }\r
1865\r
1866 //\r
1867 // Get PeHeader pointer\r
1868 //\r
1869 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);\r
1870\r
1871 //\r
1872 // Load and Relocate Image Data\r
1873 //\r
1874 MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
1875 if (MemoryImagePointer == NULL) {\r
1876 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);\r
1877 return EFI_OUT_OF_RESOURCES;\r
1878 }\r
1879 memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);\r
1880 ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));\r
1881\r
1882 Status = PeCoffLoaderLoadImage (&ImageContext);\r
1883 if (EFI_ERROR (Status)) {\r
1884 Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);\r
1885 free ((VOID *) MemoryImagePointer);\r
1886 return Status;\r
1887 }\r
1888\r
1889 ImageContext.DestinationAddress = NewPe32BaseAddress;\r
1890 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
1891 if (EFI_ERROR (Status)) {\r
1892 Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);\r
1893 free ((VOID *) MemoryImagePointer);\r
1894 return Status;\r
1895 }\r
1896\r
1897 //\r
1898 // Copy Relocated data to raw image file.\r
1899 //\r
1900 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
1901 (UINTN) ImgHdr +\r
1902 sizeof (UINT32) + \r
1903 sizeof (EFI_IMAGE_FILE_HEADER) + \r
1904 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
1905 );\r
1906\r
1907 for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
1908 CopyMem (\r
1909 FileBuffer + SectionHeader->PointerToRawData, \r
1910 (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), \r
1911 SectionHeader->SizeOfRawData\r
1912 );\r
1913 }\r
1914\r
1915 free ((VOID *) MemoryImagePointer);\r
1916\r
1917 //\r
1918 // Update Image Base Address\r
1919 //\r
1920 if ((ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (ImgHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\r
1921 ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;\r
1922 } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
1923 ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;\r
1924 } else {\r
1925 Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",\r
1926 ImgHdr->Pe32.OptionalHeader.Magic,\r
1927 FileName\r
1928 );\r
1929 return EFI_ABORTED;\r
1930 }\r
1931\r
1932 //\r
1933 // Set new base address into section header\r
1934 //\r
1935 Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);\r
1936\r
1937 return Status;\r
1938}\r
1939\r
30fdf114
LG
1940int\r
1941main (\r
1942 int argc,\r
1943 char *argv[]\r
1944 )\r
1945/*++\r
1946\r
1947Routine Description:\r
1948\r
1949 Main function.\r
1950\r
1951Arguments:\r
1952\r
1953 argc - Number of command line parameters.\r
1954 argv - Array of pointers to command line parameter strings.\r
1955\r
1956Returns:\r
1957 STATUS_SUCCESS - Utility exits successfully.\r
1958 STATUS_ERROR - Some error occurred during execution.\r
1959\r
1960--*/\r
1961{\r
1962 UINT32 Type;\r
1963 UINT32 InputFileNum;\r
1964 CHAR8 **InputFileName;\r
1965 char *OutImageName;\r
1966 char *ModuleType;\r
1967 CHAR8 *TimeStamp;\r
1968 UINT32 OutImageType;\r
1969 FILE *fpIn;\r
1970 FILE *fpOut;\r
1971 FILE *fpInOut;\r
1972 UINT32 Data;\r
1973 UINT32 *DataPointer;\r
1974 UINT32 *OldDataPointer;\r
1975 UINT32 CheckSum;\r
1976 UINT32 Index;\r
1977 UINT32 Index1;\r
1978 UINT32 Index2;\r
1979 UINT64 Temp64;\r
1980 UINT32 MciAlignment;\r
1981 UINT8 MciPadValue;\r
1982 UINT32 AllignedRelocSize;\r
1983 UINT8 *FileBuffer;\r
1984 UINT32 FileLength;\r
1985 UINT8 *OutputFileBuffer;\r
1986 UINT32 OutputFileLength;\r
52302d4d
LG
1987 UINT8 *InputFileBuffer;\r
1988 UINT32 InputFileLength;\r
30fdf114
LG
1989 RUNTIME_FUNCTION *RuntimeFunction;\r
1990 UNWIND_INFO *UnwindInfo;\r
1991 STATUS Status;\r
1992 BOOLEAN ReplaceFlag;\r
1993 BOOLEAN KeepExceptionTableFlag;\r
1994 BOOLEAN KeepZeroPendingFlag;\r
1995 UINT64 LogLevel;\r
1996 EFI_TE_IMAGE_HEADER TEImageHeader;\r
1997 EFI_TE_IMAGE_HEADER *TeHdr;\r
1998 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
1999 EFI_IMAGE_DOS_HEADER *DosHdr;\r
2000 EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;\r
2001 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
2002 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
2003 EFI_IMAGE_DOS_HEADER BackupDosHdr;\r
2004 MICROCODE_IMAGE_HEADER *MciHeader;\r
b303ea72
LG
2005 UINT8 *HiiPackageListBuffer;\r
2006 UINT8 *HiiPackageDataPointer;\r
2007 EFI_GUID HiiPackageListGuid;\r
2008 EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader;\r
2009 EFI_HII_PACKAGE_HEADER HiiPackageHeader;\r
2010 EFI_IFR_FORM_SET IfrFormSet;\r
2011 UINT8 NumberOfFormPacakge;\r
2012 EFI_HII_PACKAGE_HEADER EndPackage;\r
a709adfa
LG
2013 UINT32 HiiSectionHeaderSize;\r
2014 UINT8 *HiiSectionHeader;\r
52302d4d
LG
2015 UINT64 NewBaseAddress;\r
2016 BOOLEAN NegativeAddr;\r
2017 FILE *ReportFile;\r
2018 CHAR8 *ReportFileName;\r
2019 UINTN FileLen;\r
636f2be6
LG
2020 time_t InputFileTime;\r
2021 time_t OutputFileTime;\r
2022 struct stat Stat_Buf;\r
30fdf114
LG
2023\r
2024 SetUtilityName (UTILITY_NAME);\r
2025\r
2026 //\r
2027 // Assign to fix compile warning\r
2028 //\r
52302d4d 2029 FileLen = 0;\r
30fdf114
LG
2030 InputFileNum = 0;\r
2031 InputFileName = NULL;\r
2032 mInImageName = NULL;\r
2033 OutImageName = NULL;\r
2034 ModuleType = NULL;\r
2035 OutImageType = FW_DUMMY_IMAGE;\r
2036 Type = 0;\r
2037 Status = STATUS_SUCCESS;\r
2038 FileBuffer = NULL;\r
2039 fpIn = NULL;\r
2040 fpOut = NULL;\r
2041 fpInOut = NULL;\r
2042 TimeStamp = NULL;\r
2043 MciAlignment = DEFAULT_MC_ALIGNMENT;\r
2044 MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE;\r
2045 FileLength = 0;\r
2046 MciHeader = NULL;\r
2047 CheckSum = 0;\r
2048 ReplaceFlag = FALSE;\r
2049 LogLevel = 0;\r
2050 OutputFileBuffer = NULL;\r
2051 OutputFileLength = 0;\r
52302d4d
LG
2052 InputFileBuffer = NULL;\r
2053 InputFileLength = 0;\r
30fdf114
LG
2054 Optional32 = NULL;\r
2055 Optional64 = NULL;\r
2056 KeepExceptionTableFlag = FALSE;\r
2057 KeepZeroPendingFlag = FALSE;\r
b303ea72
LG
2058 NumberOfFormPacakge = 0;\r
2059 HiiPackageListBuffer = NULL;\r
2060 HiiPackageDataPointer = NULL;\r
2061 EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
2062 EndPackage.Type = EFI_HII_PACKAGE_END;\r
2063 memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));\r
a709adfa
LG
2064 HiiSectionHeaderSize = 0;\r
2065 HiiSectionHeader = NULL;\r
52302d4d
LG
2066 NewBaseAddress = 0;\r
2067 NegativeAddr = FALSE;\r
636f2be6
LG
2068 InputFileTime = 0;\r
2069 OutputFileTime = 0;\r
30fdf114
LG
2070\r
2071 if (argc == 1) {\r
2072 Error (NULL, 0, 1001, "Missing options", "No input options.");\r
2073 Usage ();\r
2074 return STATUS_ERROR;\r
2075 }\r
2076\r
2077 argc --;\r
2078 argv ++;\r
2079\r
2080 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {\r
2081 Version ();\r
2082 Usage ();\r
2083 return STATUS_SUCCESS;\r
2084 }\r
2085\r
2086 if (stricmp (argv[0], "--version") == 0) {\r
2087 Version ();\r
2088 return STATUS_SUCCESS;\r
2089 }\r
2090\r
2091 while (argc > 0) {\r
2092 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {\r
2093 if (argv[1] == NULL || argv[1][0] == '-') {\r
2094 Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");\r
2095 goto Finish;\r
2096 }\r
2097 OutImageName = argv[1];\r
2098 argc -= 2;\r
2099 argv += 2;\r
2100 continue;\r
2101 }\r
2102\r
2103 if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {\r
2104 if (argv[1] == NULL || argv[1][0] == '-') {\r
2105 Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");\r
2106 goto Finish;\r
2107 }\r
2108 ModuleType = argv[1];\r
2109 if (OutImageType != FW_TE_IMAGE) {\r
2110 OutImageType = FW_EFI_IMAGE;\r
2111 }\r
2112 argc -= 2;\r
2113 argv += 2;\r
2114 continue;\r
2115 }\r
2116\r
2117 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {\r
2118 OutImageType = FW_RELOC_STRIPEED_IMAGE;\r
2119 argc --;\r
2120 argv ++;\r
2121 continue;\r
2122 }\r
2123\r
2124 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {\r
2125 OutImageType = FW_ACPI_IMAGE;\r
2126 argc --;\r
2127 argv ++;\r
2128 continue;\r
2129 }\r
2130\r
2131 if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {\r
2132 OutImageType = FW_TE_IMAGE;\r
2133 argc --;\r
2134 argv ++;\r
2135 continue;\r
2136 }\r
2137\r
2138 if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {\r
2139 OutImageType = DUMP_TE_HEADER;\r
2140 argc --;\r
2141 argv ++;\r
2142 continue;\r
2143 }\r
2144\r
2145 if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {\r
2146 OutImageType = FW_BIN_IMAGE;\r
2147 argc --;\r
2148 argv ++;\r
2149 continue;\r
2150 }\r
2151\r
2152 if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {\r
2153 OutImageType = FW_ZERO_DEBUG_IMAGE;\r
2154 argc --;\r
2155 argv ++;\r
2156 continue;\r
2157 }\r
2158\r
2159 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {\r
2160 OutImageType = FW_SET_STAMP_IMAGE;\r
2161 if (argv[1] == NULL || argv[1][0] == '-') {\r
2162 Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");\r
2163 goto Finish;\r
2164 }\r
2165 TimeStamp = argv[1];\r
2166 argc -= 2;\r
2167 argv += 2;\r
2168 continue;\r
2169 }\r
2170\r
2171 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {\r
2172 ReplaceFlag = TRUE;\r
2173 argc --;\r
2174 argv ++;\r
2175 continue;\r
2176 }\r
2177\r
2178 if (stricmp (argv[0], "--keepexceptiontable") == 0) {\r
2179 KeepExceptionTableFlag = TRUE;\r
2180 argc --;\r
2181 argv ++;\r
2182 continue;\r
2183 }\r
2184\r
2185 if (stricmp (argv[0], "--keepzeropending") == 0) {\r
2186 KeepZeroPendingFlag = TRUE;\r
2187 argc --;\r
2188 argv ++;\r
2189 continue;\r
2190 }\r
2191\r
2192 if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {\r
2193 OutImageType = FW_MCI_IMAGE;\r
2194 argc --;\r
2195 argv ++;\r
2196 continue;\r
2197 }\r
2198\r
2199 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {\r
2200 OutImageType = FW_MERGE_IMAGE;\r
2201 argc --;\r
2202 argv ++;\r
2203 continue;\r
2204 }\r
2205\r
2206 if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {\r
2207 if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
2208 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2209 goto Finish;\r
2210 }\r
2211 MciAlignment = (UINT32) Temp64;\r
2212 argc -= 2;\r
2213 argv += 2;\r
2214 continue;\r
2215 }\r
2216\r
52302d4d
LG
2217 if ((stricmp (argv[0], "--rebase") == 0)) {\r
2218 if (argv[1][0] == '-') {\r
2219 NegativeAddr = TRUE;\r
2220 Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);\r
2221 } else {\r
2222 NegativeAddr = FALSE;\r
2223 Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);\r
2224 }\r
2225 if (Status != EFI_SUCCESS) {\r
2226 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2227 goto Finish;\r
2228 }\r
2229 OutImageType = FW_REBASE_IMAGE;\r
2230 NewBaseAddress = (UINT64) Temp64;\r
2231 argc -= 2;\r
2232 argv += 2;\r
2233 continue;\r
2234 }\r
2235\r
2236 if ((stricmp (argv[0], "--address") == 0)) {\r
2237 if (argv[1][0] == '-') {\r
2238 NegativeAddr = TRUE;\r
2239 Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);\r
2240 } else {\r
2241 NegativeAddr = FALSE;\r
2242 Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);\r
2243 }\r
2244 if (Status != EFI_SUCCESS) {\r
2245 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2246 goto Finish;\r
2247 }\r
2248 OutImageType = FW_SET_ADDRESS_IMAGE;\r
2249 NewBaseAddress = (UINT64) Temp64;\r
2250 argc -= 2;\r
2251 argv += 2;\r
2252 continue;\r
2253 }\r
2254\r
30fdf114
LG
2255 if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {\r
2256 if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {\r
2257 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2258 goto Finish;\r
2259 }\r
2260 MciPadValue = (UINT8) Temp64;\r
2261 argc -= 2;\r
2262 argv += 2;\r
2263 continue;\r
2264 }\r
2265\r
2266 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {\r
2267 SetPrintLevel (VERBOSE_LOG_LEVEL);\r
2268 VerboseMsg ("Verbose output Mode Set!");\r
2269 argc --;\r
2270 argv ++;\r
2271 continue;\r
2272 }\r
2273\r
2274 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {\r
2275 SetPrintLevel (KEY_LOG_LEVEL);\r
2276 KeyMsg ("Quiet output Mode Set!");\r
2277 argc --;\r
2278 argv ++;\r
2279 continue;\r
2280 }\r
2281\r
2282 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {\r
2283 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);\r
2284 if (EFI_ERROR (Status)) {\r
2285 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2286 goto Finish;\r
2287 }\r
2288 if (LogLevel > 9) {\r
fd171542 2289 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", (int) LogLevel);\r
30fdf114
LG
2290 goto Finish;\r
2291 }\r
2292 SetPrintLevel (LogLevel);\r
2293 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);\r
2294 argc -= 2;\r
2295 argv += 2;\r
2296 continue;\r
2297 }\r
52302d4d 2298\r
b303ea72
LG
2299 if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {\r
2300 Status = StringToGuid (argv[1], &HiiPackageListGuid);\r
2301 if (EFI_ERROR (Status)) {\r
2302 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
2303 goto Finish;\r
2304 }\r
2305 argc -= 2;\r
2306 argv += 2;\r
2307 continue;\r
2308 }\r
2309\r
2310 if (stricmp (argv[0], "--hiipackage") == 0) {\r
2311 OutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;\r
2312 argc --;\r
2313 argv ++;\r
2314 continue;\r
2315 }\r
2316\r
a709adfa
LG
2317 if (stricmp (argv[0], "--hiibinpackage") == 0) {\r
2318 OutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;\r
2319 argc --;\r
2320 argv ++;\r
2321 continue;\r
2322 }\r
2323\r
30fdf114
LG
2324 if (argv[0][0] == '-') {\r
2325 Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
2326 goto Finish;\r
2327 }\r
2328 //\r
2329 // Get Input file name\r
2330 //\r
2331 if ((InputFileNum == 0) && (InputFileName == NULL)) {\r
2332 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));\r
2333 if (InputFileName == NULL) {\r
2334 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
fd171542 2335 goto Finish;\r
30fdf114
LG
2336 }\r
2337\r
2338 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
2339 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {\r
2340 //\r
2341 // InputFileName buffer too small, need to realloc\r
2342 //\r
2343 InputFileName = (CHAR8 **) realloc (\r
52302d4d
LG
2344 InputFileName,\r
2345 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)\r
2346 );\r
30fdf114
LG
2347\r
2348 if (InputFileName == NULL) {\r
2349 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
fd171542 2350 goto Finish;\r
30fdf114
LG
2351 }\r
2352\r
2353 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));\r
2354 }\r
2355\r
2356 InputFileName [InputFileNum ++] = argv[0];\r
2357 argc --;\r
2358 argv ++;\r
2359 }\r
2360\r
2361 VerboseMsg ("%s tool start.", UTILITY_NAME);\r
2362\r
2363 if (OutImageType == FW_DUMMY_IMAGE) {\r
2364 Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");\r
2365 if (ReplaceFlag) {\r
2366 Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");\r
2367 }\r
2368 goto Finish;\r
2369 }\r
2370\r
2371 //\r
2372 // check input files\r
2373 //\r
2374 if (InputFileNum == 0) {\r
2375 Error (NULL, 0, 1001, "Missing option", "Input files");\r
2376 goto Finish;\r
2377 }\r
2378\r
2379 //\r
2380 // Combine MciBinary files to one file\r
2381 //\r
2382 if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {\r
2383 Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");\r
2384 goto Finish;\r
2385 }\r
2386\r
b303ea72
LG
2387 //\r
2388 // Combine HiiBinary packages to a single package list\r
2389 //\r
2390 if ((OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {\r
2391 Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");\r
2392 goto Finish;\r
2393 }\r
2394\r
a709adfa
LG
2395 if ((OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {\r
2396 Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");\r
2397 goto Finish;\r
2398 }\r
2399\r
30fdf114
LG
2400 //\r
2401 // Input image file\r
2402 //\r
2403 mInImageName = InputFileName [InputFileNum - 1];\r
2404 VerboseMsg ("the input file name is %s", mInImageName);\r
2405\r
2406 //\r
2407 // Action will be taken for the input file.\r
2408 //\r
2409 switch (OutImageType) {\r
2410 case FW_EFI_IMAGE:\r
2411 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);\r
2412 break;\r
2413 case FW_TE_IMAGE:\r
2414 VerboseMsg ("Create Te Image based on the input PE image.");\r
2415 break;\r
2416 case FW_ACPI_IMAGE:\r
2417 VerboseMsg ("Get acpi table data from the input PE image.");\r
2418 break;\r
2419 case FW_RELOC_STRIPEED_IMAGE:\r
2420 VerboseMsg ("Remove relocation section from Pe or Te image.");\r
2421 break;\r
2422 case FW_BIN_IMAGE:\r
2423 VerboseMsg ("Convert the input EXE to the output BIN file.");\r
2424 break;\r
2425 case FW_ZERO_DEBUG_IMAGE:\r
2426 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");\r
2427 break;\r
2428 case FW_SET_STAMP_IMAGE:\r
2429 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);\r
2430 break;\r
2431 case DUMP_TE_HEADER:\r
2432 VerboseMsg ("Dump the TE header information of the input TE image.");\r
2433 break;\r
2434 case FW_MCI_IMAGE:\r
2435 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");\r
2436 break;\r
2437 case FW_MERGE_IMAGE:\r
2438 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");\r
2439 break;\r
b303ea72
LG
2440 case FW_HII_PACKAGE_LIST_RCIMAGE:\r
2441 VerboseMsg ("Combine the input multi hii bin packages to one text pacakge list RC file.");\r
2442 break;\r
a709adfa
LG
2443 case FW_HII_PACKAGE_LIST_BINIMAGE:\r
2444 VerboseMsg ("Combine the input multi hii bin packages to one binary pacakge list file.");\r
2445 break;\r
52302d4d
LG
2446 case FW_REBASE_IMAGE:\r
2447 VerboseMsg ("Rebase the input image to new base address.");\r
2448 break;\r
2449 case FW_SET_ADDRESS_IMAGE:\r
2450 VerboseMsg ("Set the preferred address into the section header of the input image");\r
2451 break;\r
30fdf114
LG
2452 default:\r
2453 break;\r
2454 }\r
2455\r
2456 if (ReplaceFlag) {\r
2457 VerboseMsg ("Overwrite the input file with the output content.");\r
2458 }\r
2459\r
2460 //\r
2461 // Open output file and Write image into the output file.\r
2462 //\r
2463 if (OutImageName != NULL) {\r
2464 fpOut = fopen (OutImageName, "rb");\r
2465 if (fpOut != NULL) {\r
636f2be6
LG
2466 //\r
2467 // Get Output file time stamp\r
2468 //\r
2469 fstat(fileno (fpOut), &Stat_Buf);\r
2470 OutputFileTime = Stat_Buf.st_mtime;\r
2471 //\r
2472 // Get Output file data\r
2473 //\r
30fdf114
LG
2474 OutputFileLength = _filelength (fileno (fpOut));\r
2475 OutputFileBuffer = malloc (OutputFileLength);\r
2476 if (OutputFileBuffer == NULL) {\r
2477 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2478 fclose (fpOut);\r
2479 fpOut = NULL;\r
2480 goto Finish;\r
2481 }\r
2482 fread (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
2483 fclose (fpOut);\r
52302d4d 2484 fpOut = NULL;\r
30fdf114
LG
2485 }\r
2486 VerboseMsg ("Output file name is %s", OutImageName);\r
52302d4d
LG
2487 } else if (!ReplaceFlag && OutImageType != DUMP_TE_HEADER) {\r
2488 Error (NULL, 0, 1001, "Missing option", "output file");\r
2489 goto Finish;\r
30fdf114
LG
2490 }\r
2491\r
52302d4d
LG
2492 //\r
2493 // Open input file and read file data into file buffer.\r
2494 //\r
2495 fpIn = fopen (mInImageName, "rb");\r
2496 if (fpIn == NULL) {\r
2497 Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2498 goto Finish;\r
2499 }\r
636f2be6
LG
2500 //\r
2501 // Get Iutput file time stamp\r
2502 //\r
2503 fstat(fileno (fpIn), &Stat_Buf);\r
2504 InputFileTime = Stat_Buf.st_mtime;\r
2505 //\r
2506 // Get Input file data\r
2507 //\r
52302d4d
LG
2508 InputFileLength = _filelength (fileno (fpIn));\r
2509 InputFileBuffer = malloc (InputFileLength);\r
2510 if (InputFileBuffer == NULL) {\r
2511 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2512 fclose (fpIn);\r
2513 goto Finish;\r
2514 }\r
2515 fread (InputFileBuffer, 1, InputFileLength, fpIn);\r
2516 fclose (fpIn);\r
2517 DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength);\r
2518\r
b303ea72 2519 //\r
a709adfa 2520 // Combine multi binary HII package files.\r
b303ea72 2521 //\r
a709adfa 2522 if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
52302d4d
LG
2523 //\r
2524 // Open output file handle.\r
2525 //\r
2526 fpOut = fopen (OutImageName, "wb");\r
2527 if (!fpOut) {\r
2528 Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
2529 goto Finish;\r
2530 }\r
b303ea72
LG
2531 //\r
2532 // Get hii package list lenght\r
2533 //\r
2534 HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
2535 for (Index = 0; Index < InputFileNum; Index ++) {\r
2536 fpIn = fopen (InputFileName [Index], "rb");\r
52302d4d 2537 if (fpIn == NULL) {\r
b303ea72
LG
2538 Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2539 goto Finish;\r
2540 }\r
2541 FileLength = _filelength (fileno (fpIn));\r
2542 fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);\r
2543 if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {\r
2544 if (HiiPackageHeader.Length != FileLength) {\r
2545 Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);\r
2546 fclose (fpIn);\r
2547 goto Finish;\r
2548 }\r
2549 if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
2550 fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);\r
2551 memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));\r
2552 }\r
2553 NumberOfFormPacakge ++;\r
2554 }\r
2555 HiiPackageListHeader.PackageLength += FileLength;\r
2556 fclose (fpIn);\r
2557 }\r
2558 HiiPackageListHeader.PackageLength += sizeof (EndPackage);\r
2559 //\r
2560 // Check whether hii packages are valid\r
2561 //\r
2562 if (NumberOfFormPacakge > 1) {\r
2563 Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");\r
2564 goto Finish;\r
2565 }\r
2566 if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {\r
2567 Error (NULL, 0, 3000, "Invalid", "HII pacakge list guid is not specified!");\r
2568 goto Finish;\r
2569 }\r
2570 memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));\r
2571 //\r
2572 // read hii packages\r
2573 //\r
2574 HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);\r
2575 if (HiiPackageListBuffer == NULL) {\r
2576 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2577 goto Finish;\r
2578 }\r
2579 memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));\r
2580 HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);\r
2581 for (Index = 0; Index < InputFileNum; Index ++) {\r
2582 fpIn = fopen (InputFileName [Index], "rb");\r
52302d4d 2583 if (fpIn == NULL) {\r
b303ea72
LG
2584 Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2585 free (HiiPackageListBuffer);\r
2586 goto Finish;\r
2587 }\r
2588\r
2589 FileLength = _filelength (fileno (fpIn));\r
2590 fread (HiiPackageDataPointer, 1, FileLength, fpIn);\r
2591 fclose (fpIn);\r
2592 HiiPackageDataPointer = HiiPackageDataPointer + FileLength;\r
2593 }\r
2594 memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));\r
a709adfa 2595\r
b303ea72 2596 //\r
a709adfa 2597 // write the hii package into the binary package list file with the resource section header\r
b303ea72 2598 //\r
a709adfa
LG
2599 if (OutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {\r
2600 //\r
2601 // Create the resource section header\r
2602 //\r
2603 HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);\r
2604 //\r
2605 // Wrtie section header and HiiData into File.\r
2606 //\r
2607 fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);\r
2608 fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);\r
2609 //\r
2610 // Free allocated resources.\r
2611 //\r
2612 free (HiiSectionHeader);\r
2613 free (HiiPackageListBuffer);\r
2614 //\r
2615 // Done successfully\r
2616 //\r
2617 goto Finish;\r
b303ea72 2618 }\r
b303ea72 2619\r
a709adfa
LG
2620 //\r
2621 // write the hii package into the text package list rc file.\r
2622 //\r
2623 if (OutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {\r
2624 for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {\r
2625 fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);\r
2626 }\r
2627 fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);\r
2628\r
2629 HiiPackageDataPointer = HiiPackageListBuffer;\r
2630 for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {\r
2631 if (Index % 16 == 0) {\r
2632 fprintf (fpOut, "\n ");\r
2633 }\r
2634 fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);\r
2635 HiiPackageDataPointer += 2;\r
2636 }\r
52302d4d 2637\r
b303ea72
LG
2638 if (Index % 16 == 0) {\r
2639 fprintf (fpOut, "\n ");\r
2640 }\r
a709adfa
LG
2641 if ((Index + 2) == HiiPackageListHeader.PackageLength) {\r
2642 fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);\r
2643 }\r
2644 if ((Index + 1) == HiiPackageListHeader.PackageLength) {\r
2645 fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);\r
2646 }\r
2647 free (HiiPackageListBuffer);\r
2648 //\r
2649 // Done successfully\r
2650 //\r
2651 goto Finish;\r
b303ea72 2652 }\r
b303ea72
LG
2653 }\r
2654\r
30fdf114
LG
2655 //\r
2656 // Combine MciBinary files to one file\r
2657 //\r
2658 if (OutImageType == FW_MERGE_IMAGE) {\r
52302d4d
LG
2659 //\r
2660 // Open output file handle.\r
2661 //\r
2662 fpOut = fopen (OutImageName, "wb");\r
2663 if (!fpOut) {\r
2664 Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
2665 goto Finish;\r
2666 }\r
30fdf114
LG
2667 for (Index = 0; Index < InputFileNum; Index ++) {\r
2668 fpIn = fopen (InputFileName [Index], "rb");\r
2669 if (!fpIn) {\r
2670 Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);\r
2671 goto Finish;\r
2672 }\r
2673\r
2674 FileLength = _filelength (fileno (fpIn));\r
2675 FileBuffer = malloc (FileLength);\r
2676 if (FileBuffer == NULL) {\r
2677 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2678 fclose (fpIn);\r
2679 goto Finish;\r
2680 }\r
2681\r
2682 fread (FileBuffer, 1, FileLength, fpIn);\r
2683 fclose (fpIn);\r
2684 //\r
2685 // write input file to out file\r
2686 //\r
2687 fwrite (FileBuffer, 1, FileLength, fpOut);\r
2688 //\r
2689 // write pad value to out file.\r
2690 //\r
2691 while (FileLength ++ % MciAlignment != 0) {\r
2692 fwrite (&MciPadValue, 1, 1, fpOut);\r
2693 }\r
2694 //\r
2695 // free allocated memory space\r
2696 //\r
2697 free (FileBuffer);\r
2698 FileBuffer = NULL;\r
2699 }\r
2700 //\r
2701 // Done successfully\r
2702 //\r
2703 goto Finish;\r
2704 }\r
2705\r
2706 //\r
2707 // Convert MicroCode.txt file to MicroCode.bin file\r
2708 //\r
2709 if (OutImageType == FW_MCI_IMAGE) {\r
2710 fpIn = fopen (mInImageName, "r");\r
52302d4d 2711 if (fpIn == NULL) {\r
30fdf114
LG
2712 Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2713 goto Finish;\r
2714 }\r
2715\r
2716 //\r
2717 // The first pass is to determine\r
2718 // how much data is in the file so we can allocate a working buffer.\r
2719 //\r
2720 FileLength = 0;\r
2721 do {\r
2722 Status = MicrocodeReadData (fpIn, &Data);\r
2723 if (Status == STATUS_SUCCESS) {\r
2724 FileLength += sizeof (Data);\r
2725 }\r
2726 if (Status == STATUS_IGNORE) {\r
2727 Status = STATUS_SUCCESS;\r
2728 }\r
2729 } while (Status == STATUS_SUCCESS);\r
2730 //\r
2731 // Error if no data.\r
2732 //\r
2733 if (FileLength == 0) {\r
2734 Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);\r
2735 goto Finish;\r
2736 }\r
2737 if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {\r
2738 Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);\r
2739 goto Finish;\r
2740 }\r
2741\r
2742 //\r
2743 // Allocate a buffer for the data\r
2744 //\r
2745 FileBuffer = malloc (FileLength);\r
2746 if (FileBuffer == NULL) {\r
2747 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
2748 goto Finish;\r
2749 }\r
2750 //\r
2751 // Re-read the file, storing the data into our buffer\r
2752 //\r
2753 fseek (fpIn, 0, SEEK_SET);\r
2754 DataPointer = (UINT32 *) FileBuffer;\r
2755 OldDataPointer = DataPointer;\r
2756 do {\r
2757 OldDataPointer = DataPointer;\r
2758 Status = MicrocodeReadData (fpIn, DataPointer++);\r
2759 if (Status == STATUS_IGNORE) {\r
2760 DataPointer = OldDataPointer;\r
2761 Status = STATUS_SUCCESS;\r
2762 }\r
2763 } while (Status == STATUS_SUCCESS);\r
2764 //\r
2765 // close input file after read data\r
2766 //\r
2767 fclose (fpIn);\r
2768\r
2769 //\r
2770 // Can't do much checking on the header because, per the spec, the\r
2771 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,\r
2772 // and the TotalSize field is invalid (actually missing). Thus we can't\r
2773 // even verify the Reserved fields are 0.\r
2774 //\r
2775 MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;\r
2776 if (MciHeader->DataSize == 0) {\r
2777 Index = 2048;\r
2778 } else {\r
2779 Index = MciHeader->TotalSize;\r
2780 }\r
2781\r
2782 if (Index != FileLength) {\r
fd171542 2783 Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);\r
30fdf114
LG
2784 goto Finish;\r
2785 }\r
2786\r
2787 //\r
2788 // Checksum the contents\r
2789 //\r
2790 DataPointer = (UINT32 *) FileBuffer;\r
2791 CheckSum = 0;\r
2792 Index = 0;\r
2793 while (Index < FileLength) {\r
2794 CheckSum += *DataPointer;\r
2795 DataPointer ++;\r
2796 Index += sizeof (*DataPointer);\r
2797 }\r
2798 if (CheckSum != 0) {\r
fd171542 2799 Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);\r
30fdf114
LG
2800 goto Finish;\r
2801 }\r
2802 //\r
2803 // Open the output file and write the buffer contents\r
2804 //\r
fd171542 2805 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
52302d4d 2806 goto WriteFile;\r
30fdf114
LG
2807 }\r
2808\r
2809 //\r
2810 // Open input file and read file data into file buffer.\r
2811 //\r
52302d4d 2812 FileLength = InputFileLength;\r
30fdf114
LG
2813 FileBuffer = malloc (FileLength);\r
2814 if (FileBuffer == NULL) {\r
2815 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
30fdf114
LG
2816 goto Finish;\r
2817 }\r
52302d4d 2818 memcpy (FileBuffer, InputFileBuffer, InputFileLength);\r
30fdf114 2819\r
30fdf114
LG
2820 //\r
2821 // Dump TeImage Header into output file.\r
2822 //\r
2823 if (OutImageType == DUMP_TE_HEADER) {\r
2824 memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));\r
2825 if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2826 Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);\r
2827 goto Finish;\r
2828 }\r
52302d4d
LG
2829 //\r
2830 // Open the output file handle.\r
2831 //\r
2832 if (ReplaceFlag) {\r
2833 fpInOut = fopen (mInImageName, "wb");\r
2834 if (fpInOut == NULL) {\r
2835 Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
2836 goto Finish;\r
2837 }\r
2838 } else {\r
2839 if (OutImageName != NULL) {\r
2840 fpOut = fopen (OutImageName, "wb");\r
2841 } else {\r
2842 fpOut = stdout;\r
2843 }\r
2844 if (fpOut == NULL) {\r
2845 Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
2846 goto Finish;\r
2847 }\r
2848 }\r
30fdf114
LG
2849 if (fpInOut != NULL) {\r
2850 fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);\r
2851 fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");\r
2852 fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);\r
2853 fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2854 fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2855 fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
fd171542 2856 fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2857 fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2858 fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2859 fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2860 fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
30fdf114 2861 }\r
30fdf114
LG
2862 if (fpOut != NULL) {\r
2863 fprintf (fpOut, "Dump of file %s\n\n", mInImageName);\r
2864 fprintf (fpOut, "TE IMAGE HEADER VALUES\n");\r
2865 fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);\r
2866 fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);\r
2867 fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);\r
2868 fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);\r
fd171542 2869 fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);\r
2870 fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);\r
2871 fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);\r
2872 fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);\r
2873 fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);\r
30fdf114
LG
2874 }\r
2875 goto Finish;\r
2876 }\r
2877\r
2878 //\r
2879 // Following code to convert dll to efi image or te image.\r
2880 // Get new image type\r
2881 //\r
2882 if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {\r
2883 if (ModuleType == NULL) {\r
2884 if (OutImageType == FW_EFI_IMAGE) {\r
2885 Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");\r
2886 goto Finish;\r
2887 } else if (OutImageType == FW_TE_IMAGE) {\r
2888 //\r
2889 // Default TE Image Type is Boot service driver\r
2890 //\r
2891 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2892 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
2893 }\r
2894 } else {\r
2895 if (stricmp (ModuleType, "BASE") == 0 ||\r
52302d4d
LG
2896 stricmp (ModuleType, "SEC") == 0 ||\r
2897 stricmp (ModuleType, "SECURITY_CORE") == 0 ||\r
2898 stricmp (ModuleType, "PEI_CORE") == 0 ||\r
2899 stricmp (ModuleType, "PEIM") == 0 ||\r
2900 stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||\r
2901 stricmp (ModuleType, "PIC_PEIM") == 0 ||\r
2902 stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||\r
2903 stricmp (ModuleType, "DXE_CORE") == 0 ||\r
2904 stricmp (ModuleType, "BS_DRIVER") == 0 ||\r
2905 stricmp (ModuleType, "DXE_DRIVER") == 0 ||\r
2906 stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 ||\r
2907 stricmp (ModuleType, "UEFI_DRIVER") == 0 ||\r
2908 stricmp (ModuleType, "SMM_CORE") == 0) {\r
2909 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;\r
2910 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");\r
30fdf114
LG
2911\r
2912 } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||\r
52302d4d
LG
2913 stricmp (ModuleType, "APPLICATION") == 0) {\r
2914 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;\r
2915 VerboseMsg ("Efi Image subsystem type is efi application.");\r
30fdf114
LG
2916\r
2917 } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||\r
52302d4d
LG
2918 stricmp (ModuleType, "RT_DRIVER") == 0) {\r
2919 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;\r
2920 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");\r
30fdf114
LG
2921\r
2922 } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||\r
52302d4d
LG
2923 stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {\r
2924 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;\r
2925 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");\r
30fdf114
LG
2926\r
2927 } else {\r
2928 Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);\r
2929 goto Finish;\r
2930 }\r
2931 }\r
2932 }\r
2933\r
2934 //\r
2935 // Convert EFL image to PeImage\r
2936 //\r
2937 if (IsElfHeader(FileBuffer)) {\r
2938 VerboseMsg ("Convert the input ELF Image to Pe Image");\r
2939 ConvertElf(&FileBuffer, &FileLength);\r
2940 }\r
52302d4d 2941\r
a709adfa
LG
2942 //\r
2943 // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP\r
2944 // XIP == eXecute In Place\r
2945 //\r
2946 PeCoffConvertImageToXip (&FileBuffer, &FileLength);\r
30fdf114
LG
2947\r
2948 //\r
2949 // Remove reloc section from PE or TE image\r
2950 //\r
2951 if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {\r
2952 //\r
2953 // Check TeImage\r
2954 //\r
2955 TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;\r
2956 if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
2957 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);\r
2958 for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
2959 if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2960 //\r
2961 // Check the reloc section is in the end of image.\r
2962 //\r
2963 if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==\r
2964 (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {\r
52302d4d
LG
2965 //\r
2966 // Remove .reloc section and update TeImage Header\r
2967 //\r
2968 FileLength = FileLength - SectionHeader->SizeOfRawData;\r
2969 SectionHeader->SizeOfRawData = 0;\r
2970 SectionHeader->Misc.VirtualSize = 0;\r
2971 TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
2972 TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
2973 break;\r
30fdf114
LG
2974 }\r
2975 }\r
2976 }\r
2977 } else {\r
2978 //\r
2979 // Check PE Image\r
2980 //\r
2981 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
2982 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
2983 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
2984 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2985 Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);\r
2986 goto Finish;\r
2987 }\r
2988 DosHdr = NULL;\r
2989 } else {\r
2990 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
2991 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
2992 Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
2993 goto Finish;\r
2994 }\r
2995 }\r
2996 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
2997 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
2998 if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {\r
2999 //\r
3000 // Check the reloc section is in the end of image.\r
3001 //\r
3002 if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {\r
3003 //\r
3004 // Remove .reloc section and update PeImage Header\r
3005 //\r
3006 FileLength = FileLength - SectionHeader->SizeOfRawData;\r
3007\r
3008 PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
3009 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
3010 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
3011 Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;\r
3012 Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
3013 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
3014 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
3015 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
3016 }\r
3017 }\r
3018 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
3019 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
3020 Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;\r
3021 Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;\r
3022 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
3023 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;\r
3024 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;\r
3025 }\r
3026 }\r
3027 SectionHeader->Misc.VirtualSize = 0;\r
3028 SectionHeader->SizeOfRawData = 0;\r
3029 break;\r
3030 }\r
3031 }\r
3032 }\r
3033 }\r
3034 //\r
3035 // Write file\r
3036 //\r
3037 goto WriteFile;\r
3038 }\r
3039 //\r
3040 // Read the dos & pe hdrs of the image\r
3041 //\r
3042 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
3043 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
3044 // NO DOS header, check for PE/COFF header\r
3045 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);\r
3046 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
3047 Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);\r
3048 goto Finish;\r
3049 }\r
3050 DosHdr = NULL;\r
3051 } else {\r
3052\r
3053 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);\r
3054 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {\r
3055 Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);\r
3056 goto Finish;\r
3057 }\r
3058 }\r
52302d4d 3059\r
30fdf114
LG
3060 if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {\r
3061 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)\r
3062 // so patch back to the offical UEFI value.\r
3063 PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;\r
3064 }\r
3065\r
52302d4d
LG
3066 //\r
3067 // Set new base address into image\r
3068 //\r
3069 if (OutImageType == FW_REBASE_IMAGE || OutImageType == FW_SET_ADDRESS_IMAGE) {\r
3070 if ((PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) && (PeHdr->Pe32.FileHeader.Machine != IMAGE_FILE_MACHINE_IA64)) {\r
3071 if (NewBaseAddress >= 0x100000000ULL) {\r
3072 Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");\r
3073 goto Finish;\r
3074 }\r
3075 }\r
3076 \r
3077 if (NegativeAddr) {\r
3078 //\r
3079 // Set Base Address to a negative value.\r
3080 //\r
3081 NewBaseAddress = (UINT64) (0 - NewBaseAddress);\r
3082 }\r
3083 if (OutImageType == FW_REBASE_IMAGE) {\r
3084 Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress);\r
3085 } else {\r
3086 Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress);\r
3087 }\r
3088 if (EFI_ERROR (Status)) {\r
3089 if (NegativeAddr) {\r
3090 Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress);\r
3091 } else {\r
3092 Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress);\r
3093 }\r
3094 goto Finish;\r
3095 }\r
3096\r
3097 //\r
3098 // Write file\r
3099 //\r
3100 goto WriteFile;\r
3101 }\r
3102\r
30fdf114
LG
3103 //\r
3104 // Extract bin data from Pe image.\r
3105 //\r
3106 if (OutImageType == FW_BIN_IMAGE) {\r
3107 if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {\r
3108 Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);\r
3109 goto Finish;\r
3110 }\r
3111 //\r
3112 // Output bin data from exe file\r
3113 //\r
52302d4d
LG
3114 FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;\r
3115 memcpy (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength);\r
3116 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
3117 goto WriteFile;\r
30fdf114
LG
3118 }\r
3119\r
3120 //\r
3121 // Zero Debug Information of Pe Image\r
3122 //\r
3123 if (OutImageType == FW_ZERO_DEBUG_IMAGE) {\r
3124 Status = ZeroDebugData (FileBuffer, TRUE);\r
3125 if (EFI_ERROR (Status)) {\r
fd171542 3126 Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);\r
30fdf114
LG
3127 goto Finish;\r
3128 }\r
3129\r
52302d4d
LG
3130 //\r
3131 // Write the updated Image\r
3132 //\r
fd171542 3133 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
52302d4d 3134 goto WriteFile;\r
30fdf114
LG
3135 }\r
3136\r
3137 //\r
3138 // Set Time Stamp of Pe Image\r
3139 //\r
3140 if (OutImageType == FW_SET_STAMP_IMAGE) {\r
3141 Status = SetStamp (FileBuffer, TimeStamp);\r
3142 if (EFI_ERROR (Status)) {\r
3143 goto Finish;\r
3144 }\r
3145\r
52302d4d
LG
3146 //\r
3147 // Write the updated Image\r
3148 //\r
fd171542 3149 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
52302d4d 3150 goto WriteFile;\r
30fdf114
LG
3151 }\r
3152\r
3153 //\r
3154 // Extract acpi data from pe image.\r
3155 //\r
3156 if (OutImageType == FW_ACPI_IMAGE) {\r
3157 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3158 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {\r
3159 if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {\r
3160 //\r
3161 // Check Acpi Table\r
3162 //\r
3163 if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {\r
3164 FileLength = SectionHeader->Misc.VirtualSize;\r
3165 } else {\r
3166 FileLength = SectionHeader->SizeOfRawData;\r
3167 }\r
3168\r
3169 if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {\r
3170 Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);\r
3171 goto Finish;\r
3172 }\r
3173\r
3174 //\r
3175 // Output Apci data to file\r
3176 //\r
52302d4d 3177 memcpy (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);\r
fd171542 3178 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
52302d4d 3179 goto WriteFile;\r
30fdf114
LG
3180 }\r
3181 }\r
3182 Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);\r
3183 goto Finish;\r
3184 }\r
3185 //\r
3186 // Zero all unused fields of the DOS header\r
3187 //\r
3188 if (DosHdr != NULL) {\r
3189 memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));\r
3190 memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));\r
3191 DosHdr->e_magic = BackupDosHdr.e_magic;\r
3192 DosHdr->e_lfanew = BackupDosHdr.e_lfanew;\r
52302d4d 3193\r
30fdf114 3194 for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {\r
fd171542 3195 FileBuffer[Index] = (UINT8) DosHdr->e_cp;\r
30fdf114
LG
3196 }\r
3197 }\r
3198\r
3199 //\r
3200 // Initialize TeImage Header\r
3201 //\r
3202 memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));\r
3203 TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;\r
3204 TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine;\r
3205 TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;\r
3206 TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);\r
3207 TEImageHeader.Subsystem = (UINT8) Type;\r
52302d4d 3208\r
30fdf114
LG
3209 //\r
3210 // Patch the PE header\r
3211 //\r
3212 PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;\r
3213\r
3214 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
3215 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
30fdf114
LG
3216 Optional32->MajorOperatingSystemVersion = 0;\r
3217 Optional32->MinorOperatingSystemVersion = 0;\r
3218 Optional32->MajorImageVersion = 0;\r
3219 Optional32->MinorImageVersion = 0;\r
3220 Optional32->MajorSubsystemVersion = 0;\r
3221 Optional32->MinorSubsystemVersion = 0;\r
3222 Optional32->Win32VersionValue = 0;\r
3223 Optional32->CheckSum = 0;\r
3224 Optional32->SizeOfStackReserve = 0;\r
3225 Optional32->SizeOfStackCommit = 0;\r
3226 Optional32->SizeOfHeapReserve = 0;\r
3227 Optional32->SizeOfHeapCommit = 0;\r
3228\r
3229 TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;\r
3230 TEImageHeader.BaseOfCode = Optional32->BaseOfCode;\r
3231 TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase);\r
3232\r
3233 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
3234 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
3235 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
3236 }\r
3237\r
3238 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
3239 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3240 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
3241 }\r
3242\r
3243 //\r
3244 // Zero .pdata section data.\r
3245 //\r
3246 if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
52302d4d
LG
3247 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
3248 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
3249 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3250 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
3251 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
3252 //\r
3253 // Zero .pdata Section data\r
3254 //\r
3255 memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);\r
3256 //\r
3257 // Zero .pdata Section header name\r
3258 //\r
3259 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
3260 //\r
3261 // Zero Execption Table\r
3262 //\r
3263 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
3264 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
3265 DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);\r
3266 break;\r
3267 }\r
30fdf114 3268 }\r
30fdf114
LG
3269 }\r
3270\r
3271 //\r
3272 // Strip zero padding at the end of the .reloc section\r
3273 //\r
3274 if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
3275 if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
3276 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3277 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
3278 //\r
3279 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
3280 //\r
3281 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
3282 SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
3283 AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));\r
3284 //\r
3285 // Check to see if there is zero padding at the end of the base relocations\r
3286 //\r
3287 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
3288 //\r
3289 // Check to see if the base relocations are at the end of the file\r
3290 //\r
3291 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {\r
3292 //\r
3293 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
3294 //\r
3295 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3296 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3297 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
3298 FileLength = Optional32->SizeOfImage;\r
fd171542 3299 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
30fdf114
LG
3300 }\r
3301 }\r
3302 }\r
3303 }\r
3304 }\r
3305 }\r
3306 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
3307 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
30fdf114
LG
3308 Optional64->MajorOperatingSystemVersion = 0;\r
3309 Optional64->MinorOperatingSystemVersion = 0;\r
3310 Optional64->MajorImageVersion = 0;\r
3311 Optional64->MinorImageVersion = 0;\r
3312 Optional64->MajorSubsystemVersion = 0;\r
3313 Optional64->MinorSubsystemVersion = 0;\r
3314 Optional64->Win32VersionValue = 0;\r
3315 Optional64->CheckSum = 0;\r
3316 Optional64->SizeOfStackReserve = 0;\r
3317 Optional64->SizeOfStackCommit = 0;\r
3318 Optional64->SizeOfHeapReserve = 0;\r
3319 Optional64->SizeOfHeapCommit = 0;\r
3320\r
3321 TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;\r
3322 TEImageHeader.BaseOfCode = Optional64->BaseOfCode;\r
3323 TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);\r
3324\r
3325 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
3326 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;\r
3327 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
3328 }\r
3329\r
3330 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
3331 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3332 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;\r
3333 }\r
3334\r
3335 //\r
3336 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty\r
3337 // For Itaninum and X64 Image, remove .pdata section.\r
3338 //\r
3339 if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {\r
3340 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&\r
52302d4d
LG
3341 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&\r
3342 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {\r
3343 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3344 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
3345 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {\r
3346 //\r
3347 // Zero .pdata Section header name\r
3348 //\r
3349 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));\r
3350\r
3351 RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);\r
3352 for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {\r
3353 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3354 for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {\r
3355 if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {\r
3356 UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));\r
3357 if (UnwindInfo->Version == 1) {\r
3358 memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));\r
3359 memset (UnwindInfo, 0, sizeof (UNWIND_INFO));\r
3360 }\r
3361 break;\r
30fdf114
LG
3362 }\r
3363 }\r
52302d4d 3364 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));\r
30fdf114 3365 }\r
52302d4d
LG
3366 //\r
3367 // Zero Execption Table\r
3368 //\r
3369 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;\r
3370 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;\r
3371 DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);\r
3372 break;\r
30fdf114 3373 }\r
30fdf114 3374 }\r
30fdf114
LG
3375 }\r
3376 }\r
3377\r
3378 //\r
3379 // Strip zero padding at the end of the .reloc section\r
3380 //\r
3381 if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
3382 if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {\r
3383 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3384 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {\r
3385 //\r
3386 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory\r
3387 //\r
3388 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {\r
3389 SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;\r
3390 AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));\r
3391 //\r
3392 // Check to see if there is zero padding at the end of the base relocations\r
3393 //\r
3394 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {\r
3395 //\r
3396 // Check to see if the base relocations are at the end of the file\r
3397 //\r
3398 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {\r
3399 //\r
3400 // All the required conditions are met to strip the zero padding of the end of the base relocations section\r
3401 //\r
3402 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3403 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);\r
3404 SectionHeader->SizeOfRawData = AllignedRelocSize;\r
3405 FileLength = Optional64->SizeOfImage;\r
fd171542 3406 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));\r
30fdf114
LG
3407 }\r
3408 }\r
3409 }\r
3410 }\r
3411 }\r
3412 }\r
3413 } else {\r
3414 Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);\r
3415 goto Finish;\r
3416 }\r
52302d4d 3417\r
30fdf114
LG
3418 if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \\r
3419 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \\r
3420 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {\r
52302d4d
LG
3421 //\r
3422 // PeImage can be loaded into memory, but it has no relocation section. \r
3423 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.\r
3424 //\r
3425 if (Optional32 != NULL) {\r
3426 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
3427 } else if (Optional64 != NULL) {\r
3428 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);\r
3429 }\r
30fdf114 3430 }\r
a709adfa
LG
3431\r
3432 //\r
3433 // Fill HII section data\r
3434 //\r
3435 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
3436 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
3437 if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {\r
3438 //\r
3439 // Update resource section header offset\r
3440 //\r
3441 SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);\r
3442 //\r
3443 // Update resource section name\r
3444 //\r
3445 strcpy((char *) SectionHeader[Index].Name, ".rsrc");\r
3446 //\r
3447 // Update resource data directory.\r
3448 //\r
3449 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
3450 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
3451 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
3452 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
3453 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
3454 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
3455 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;\r
3456 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;\r
3457 }\r
3458 break;\r
3459 }\r
3460 }\r
3461\r
30fdf114
LG
3462 //\r
3463 // Zero ExceptionTable Xdata\r
3464 //\r
3465 if (!KeepExceptionTableFlag) {\r
3466 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);\r
b303ea72
LG
3467 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {\r
3468 if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {\r
3469 //\r
3470 // zero .xdata section\r
3471 //\r
3472 memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);\r
3473 DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData);\r
3474 break;\r
3475 }\r
3476 }\r
30fdf114
LG
3477 }\r
3478\r
3479 //\r
3480 // Zero Time/Data field\r
3481 //\r
3482 ZeroDebugData (FileBuffer, FALSE);\r
3483\r
3484 if (OutImageType == FW_TE_IMAGE) {\r
3485 if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {\r
3486 //\r
3487 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.\r
3488 //\r
3489 Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);\r
3490 goto Finish;\r
3491 }\r
3492\r
3493 if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {\r
3494 //\r
3495 // TeImage has the same section alignment and file alignment.\r
3496 //\r
3497 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);\r
3498 goto Finish;\r
3499 }\r
3500\r
fd171542 3501 DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",\r
52302d4d 3502 TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);\r
30fdf114
LG
3503 //\r
3504 // Update Image to TeImage\r
3505 //\r
52302d4d
LG
3506 FileLength = FileLength - TEImageHeader.StrippedSize;\r
3507 memcpy (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);\r
3508 FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);\r
3509 memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));\r
3510 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));\r
636f2be6
LG
3511 } else {\r
3512\r
3513 //\r
3514 // Following codes are to fix the objcopy's issue:\r
3515 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section\r
3516 // It cause issue for EFI image which has no ".reloc" sections.\r
3517 // Following codes will be removed when objcopy in binutil fix this problem for PE image.\r
3518 //\r
3519 if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
3520 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
3521 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;\r
3522 if (Optional32->ImageBase == 0) {\r
3523 PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
3524 }\r
3525 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
3526 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;\r
3527 if (Optional64->ImageBase == 0) {\r
3528 PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;\r
3529 }\r
3530 }\r
3531 }\r
30fdf114 3532 }\r
52302d4d 3533\r
30fdf114
LG
3534WriteFile:\r
3535 //\r
52302d4d 3536 // Update Image to EfiImage or TE image\r
30fdf114 3537 //\r
52302d4d
LG
3538 if (ReplaceFlag) {\r
3539 if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {\r
3540 //\r
3541 // Update File when File is changed.\r
3542 //\r
3543 fpInOut = fopen (mInImageName, "wb");\r
3544 if (fpInOut == NULL) {\r
3545 Error (NULL, 0, 0001, "Error opening file", mInImageName);\r
3546 goto Finish;\r
3547 }\r
3548 fwrite (FileBuffer, 1, FileLength, fpInOut);\r
3549 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
3550 }\r
3551 } else {\r
636f2be6
LG
3552 if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {\r
3553 //\r
3554 // Update File when File is changed or File is old.\r
3555 //\r
52302d4d
LG
3556 fpOut = fopen (OutImageName, "wb");\r
3557 if (fpOut == NULL) {\r
3558 Error (NULL, 0, 0001, "Error opening output file", OutImageName);\r
3559 goto Finish;\r
3560 }\r
3561 fwrite (FileBuffer, 1, FileLength, fpOut);\r
3562 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);\r
3563 }\r
30fdf114 3564 }\r
52302d4d 3565 mImageSize = FileLength;\r
30fdf114
LG
3566\r
3567Finish:\r
3568 if (fpInOut != NULL) {\r
3569 if (GetUtilityStatus () != STATUS_SUCCESS) {\r
3570 //\r
52302d4d 3571 // when file updates failed, original file is still recovered.\r
30fdf114 3572 //\r
52302d4d 3573 fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);\r
30fdf114
LG
3574 }\r
3575 //\r
3576 // Write converted data into fpInOut file and close input file.\r
3577 //\r
3578 fclose (fpInOut);\r
3579 }\r
3580\r
3581 if (FileBuffer != NULL) {\r
3582 free (FileBuffer);\r
3583 }\r
3584\r
3585 if (InputFileName != NULL) {\r
3586 free (InputFileName);\r
3587 }\r
3588\r
3589 if (fpOut != NULL) {\r
3590 //\r
3591 // Write converted data into fpOut file and close output file.\r
3592 //\r
3593 fclose (fpOut);\r
3594 if (GetUtilityStatus () != STATUS_SUCCESS) {\r
3595 if (OutputFileBuffer == NULL) {\r
3596 remove (OutImageName);\r
3597 } else {\r
3598 fpOut = fopen (OutImageName, "wb");\r
3599 fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);\r
3600 fclose (fpOut);\r
30fdf114
LG
3601 }\r
3602 }\r
3603 }\r
52302d4d
LG
3604 \r
3605 if (InputFileBuffer != NULL) {\r
3606 free (InputFileBuffer);\r
3607 }\r
3608\r
3609 if (OutputFileBuffer != NULL) {\r
3610 free (OutputFileBuffer);\r
3611 }\r
30fdf114 3612\r
52302d4d
LG
3613 //\r
3614 // Write module size and time stamp to report file.\r
3615 //\r
3616 if (OutImageName != NULL) {\r
3617 FileLen = strlen (OutImageName);\r
3618 }\r
3619 if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {\r
3620 ReportFileName = (CHAR8 *) malloc (FileLen + 1);\r
3621 if (ReportFileName != NULL) {\r
3622 strcpy (ReportFileName, OutImageName);\r
3623 strcpy (ReportFileName + (FileLen - 4), ".txt"); \r
3624 ReportFile = fopen (ReportFileName, "w+");\r
3625 if (ReportFile != NULL) {\r
3626 fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);\r
3627 fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);\r
3628 fclose(ReportFile);\r
3629 }\r
3630 free (ReportFileName);\r
3631 }\r
3632 }\r
30fdf114
LG
3633 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());\r
3634\r
3635 return GetUtilityStatus ();\r
3636}\r
3637\r
3638STATIC\r
3639EFI_STATUS\r
3640ZeroDebugData (\r
3641 IN OUT UINT8 *FileBuffer,\r
3642 BOOLEAN ZeroDebugFlag\r
3643 )\r
3644/*++\r
3645\r
3646Routine Description:\r
3647\r
3648 Zero debug information in PeImage.\r
3649\r
3650Arguments:\r
3651\r
3652 FileBuffer - Pointer to PeImage.\r
3653 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp\r
3654\r
3655Returns:\r
3656\r
3657 EFI_ABORTED - PeImage is invalid.\r
3658 EFI_SUCCESS - Zero debug data successfully.\r
3659\r
3660--*/\r
3661{\r
3662 UINT32 Index;\r
3663 UINT32 DebugDirectoryEntryRva;\r
3664 UINT32 DebugDirectoryEntryFileOffset;\r
3665 UINT32 ExportDirectoryEntryRva;\r
3666 UINT32 ExportDirectoryEntryFileOffset;\r
3667 UINT32 ResourceDirectoryEntryRva;\r
3668 UINT32 ResourceDirectoryEntryFileOffset;\r
3669 EFI_IMAGE_DOS_HEADER *DosHdr;\r
3670 EFI_IMAGE_FILE_HEADER *FileHdr;\r
3671 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;\r
3672 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;\r
3673 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
3674 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
3675 UINT32 *NewTimeStamp; \r
3676\r
3677 //\r
3678 // Init variable.\r
3679 //\r
58e4d800 3680 DebugDirectoryEntryRva = 0;\r
3681 ExportDirectoryEntryRva = 0;\r
3682 ResourceDirectoryEntryRva = 0;\r
3683 DebugDirectoryEntryFileOffset = 0;\r
3684 ExportDirectoryEntryFileOffset = 0;\r
3685 ResourceDirectoryEntryFileOffset = 0;\r
30fdf114
LG
3686 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;\r
3687 FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3688\r
3689\r
3690 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
3691 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
3692 // NO DOS header, must start with PE/COFF header\r
3693 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));\r
3694 } else {\r
3695 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3696 }\r
3697\r
3698 //\r
3699 // Get Debug, Export and Resource EntryTable RVA address.\r
3700 // Resource Directory entry need to review.\r
3701 //\r
3702 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
3703 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3704 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);\r
3705 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3706 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3707 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3708 }\r
3709 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3710 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3711 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3712 }\r
3713 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3714 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3715 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3716 if (ZeroDebugFlag) {\r
3717 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
3718 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
3719 }\r
3720 }\r
3721 } else {\r
3722 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3723 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);\r
3724 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3725 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3726 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3727 }\r
3728 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3729 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3730 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3731 }\r
3732 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3733 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3734 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3735 if (ZeroDebugFlag) {\r
3736 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;\r
3737 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;\r
3738 }\r
3739 }\r
3740 }\r
3741\r
3742 //\r
3743 // Get DirectoryEntryTable file offset.\r
3744 //\r
3745 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
3746 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3747 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3748 DebugDirectoryEntryFileOffset =\r
3749 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3750 }\r
3751 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3752 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3753 ExportDirectoryEntryFileOffset =\r
3754 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3755 }\r
3756 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3757 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3758 ResourceDirectoryEntryFileOffset =\r
3759 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3760 }\r
3761 }\r
3762\r
3763 //\r
3764 //Zero Debug Data and TimeStamp\r
3765 //\r
3766 FileHdr->TimeDateStamp = 0;\r
52302d4d 3767 mImageTimeStamp = 0;\r
58e4d800 3768 if (ExportDirectoryEntryFileOffset != 0) {\r
30fdf114
LG
3769 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
3770 *NewTimeStamp = 0;\r
3771 }\r
3772\r
58e4d800 3773 if (ResourceDirectoryEntryFileOffset != 0) {\r
30fdf114
LG
3774 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
3775 *NewTimeStamp = 0;\r
3776 }\r
3777\r
58e4d800 3778 if (DebugDirectoryEntryFileOffset != 0) {\r
30fdf114
LG
3779 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);\r
3780 DebugEntry->TimeDateStamp = 0;\r
52302d4d 3781 mImageTimeStamp = 0;\r
30fdf114
LG
3782 if (ZeroDebugFlag) {\r
3783 memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);\r
3784 memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
3785 }\r
3786 }\r
3787\r
3788 return EFI_SUCCESS;\r
3789}\r
3790\r
3791STATIC\r
3792EFI_STATUS\r
3793SetStamp (\r
3794 IN OUT UINT8 *FileBuffer,\r
3795 IN CHAR8 *TimeStamp\r
3796 )\r
3797/*++\r
3798\r
3799Routine Description:\r
3800\r
3801 Set new time stamp into PeImage FileHdr and Directory table:\r
3802 Debug, Export and Resource.\r
3803\r
3804Arguments:\r
3805\r
3806 FileBuffer - Pointer to PeImage.\r
3807 TimeStamp - Time stamp string.\r
3808\r
3809Returns:\r
3810\r
3811 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.\r
3812 EFI_SUCCESS - Set new time stamp in this image successfully.\r
3813\r
3814--*/\r
3815{\r
3816 struct tm stime;\r
3817 struct tm *ptime;\r
3818 time_t newtime;\r
fd171542 3819 UINT32 Index;\r
3820 UINT32 DebugDirectoryEntryRva;\r
3821 UINT32 DebugDirectoryEntryFileOffset;\r
3822 UINT32 ExportDirectoryEntryRva;\r
3823 UINT32 ExportDirectoryEntryFileOffset;\r
3824 UINT32 ResourceDirectoryEntryRva;\r
3825 UINT32 ResourceDirectoryEntryFileOffset;\r
30fdf114
LG
3826 EFI_IMAGE_DOS_HEADER *DosHdr;\r
3827 EFI_IMAGE_FILE_HEADER *FileHdr;\r
3828 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;\r
3829 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;\r
3830 EFI_IMAGE_SECTION_HEADER *SectionHeader;\r
3831 UINT32 *NewTimeStamp;\r
3832 \r
3833 //\r
3834 // Init variable.\r
3835 //\r
fd171542 3836 DebugDirectoryEntryRva = 0;\r
3837 DebugDirectoryEntryFileOffset = 0;\r
3838 ExportDirectoryEntryRva = 0;\r
3839 ExportDirectoryEntryFileOffset = 0;\r
3840 ResourceDirectoryEntryRva = 0;\r
3841 ResourceDirectoryEntryFileOffset = 0;\r
30fdf114
LG
3842 //\r
3843 // Get time and date that will be set.\r
3844 //\r
3845 if (TimeStamp == NULL) {\r
3846 Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");\r
3847 return EFI_INVALID_PARAMETER;\r
3848 }\r
3849 //\r
3850 // compare the value with "NOW", if yes, current system time is set.\r
3851 //\r
3852 if (stricmp (TimeStamp, "NOW") == 0) {\r
3853 //\r
3854 // get system current time and date\r
3855 //\r
3856 time (&newtime);\r
3857 } else {\r
3858 //\r
3859 // Check Time Format strictly yyyy-mm-dd 00:00:00\r
3860 //\r
3861 for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {\r
3862 if (Index == 4 || Index == 7) {\r
3863 if (TimeStamp[Index] == '-') {\r
3864 continue;\r
3865 }\r
3866 } else if (Index == 13 || Index == 16) {\r
3867 if (TimeStamp[Index] == ':') {\r
3868 continue;\r
3869 }\r
3870 } else if (Index == 10 && TimeStamp[Index] == ' ') {\r
3871 continue;\r
3872 } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {\r
3873 break;\r
3874 }\r
3875 }\r
3876\r
3877 if (Index < 19 || TimeStamp[19] != '\0') {\r
3878 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);\r
3879 return EFI_INVALID_PARAMETER;\r
3880 }\r
3881\r
3882 //\r
3883 // get the date and time from TimeStamp\r
3884 //\r
3885 if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",\r
3886 &stime.tm_year,\r
3887 &stime.tm_mon,\r
3888 &stime.tm_mday,\r
3889 &stime.tm_hour,\r
3890 &stime.tm_min,\r
3891 &stime.tm_sec\r
3892 ) != 6) {\r
3893 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);\r
3894 return EFI_INVALID_PARAMETER;\r
3895 }\r
3896\r
3897 //\r
3898 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it\r
3899 //\r
3900 if (stime.tm_mon <= 0 || stime.tm_mday <=0) {\r
3901 Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);\r
3902 return EFI_INVALID_PARAMETER;\r
3903 }\r
3904 stime.tm_mon -= 1;\r
3905\r
3906 //\r
3907 // in struct, Year (current year minus 1900)\r
3908 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038\r
3909 //\r
3910 //\r
3911 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)\r
3912 //\r
3913 if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {\r
3914 //\r
3915 // convert 1970 -> 70, 2000 -> 100, ...\r
3916 //\r
3917 stime.tm_year -= 1900;\r
3918 } else {\r
3919 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
3920 return EFI_INVALID_PARAMETER;\r
3921 }\r
3922\r
3923 //\r
3924 // convert the date and time to time_t format\r
3925 //\r
3926 newtime = mktime (&stime);\r
3927 if (newtime == (time_t) - 1) {\r
3928 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);\r
3929 return EFI_INVALID_PARAMETER;\r
3930 }\r
3931 }\r
3932\r
3933 ptime = localtime (&newtime);\r
3934 DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",\r
3935 ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);\r
3936 //\r
3937 // Set new time and data into PeImage.\r
3938 //\r
3939 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;\r
3940 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
3941 // NO DOS header, must start with PE/COFF header\r
3942 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));\r
3943 } else {\r
3944 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));\r
3945 }\r
3946\r
3947 //\r
3948 // Get Debug, Export and Resource EntryTable RVA address.\r
3949 // Resource Directory entry need to review.\r
3950 //\r
3951 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {\r
3952 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3953 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);\r
3954 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3955 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3956 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3957 }\r
3958 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3959 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3960 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3961 }\r
3962 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3963 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3964 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3965 }\r
3966 } else {\r
3967 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));\r
3968 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);\r
3969 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \\r
3970 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {\r
3971 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;\r
3972 }\r
3973 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \\r
3974 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {\r
3975 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;\r
3976 }\r
3977 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \\r
3978 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {\r
3979 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;\r
3980 }\r
3981 }\r
3982\r
3983 //\r
3984 // Get DirectoryEntryTable file offset.\r
3985 //\r
3986 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {\r
3987 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3988 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3989 DebugDirectoryEntryFileOffset =\r
3990 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3991 }\r
3992 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3993 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3994 ExportDirectoryEntryFileOffset =\r
3995 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
3996 }\r
3997 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&\r
3998 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {\r
3999 ResourceDirectoryEntryFileOffset =\r
4000 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;\r
4001 }\r
4002 }\r
4003\r
4004 //\r
4005 // Set new stamp\r
4006 //\r
4007 FileHdr->TimeDateStamp = (UINT32) newtime;\r
52302d4d 4008 mImageTimeStamp = (UINT32) newtime;\r
30fdf114
LG
4009 if (ExportDirectoryEntryRva != 0) {\r
4010 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));\r
4011 *NewTimeStamp = (UINT32) newtime;\r
4012 }\r
4013\r
4014 if (ResourceDirectoryEntryRva != 0) {\r
4015 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));\r
4016 *NewTimeStamp = (UINT32) newtime;\r
4017 }\r
4018\r
4019 if (DebugDirectoryEntryRva != 0) {\r
4020 NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));\r
4021 *NewTimeStamp = (UINT32) newtime;\r
4022 }\r
4023\r
4024 return EFI_SUCCESS;\r
4025}\r
4026\r
4027STATIC\r
4028STATUS\r
4029MicrocodeReadData (\r
4030 FILE *InFptr,\r
4031 UINT32 *Data\r
4032 )\r
4033/*++\r
4034\r
4035Routine Description:\r
4036 Read a 32-bit microcode data value from a text file and convert to raw binary form.\r
4037\r
4038Arguments:\r
4039 InFptr - file pointer to input text file\r
4040 Data - pointer to where to return the data parsed\r
4041\r
4042Returns:\r
4043 STATUS_SUCCESS - no errors or warnings, Data contains valid information\r
4044 STATUS_ERROR - errors were encountered\r
4045\r
4046--*/\r
4047{\r
4048 CHAR8 Line[MAX_LINE_LEN];\r
4049 CHAR8 *cptr;\r
fd171542 4050 unsigned ScannedData = 0;\r
30fdf114
LG
4051\r
4052 Line[MAX_LINE_LEN - 1] = 0;\r
4053 while (1) {\r
4054 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {\r
4055 return STATUS_ERROR;\r
4056 }\r
4057 //\r
4058 // If it was a binary file, then it may have overwritten our null terminator\r
4059 //\r
4060 if (Line[MAX_LINE_LEN - 1] != 0) {\r
4061 return STATUS_ERROR;\r
4062 }\r
4063\r
4064 //\r
4065 // strip space\r
4066 //\r
a709adfa 4067 for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {\r
30fdf114
LG
4068 }\r
4069\r
4070 // Skip Blank Lines and Comment Lines\r
4071 if ((strlen(cptr) != 0) && (*cptr != ';')) {\r
4072 break;\r
4073 }\r
4074 }\r
4075\r
4076 // Look for\r
4077 // dd 000000001h ; comment\r
4078 // dd XXXXXXXX\r
4079 // DD XXXXXXXXX\r
4080 // DD XXXXXXXXX\r
4081 //\r
a709adfa 4082 if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {\r
30fdf114
LG
4083 //\r
4084 // Skip blanks and look for a hex digit\r
4085 //\r
4086 cptr += 3;\r
a709adfa 4087 for (; *cptr && isspace((int)*cptr); cptr++) {\r
30fdf114 4088 }\r
a709adfa 4089 if (isxdigit ((int)*cptr)) {\r
fd171542 4090 if (sscanf (cptr, "%X", &ScannedData) != 1) {\r
30fdf114
LG
4091 return STATUS_ERROR;\r
4092 }\r
4093 }\r
fd171542 4094 *Data = (UINT32) ScannedData;\r
30fdf114
LG
4095 return STATUS_SUCCESS;\r
4096 }\r
4097\r
4098 return STATUS_ERROR;\r
4099}\r