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