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