]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenFw/GenFw.c
Check In tool source code based on Build tool project revision r1655.
[mirror_edk2.git] / BaseTools / Source / C / GenFw / GenFw.c
1 /** @file
2
3 Copyright (c) 2004 - 2009, 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 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <ctype.h>
32
33 #include <Common/UefiBaseTypes.h>
34 #include <IndustryStandard/PeImage.h>
35
36 //
37 // Acpi Table definition
38 //
39 #include <IndustryStandard/Acpi.h>
40 #include <IndustryStandard/Acpi1_0.h>
41 #include <IndustryStandard/Acpi2_0.h>
42 #include <IndustryStandard/Acpi3_0.h>
43 #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
44
45 #include "CommonLib.h"
46 #include "EfiUtilityMsgs.h"
47
48 #include "elf_common.h"
49 #include "elf32.h"
50 #include "elf64.h"
51
52
53 //
54 // Version of this utility
55 //
56 #define UTILITY_NAME "GenFw"
57 #define UTILITY_MAJOR_VERSION 0
58 #define UTILITY_MINOR_VERSION 2
59
60 //
61 // Action for this tool.
62 //
63 #define FW_DUMMY_IMAGE 0
64 #define FW_EFI_IMAGE 1
65 #define FW_TE_IMAGE 2
66 #define FW_ACPI_IMAGE 3
67 #define FW_BIN_IMAGE 4
68 #define FW_ZERO_DEBUG_IMAGE 5
69 #define FW_SET_STAMP_IMAGE 6
70 #define FW_MCI_IMAGE 7
71 #define FW_MERGE_IMAGE 8
72 #define FW_RELOC_STRIPEED_IMAGE 9
73
74 #define DUMP_TE_HEADER 0x11
75
76 #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
77 #define DEFAULT_MC_ALIGNMENT 16
78
79 #ifndef _MAX_PATH
80 #define _MAX_PATH 500
81 #endif
82
83 #define STATUS_IGNORE 0xA
84 //
85 // Structure definition for a microcode header
86 //
87 typedef struct {
88 UINT32 HeaderVersion;
89 UINT32 PatchId;
90 UINT32 Date;
91 UINT32 CpuId;
92 UINT32 Checksum;
93 UINT32 LoaderVersion;
94 UINT32 PlatformId;
95 UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
96 UINT32 TotalSize; // number of bytes
97 UINT32 Reserved[3];
98 } MICROCODE_IMAGE_HEADER;
99
100 STATIC CHAR8 *mInImageName;
101
102 STATIC
103 EFI_STATUS
104 ZeroDebugData (
105 IN OUT UINT8 *FileBuffer,
106 BOOLEAN ZeroDebug
107 );
108
109 STATIC
110 EFI_STATUS
111 SetStamp (
112 IN OUT UINT8 *FileBuffer,
113 IN CHAR8 *TimeStamp
114 );
115
116 STATIC
117 STATUS
118 MicrocodeReadData (
119 FILE *InFptr,
120 UINT32 *Data
121 );
122
123 STATIC
124 VOID
125 Version (
126 VOID
127 )
128 /*++
129
130 Routine Description:
131
132 Print out version information for this utility.
133
134 Arguments:
135
136 None
137
138 Returns:
139
140 None
141
142 --*/
143 {
144 fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
145 }
146
147 STATIC
148 VOID
149 Usage (
150 VOID
151 )
152 /*++
153
154 Routine Description:
155
156 Print Help message.
157
158 Arguments:
159
160 VOID
161
162 Returns:
163
164 None
165
166 --*/
167 {
168 //
169 // Summary usage
170 //
171 fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);
172
173 //
174 // Copyright declaration
175 //
176 fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
177
178 //
179 // Details Option
180 //
181 fprintf (stdout, "Options:\n");
182 fprintf (stdout, " -o FileName, --outputfile FileName\n\
183 File will be created to store the ouput content.\n");
184 fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
185 Create Efi Image. EFI_FILETYPE is one of BASE, SEC,\n\
186 PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
187 DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER, \n\
188 DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER, \n\
189 PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
190 APPLICATION, SAL_RT_DRIVER to support all module types\n\
191 It can only be used together with --keepexceptiontable,\n\
192 --keepzeropending, -r, -o option.It is a action option.\n\
193 If it is combined with other action options, the later\n\
194 input action option will override the previous one.\n");
195 fprintf (stdout, " -c, --acpi Create Acpi table.\n\
196 It can't be combined with other action options\n\
197 except for -o, -r option. It is a action option.\n\
198 If it is combined with other action options, the later\n\
199 input action option will override the previous one.\n");
200 fprintf (stdout, " -t, --terse Create Te Image.\n\
201 It can only be used together with --keepexceptiontable,\n\
202 --keepzeropending, -r, -o option.It is a action option.\n\
203 If it is combined with other action options, the later\n\
204 input action option will override the previous one.\n");
205 fprintf (stdout, " -u, --dump Dump TeImage Header.\n\
206 It can't be combined with other action options\n\
207 except for -o, -r option. It is a action option.\n\
208 If it is combined with other action options, the later\n\
209 input action option will override the previous one.\n");
210 fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
211 It also zeros the time stamp fields.\n\
212 This option can be used to compare the binary efi image.\n\
213 It can't be combined with other action options\n\
214 except for -o, -r option. It is a action option.\n\
215 If it is combined with other action options, the later\n\
216 input action option will override the previous one.\n");
217 fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
218 It can't be combined with other action options\n\
219 except for -o, -r option. It is a action option.\n\
220 If it is combined with other action options, the later\n\
221 input action option will override the previous one.\n");;
222 fprintf (stdout, " -l, --stripped Relocation info stripped from the input PE or TE image.\n\
223 It can't be combined with other action options\n\
224 except for -o, -r option. It is a action option.\n\
225 If it is combined with other action options, the later\n\
226 input action option will override the previous one.\n");
227 fprintf (stdout, " -s timedate, --stamp timedate\n\
228 timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
229 is set to NOW, current system time is used. The support\n\
230 date scope is 1970-1-1 8:0:0 ~ 2038-1-19 3:14:07\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, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
236 It can't be combined with other action options\n\
237 except for -o option. It is a action option.\n\
238 If it is combined with other action options, the later\n\
239 input action option will override the previous one.\n");
240 fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\
241 It can be specified with -a, -p, -o option.\n\
242 No other options can be combined with it.\n\
243 If it is combined with other action options, the later\n\
244 input action option will override the previous one.\n");
245 fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
246 This option is only used together with -j option.\n");
247 fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
248 This option is only used together with -j option.\n");
249 fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\
250 This option can be used together with -e or -t.\n\
251 It doesn't work for other options.\n");
252 fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\
253 This option can be used together with -e or -t.\n\
254 It doesn't work for other options.\n");
255 fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\
256 If more input files are specified,\n\
257 the last input file will be as the output file.\n");
258 fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
259 fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
260 fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
261 fprintf (stdout, " --version Show program's version number and exit\n");
262 fprintf (stdout, " -h, --help Show this help message and exit\n");
263 }
264
265 STATIC
266 STATUS
267 CheckAcpiTable (
268 VOID *AcpiTable,
269 UINT32 Length
270 )
271 /*++
272
273 Routine Description:
274
275 Check Acpi Table
276
277 Arguments:
278
279 AcpiTable Buffer for AcpiSection
280 Length AcpiSection Length
281
282 Returns:
283
284 0 success
285 non-zero otherwise
286
287 --*/
288 {
289 EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;
290 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
291 UINT32 ExpectedLength;
292
293 AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
294
295 //
296 // Generic check for AcpiTable length.
297 //
298 if (AcpiHeader->Length > Length) {
299 Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);
300 return STATUS_ERROR;
301 }
302
303 //
304 // Currently, we only check must-have tables: FADT, FACS, DSDT,
305 // and some important tables: MADT, MCFG.
306 //
307 switch (AcpiHeader->Signature) {
308
309 //
310 // "FACP" Fixed ACPI Description Table
311 //
312 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
313 switch (AcpiHeader->Revision) {
314 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
315 ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
316 break;
317 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
318 ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
319 break;
320 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
321 ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
322 break;
323 default:
324 Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");
325 return STATUS_ERROR;
326 }
327 if (ExpectedLength != AcpiHeader->Length) {
328 Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");
329 return STATUS_ERROR;
330 }
331 break;
332
333 //
334 // "FACS" Firmware ACPI Control Structure
335 //
336 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
337 Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
338 if ((Facs->Version != 0) &&
339 (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
340 (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){
341 Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");
342 return STATUS_ERROR;
343 }
344 if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
345 (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
346 (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
347 Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");
348 return STATUS_ERROR;
349 }
350 break;
351
352 //
353 // "DSDT" Differentiated System Description Table
354 //
355 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
356 if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
357 Error (NULL, 0, 3000, "Invalid", "DSDT revision check failed.");
358 return STATUS_ERROR;
359 }
360 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
361 Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");
362 return STATUS_ERROR;
363 }
364 break;
365
366 //
367 // "APIC" Multiple APIC Description Table
368 //
369 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
370 if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
371 (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
372 (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
373 Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");
374 return STATUS_ERROR;
375 }
376 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {
377 Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");
378 return STATUS_ERROR;
379 }
380 break;
381
382 //
383 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
384 //
385 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
386 if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
387 Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");
388 return STATUS_ERROR;
389 }
390 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {
391 Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");
392 return STATUS_ERROR;
393 }
394 break;
395
396 //
397 // Other table pass check
398 //
399 default:
400 break;
401 }
402
403 return STATUS_SUCCESS;
404 }
405
406
407 INTN
408 IsElfHeader(
409 UINT8 *FileBuffer
410 )
411 {
412 return (FileBuffer[EI_MAG0] == ELFMAG0
413 && FileBuffer[EI_MAG1] == ELFMAG1
414 && FileBuffer[EI_MAG2] == ELFMAG2
415 && FileBuffer[EI_MAG3] == ELFMAG3);
416 }
417
418 typedef Elf32_Shdr Elf_Shdr;
419 typedef Elf32_Ehdr Elf_Ehdr;
420 typedef Elf32_Rel Elf_Rel;
421 typedef Elf32_Sym Elf_Sym;
422 typedef Elf32_Phdr Elf_Phdr;
423 typedef Elf32_Dyn Elf_Dyn;
424
425 #define ELFCLASS ELFCLASS32
426 #define ELF_R_TYPE(r) ELF32_R_TYPE(r)
427 #define ELF_R_SYM(r) ELF32_R_SYM(r)
428
429 //
430 // Well known ELF structures.
431 //
432 Elf_Ehdr *Ehdr;
433 Elf_Shdr *ShdrBase;
434 Elf_Phdr *gPhdrBase;
435
436 //
437 // PE section alignment.
438 //
439 const UINT32 CoffAlignment = 0x20;
440 const UINT32 CoffNbrSections = 4;
441
442 //
443 // Current offset in coff file.
444 //
445 UINT32 CoffOffset;
446
447 //
448 // Result Coff file in memory.
449 //
450 UINT8 *CoffFile = NULL;
451 //
452 // ELF sections to offset in Coff file.
453 //
454 UINT32 *CoffSectionsOffset = NULL;
455
456 //
457 // Offset in Coff file of headers and sections.
458 //
459 UINT32 NtHdrOffset;
460 UINT32 TableOffset;
461 UINT32 TextOffset;
462 UINT32 DataOffset;
463 UINT32 RelocOffset;
464
465 EFI_IMAGE_BASE_RELOCATION *CoffBaseRel;
466 UINT16 *CoffEntryRel;
467
468 UINT32
469 CoffAlign(
470 UINT32 Offset
471 )
472 {
473 return (Offset + CoffAlignment - 1) & ~(CoffAlignment - 1);
474 }
475
476 Elf_Shdr *
477 GetShdrByIndex(
478 UINT32 Num
479 )
480 {
481 if (Num >= Ehdr->e_shnum)
482 return NULL;
483 return (Elf_Shdr*)((UINT8*)ShdrBase + Num * Ehdr->e_shentsize);
484 }
485
486 INTN
487 CheckElfHeader(
488 VOID
489 )
490 {
491 //
492 // Note: Magic has already been tested.
493 //
494 if (Ehdr->e_ident[EI_CLASS] != ELFCLASS) {
495 Error (NULL, 0, 3000, "Unsupported", "%s needs to be ported for 64-bit ELF.", mInImageName);
496 return 0;
497 }
498 if (Ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
499 Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB");
500 return 0;
501 }
502 if ((Ehdr->e_type != ET_EXEC) && (Ehdr->e_type != ET_DYN)) {
503 Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN");
504 return 0;
505 }
506 if (!((Ehdr->e_machine == EM_386) || (Ehdr->e_machine == EM_ARM))) {
507 Error (NULL, 0, 3000, "Unsupported", "ELF e_machine not EM_386 or EM_ARM");
508 return 0;
509 }
510 if (Ehdr->e_version != EV_CURRENT) {
511 Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%d) not EV_CURRENT (%d)", Ehdr->e_version, EV_CURRENT);
512 return 0;
513 }
514
515 //
516 // Find the section header table
517 //
518 ShdrBase = (Elf_Shdr *)((UINT8 *)Ehdr + Ehdr->e_shoff);
519 gPhdrBase = (Elf_Phdr *)((UINT8 *)Ehdr + Ehdr->e_phoff);
520
521 CoffSectionsOffset = (UINT32 *)malloc(Ehdr->e_shnum * sizeof (UINT32));
522
523 memset(CoffSectionsOffset, 0, Ehdr->e_shnum * sizeof(UINT32));
524 return 1;
525 }
526
527 int
528 IsTextShdr(
529 Elf_Shdr *Shdr
530 )
531 {
532 return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC;
533 }
534
535 int
536 IsDataShdr(
537 Elf_Shdr *Shdr
538 )
539 {
540 return (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE);
541 }
542
543 VOID
544 CreateSectionHeader(
545 const CHAR8 *Name,
546 UINT32 Offset,
547 UINT32 Size,
548 UINT32 Flags
549 )
550 {
551 EFI_IMAGE_SECTION_HEADER *Hdr;
552 Hdr = (EFI_IMAGE_SECTION_HEADER*)(CoffFile + TableOffset);
553
554 strcpy((char *)Hdr->Name, Name);
555 Hdr->Misc.VirtualSize = Size;
556 Hdr->VirtualAddress = Offset;
557 Hdr->SizeOfRawData = Size;
558 Hdr->PointerToRawData = Offset;
559 Hdr->PointerToRelocations = 0;
560 Hdr->PointerToLinenumbers = 0;
561 Hdr->NumberOfRelocations = 0;
562 Hdr->NumberOfLinenumbers = 0;
563 Hdr->Characteristics = Flags;
564
565 TableOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
566 }
567
568 VOID
569 ScanSections(
570 VOID
571 )
572 {
573 UINT32 i;
574 EFI_IMAGE_DOS_HEADER *DosHdr;
575 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
576 UINT32 CoffEntry;
577
578 CoffEntry = 0;
579 CoffOffset = 0;
580
581 //
582 // Coff file start with a DOS header.
583 //
584 CoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40;
585 NtHdrOffset = CoffOffset;
586 CoffOffset += sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION);
587 TableOffset = CoffOffset;
588 CoffOffset += CoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER);
589
590 //
591 // First text sections.
592 //
593 CoffOffset = CoffAlign(CoffOffset);
594 TextOffset = CoffOffset;
595 for (i = 0; i < Ehdr->e_shnum; i++) {
596 Elf_Shdr *shdr = GetShdrByIndex(i);
597 if (IsTextShdr(shdr)) {
598 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
599 // the alignment field is valid
600 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
601 // if the section address is aligned we must align PE/COFF
602 CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
603 } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {
604 // ARM RVCT tools have behavior outside of the ELF specification to try
605 // and make images smaller. If sh_addr is not aligned to sh_addralign
606 // then the section needs to preserve sh_addr MOD sh_addralign.
607 // Normally doing nothing here works great.
608 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");
609 }
610 }
611
612 /* Relocate entry. */
613 if ((Ehdr->e_entry >= shdr->sh_addr) &&
614 (Ehdr->e_entry < shdr->sh_addr + shdr->sh_size)) {
615 CoffEntry = CoffOffset + Ehdr->e_entry - shdr->sh_addr;
616 }
617 CoffSectionsOffset[i] = CoffOffset;
618 CoffOffset += shdr->sh_size;
619 }
620 }
621
622 if (Ehdr->e_machine != EM_ARM) {
623 CoffOffset = CoffAlign(CoffOffset);
624 }
625
626 //
627 // Then data sections.
628 //
629 DataOffset = CoffOffset;
630 for (i = 0; i < Ehdr->e_shnum; i++) {
631 Elf_Shdr *shdr = GetShdrByIndex(i);
632 if (IsDataShdr(shdr)) {
633 if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) {
634 // the alignment field is valid
635 if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) {
636 // if the section address is aligned we must align PE/COFF
637 CoffOffset = (CoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1);
638 } else if ((shdr->sh_addr % shdr->sh_addralign) != (CoffOffset % shdr->sh_addralign)) {
639 // ARM RVCT tools have behavior outside of the ELF specification to try
640 // and make images smaller. If sh_addr is not aligned to sh_addralign
641 // then the section needs to preserve sh_addr MOD sh_addralign.
642 // Normally doing nothing here works great.
643 Error (NULL, 0, 3000, "Invalid", "Unsupported section alignment.");
644 }
645 }
646
647 CoffSectionsOffset[i] = CoffOffset;
648 CoffOffset += shdr->sh_size;
649 }
650 }
651 CoffOffset = CoffAlign(CoffOffset);
652
653 RelocOffset = CoffOffset;
654
655 //
656 // Allocate base Coff file. Will be expanded later for relocations.
657 //
658 CoffFile = (UINT8 *)malloc(CoffOffset);
659 memset(CoffFile, 0, CoffOffset);
660
661 //
662 // Fill headers.
663 //
664 DosHdr = (EFI_IMAGE_DOS_HEADER *)CoffFile;
665 DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE;
666 DosHdr->e_lfanew = NtHdrOffset;
667
668 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(CoffFile + NtHdrOffset);
669
670 NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE;
671
672 switch (Ehdr->e_machine) {
673 case EM_386:
674 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
675 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
676 break;
677 case EM_X86_64:
678 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_X64;
679 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
680 break;
681 case EM_IA_64:
682 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IPF;
683 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
684 break;
685 case EM_ARM:
686 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT;
687 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
688 break;
689 default:
690 VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)Ehdr->e_machine);
691 NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32;
692 NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
693 }
694
695 NtHdr->Pe32.FileHeader.NumberOfSections = CoffNbrSections;
696 NtHdr->Pe32.FileHeader.TimeDateStamp = time(NULL);
697 NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
698 NtHdr->Pe32.FileHeader.NumberOfSymbols = 0;
699 NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader);
700 NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE
701 | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED
702 | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED
703 | EFI_IMAGE_FILE_32BIT_MACHINE;
704
705 NtHdr->Pe32.OptionalHeader.SizeOfCode = DataOffset - TextOffset;
706 NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = RelocOffset - DataOffset;
707 NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0;
708 NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry;
709
710 NtHdr->Pe32.OptionalHeader.BaseOfCode = TextOffset;
711
712 NtHdr->Pe32.OptionalHeader.BaseOfData = DataOffset;
713 NtHdr->Pe32.OptionalHeader.ImageBase = 0;
714 NtHdr->Pe32.OptionalHeader.SectionAlignment = CoffAlignment;
715 NtHdr->Pe32.OptionalHeader.FileAlignment = CoffAlignment;
716 NtHdr->Pe32.OptionalHeader.SizeOfImage = 0;
717
718 NtHdr->Pe32.OptionalHeader.SizeOfHeaders = TextOffset;
719 NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES;
720
721 //
722 // Section headers.
723 //
724 if ((DataOffset - TextOffset) > 0) {
725 CreateSectionHeader (".text", TextOffset, DataOffset - TextOffset,
726 EFI_IMAGE_SCN_CNT_CODE
727 | EFI_IMAGE_SCN_MEM_EXECUTE
728 | EFI_IMAGE_SCN_MEM_READ);
729 } else {
730 // Don't make a section of size 0.
731 NtHdr->Pe32.FileHeader.NumberOfSections--;
732 }
733
734 if ((RelocOffset - TextOffset) > 0) {
735 CreateSectionHeader (".data", DataOffset, RelocOffset - DataOffset,
736 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
737 | EFI_IMAGE_SCN_MEM_WRITE
738 | EFI_IMAGE_SCN_MEM_READ);
739 } else {
740 // Don't make a section of size 0.
741 NtHdr->Pe32.FileHeader.NumberOfSections--;
742 }
743 }
744
745 VOID
746 WriteSections(
747 int (*Filter)(Elf_Shdr *)
748 )
749 {
750 UINT32 Idx;
751 Elf_Shdr *SecShdr;
752 UINT32 SecOffset;
753
754 //
755 // First: copy sections.
756 //
757 for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
758 Elf_Shdr *Shdr = GetShdrByIndex(Idx);
759 if ((*Filter)(Shdr)) {
760 switch (Shdr->sh_type) {
761 case SHT_PROGBITS:
762 /* Copy. */
763 memcpy(CoffFile + CoffSectionsOffset[Idx],
764 (UINT8*)Ehdr + Shdr->sh_offset,
765 Shdr->sh_size);
766 break;
767
768 case SHT_NOBITS:
769 memset(CoffFile + CoffSectionsOffset[Idx], 0, Shdr->sh_size);
770 break;
771
772 default:
773 //
774 // Ignore for unkown section type.
775 //
776 VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (UINTN)Shdr->sh_type);
777 break;
778 }
779 }
780 }
781
782 //
783 // Second: apply relocations.
784 //
785 for (Idx = 0; Idx < Ehdr->e_shnum; Idx++) {
786 Elf_Shdr *RelShdr = GetShdrByIndex(Idx);
787 if (RelShdr->sh_type != SHT_REL)
788 continue;
789 SecShdr = GetShdrByIndex(RelShdr->sh_info);
790 SecOffset = CoffSectionsOffset[RelShdr->sh_info];
791 if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) {
792 UINT32 RelIdx;
793 Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link);
794 UINT8 *Symtab = (UINT8*)Ehdr + SymtabShdr->sh_offset;
795
796 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
797 Elf_Rel *Rel = (Elf_Rel *)((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
798 Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize);
799 Elf_Shdr *SymShdr;
800 UINT8 *Targ;
801
802 if (Sym->st_shndx == SHN_UNDEF
803 || Sym->st_shndx == SHN_ABS
804 || Sym->st_shndx > Ehdr->e_shnum) {
805 Error (NULL, 0, 3000, "Invalid", "%s bad symbol definition.", mInImageName);
806 }
807 SymShdr = GetShdrByIndex(Sym->st_shndx);
808
809 //
810 // Note: r_offset in a memory address.
811 // Convert it to a pointer in the coff file.
812 //
813 Targ = CoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr);
814
815 if (Ehdr->e_machine == EM_386) {
816 switch (ELF_R_TYPE(Rel->r_info)) {
817 case R_386_NONE:
818 break;
819 case R_386_32:
820 //
821 // Absolute relocation.
822 //
823 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr
824 + CoffSectionsOffset[Sym->st_shndx];
825 break;
826 case R_386_PC32:
827 //
828 // Relative relocation: Symbol - Ip + Addend
829 //
830 *(UINT32 *)Targ = *(UINT32 *)Targ
831 + (CoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr)
832 - (SecOffset - SecShdr->sh_addr);
833 break;
834 default:
835 Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));
836 }
837 } else if (Ehdr->e_machine == EM_ARM) {
838 switch (ELF32_R_TYPE(Rel->r_info)) {
839 case R_ARM_RBASE: // No relocation - no action required
840 case R_ARM_PC24: // PC-relative relocations don't require modification
841 case R_ARM_XPC25: // PC-relative relocations don't require modification
842 break;
843 case R_ARM_ABS32:
844 case R_ARM_RABS32:
845 //
846 // Absolute relocation.
847 //
848 *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + CoffSectionsOffset[Sym->st_shndx];
849 break;
850 default:
851 Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));
852 }
853 }
854 }
855 }
856 }
857 }
858
859 VOID
860 CoffAddFixupEntry(
861 UINT16 Val
862 )
863 {
864 *CoffEntryRel = Val;
865 CoffEntryRel++;
866 CoffBaseRel->SizeOfBlock += 2;
867 CoffOffset += 2;
868 }
869
870 VOID
871 CoffAddFixup(
872 UINT32 Offset,
873 UINT8 Type
874 )
875 {
876 if (CoffBaseRel == NULL
877 || CoffBaseRel->VirtualAddress != (Offset & ~0xfff)) {
878 if (CoffBaseRel != NULL) {
879 //
880 // Add a null entry (is it required ?)
881 //
882 CoffAddFixupEntry (0);
883 //
884 // Pad for alignment.
885 //
886 if (CoffOffset % 4 != 0)
887 CoffAddFixupEntry (0);
888 }
889
890 CoffFile = realloc
891 (CoffFile,
892 CoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
893 memset(CoffFile + CoffOffset, 0,
894 sizeof(EFI_IMAGE_BASE_RELOCATION) + 2*0x1000);
895
896 CoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(CoffFile + CoffOffset);
897 CoffBaseRel->VirtualAddress = Offset & ~0xfff;
898 CoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION);
899
900 CoffEntryRel = (UINT16 *)(CoffBaseRel + 1);
901 CoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION);
902 }
903
904 //
905 // Fill the entry.
906 //
907 CoffAddFixupEntry((Type << 12) | (Offset & 0xfff));
908 }
909
910
911 Elf_Phdr *
912 GetPhdrByIndex (
913 UINT32 num
914 )
915 {
916 if (num >= Ehdr->e_phnum) {
917 return NULL;
918 }
919
920 return (Elf32_Phdr *)((UINT8*)gPhdrBase + num * Ehdr->e_phentsize);
921 }
922
923
924 VOID
925 WriteRelocations(
926 VOID
927 )
928 {
929 UINT32 Index;
930 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
931 EFI_IMAGE_DATA_DIRECTORY *Dir;
932 BOOLEAN FoundRelocations;
933 Elf_Dyn *Dyn;
934 Elf_Rel *Rel;
935 UINTN RelElementSize;
936 UINTN RelSize;
937 UINTN RelOffset;
938 UINTN K;
939 UINT8 *Targ;
940 Elf32_Phdr *DynamicSegment;
941 Elf32_Phdr *TargetSegment;
942
943 for (Index = 0, FoundRelocations = FALSE; Index < Ehdr->e_shnum; Index++) {
944 Elf_Shdr *RelShdr = GetShdrByIndex(Index);
945 if (RelShdr->sh_type == SHT_REL) {
946 Elf_Shdr *SecShdr = GetShdrByIndex(RelShdr->sh_info);
947 if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) {
948 UINT32 RelIdx;
949 FoundRelocations = TRUE;
950 for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) {
951 Elf_Rel *Rel = (Elf_Rel *)
952 ((UINT8*)Ehdr + RelShdr->sh_offset + RelIdx);
953
954 if (Ehdr->e_machine == EM_386) {
955 switch (ELF_R_TYPE(Rel->r_info)) {
956 case R_386_NONE:
957 case R_386_PC32:
958 break;
959 case R_386_32:
960 CoffAddFixup(CoffSectionsOffset[RelShdr->sh_info]
961 + (Rel->r_offset - SecShdr->sh_addr),
962 EFI_IMAGE_REL_BASED_HIGHLOW);
963 break;
964 default:
965 Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF_R_TYPE(Rel->r_info));
966 }
967 } else if (Ehdr->e_machine == EM_ARM) {
968 switch (ELF32_R_TYPE(Rel->r_info)) {
969 case R_ARM_RBASE:
970 case R_ARM_PC24:
971 case R_ARM_XPC25:
972 break;
973 case R_ARM_ABS32:
974 case R_ARM_RABS32:
975 CoffAddFixup (
976 CoffSectionsOffset[RelShdr->sh_info]
977 + (Rel->r_offset - SecShdr->sh_addr),
978 EFI_IMAGE_REL_BASED_HIGHLOW
979 );
980 break;
981 default:
982 Error (NULL, 0, 3000, "Invalid", "%s unhandled section type %x.", mInImageName, ELF32_R_TYPE(Rel->r_info));
983 }
984 } else {
985 Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %d (processor type).", Ehdr->e_machine);
986 }
987 }
988 }
989 }
990 }
991
992 if (!FoundRelocations && (Ehdr->e_machine == EM_ARM)) {
993 /* Try again, but look for PT_DYNAMIC instead of SHT_REL */
994
995 for (Index = 0; Index < Ehdr->e_phnum; Index++) {
996 RelElementSize = 0;
997 RelSize = 0;
998 RelOffset = 0;
999
1000 DynamicSegment = GetPhdrByIndex (Index);
1001
1002 if (DynamicSegment->p_type == PT_DYNAMIC) {
1003 Dyn = (Elf32_Dyn *) ((UINT8 *)Ehdr + DynamicSegment->p_offset);
1004
1005 while (Dyn->d_tag != DT_NULL) {
1006 switch (Dyn->d_tag) {
1007 case DT_REL:
1008 RelOffset = Dyn->d_un.d_val;
1009 break;
1010
1011 case DT_RELSZ:
1012 RelSize = Dyn->d_un.d_val;
1013 break;
1014
1015 case DT_RELENT:
1016 RelElementSize = Dyn->d_un.d_val;
1017 break;
1018 }
1019 Dyn++;
1020 }
1021 if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) {
1022 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName);
1023 }
1024
1025 for (K = 0; K < RelSize; K += RelElementSize) {
1026
1027 Rel = (Elf32_Rel *) ((UINT8 *) Ehdr + DynamicSegment->p_offset + RelOffset + K);
1028
1029 switch (ELF32_R_TYPE (Rel->r_info)) {
1030 case R_ARM_RBASE:
1031 break;
1032 case R_ARM_RABS32:
1033 TargetSegment = GetPhdrByIndex (ELF32_R_SYM (Rel->r_info) - 1);
1034
1035 // Note: r_offset in a memory address. Convert it to a pointer in the coff file.
1036 Targ = CoffFile + CoffSectionsOffset[ ELF32_R_SYM( Rel->r_info ) ] + Rel->r_offset - TargetSegment->p_vaddr;
1037
1038 *(UINT32 *)Targ = *(UINT32 *)Targ + CoffSectionsOffset [ELF32_R_SYM( Rel->r_info )];
1039
1040 CoffAddFixup (CoffSectionsOffset[ELF32_R_SYM (Rel->r_info)] + (Rel->r_offset - TargetSegment->p_vaddr), EFI_IMAGE_REL_BASED_HIGHLOW);
1041 break;
1042 default:
1043 Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unkown type.", mInImageName);
1044 }
1045 }
1046 break;
1047 }
1048 }
1049 }
1050
1051 //
1052 // Pad by adding empty entries.
1053 //
1054 while (CoffOffset & (CoffAlignment - 1)) {
1055 CoffAddFixupEntry(0);
1056 }
1057
1058
1059 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
1060 Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
1061 Dir->Size = CoffOffset - RelocOffset;
1062 if (Dir->Size == 0) {
1063 // If no relocations, null out the directory entry and don't add the .reloc section
1064 Dir->VirtualAddress = 0;
1065 NtHdr->Pe32.FileHeader.NumberOfSections--;
1066 } else {
1067 Dir->VirtualAddress = RelocOffset;
1068 CreateSectionHeader (".reloc", RelocOffset, CoffOffset - RelocOffset,
1069 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1070 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1071 | EFI_IMAGE_SCN_MEM_READ);
1072 }
1073
1074 }
1075
1076 VOID
1077 WriteDebug(
1078 VOID
1079 )
1080 {
1081 UINT32 Len;
1082 UINT32 DebugOffset;
1083 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
1084 EFI_IMAGE_DATA_DIRECTORY *DataDir;
1085 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir;
1086 EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10;
1087
1088 Len = strlen(mInImageName) + 1;
1089 DebugOffset = CoffOffset;
1090
1091 CoffOffset += sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)
1092 + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)
1093 + Len;
1094 CoffOffset = CoffAlign(CoffOffset);
1095
1096 CoffFile = realloc(CoffFile, CoffOffset);
1097 memset(CoffFile + DebugOffset, 0, CoffOffset - DebugOffset);
1098
1099 Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(CoffFile + DebugOffset);
1100 Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW;
1101 Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len;
1102 Dir->RVA = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
1103 Dir->FileOffset = DebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
1104
1105 Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1);
1106 Nb10->Signature = CODEVIEW_SIGNATURE_NB10;
1107 strcpy ((char *)(Nb10 + 1), mInImageName);
1108
1109
1110 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
1111 DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG];
1112 DataDir->VirtualAddress = DebugOffset;
1113 DataDir->Size = CoffOffset - DebugOffset;
1114 if (DataDir->Size == 0) {
1115 // If no debug, null out the directory entry and don't add the .debug section
1116 DataDir->VirtualAddress = 0;
1117 NtHdr->Pe32.FileHeader.NumberOfSections--;
1118 } else {
1119 DataDir->VirtualAddress = DebugOffset;
1120 CreateSectionHeader (".debug", DebugOffset, CoffOffset - DebugOffset,
1121 EFI_IMAGE_SCN_CNT_INITIALIZED_DATA
1122 | EFI_IMAGE_SCN_MEM_DISCARDABLE
1123 | EFI_IMAGE_SCN_MEM_READ);
1124
1125 }
1126 }
1127
1128 VOID
1129 ConvertElf (
1130 UINT8 **FileBuffer,
1131 UINT32 *FileLength
1132 )
1133 {
1134 EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
1135
1136 //
1137 // Check header, read section table.
1138 //
1139 Ehdr = (Elf32_Ehdr*)*FileBuffer;
1140 if (!CheckElfHeader())
1141 return;
1142
1143 VerboseMsg ("Check Efl Image Header");
1144 //
1145 // Compute sections new address.
1146 //
1147 ScanSections();
1148
1149 VerboseMsg ("Compute sections new address.");
1150
1151 //
1152 // Write and relocate sections.
1153 //
1154 WriteSections(IsTextShdr);
1155 WriteSections(IsDataShdr);
1156 VerboseMsg ("Write and relocate sections.");
1157
1158 //
1159 // Translate and write relocations.
1160 //
1161 WriteRelocations();
1162 VerboseMsg ("Translate and write relocations.");
1163
1164 //
1165 // Write debug info.
1166 //
1167 WriteDebug();
1168 VerboseMsg ("Write debug info.");
1169
1170 NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(CoffFile + NtHdrOffset);
1171 NtHdr->Pe32.OptionalHeader.SizeOfImage = CoffOffset;
1172
1173 //
1174 // Replace.
1175 //
1176 free(*FileBuffer);
1177 *FileBuffer = CoffFile;
1178 *FileLength = CoffOffset;
1179
1180 //
1181 // Free memory space
1182 //
1183 if (CoffSectionsOffset != NULL) {
1184 free (CoffSectionsOffset);
1185 }
1186 }
1187
1188 void
1189 ZeroXdataSection (
1190 IN CHAR8 *ImageName,
1191 IN OUT UINT8 *FileBuffer,
1192 IN EFI_IMAGE_SECTION_HEADER *SectionHeader,
1193 IN UINT32 SectionTotalNumber
1194 )
1195 {
1196 FILE *fpMapFile;
1197 CHAR8 MapFileName[_MAX_PATH];
1198 CHAR8 Line [MAX_LINE_LEN];
1199 CHAR8 KeyWord [MAX_LINE_LEN];
1200 CHAR8 SectionName [MAX_LINE_LEN];
1201 UINT32 FunctionType = 0;
1202 UINT32 SectionOffset;
1203 UINT32 SectionLength;
1204 UINT32 SectionNumber;
1205 CHAR8 *PdbPointer;
1206 INT32 Index = 0;
1207
1208 for (Index = 0; Index < SectionTotalNumber; Index ++) {
1209 if (stricmp ((char *)SectionHeader[Index].Name, ".zdata") == 0) {
1210 //
1211 // try to zero the customized .zdata section, which is mapped to .xdata
1212 //
1213 memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);
1214 DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[Index].PointerToRawData, SectionHeader[Index].SizeOfRawData);
1215 return;
1216 }
1217 }
1218 //
1219 // Try to get PDB file name
1220 //
1221 PdbPointer = (CHAR8 *) PeCoffLoaderGetPdbPointer (FileBuffer);
1222 if (PdbPointer != NULL) {
1223 strcpy (MapFileName, PdbPointer);
1224 } else {
1225 strcpy (MapFileName, ImageName);
1226 }
1227
1228 //
1229 // Construct map file name
1230 //
1231 Index = strlen (MapFileName) - 1;
1232 while (Index >= 0 && MapFileName[Index] != '.') {
1233 Index --;
1234 }
1235 if (Index < 0) {
1236 //
1237 // don't know how to costruct map file
1238 //
1239 return;
1240 }
1241
1242 //
1243 // fill map file postfix
1244 //
1245 MapFileName[Index + 1] = 'm';
1246 MapFileName[Index + 2] = 'a';
1247 MapFileName[Index + 3] = 'p';
1248 MapFileName[Index + 4] = '\0';
1249
1250 //
1251 // try opening Map File
1252 //
1253 fpMapFile = fopen (MapFileName, "r");
1254 if (fpMapFile == NULL) {
1255 //
1256 // Can't open Map file. Maybe it doesn't exist.
1257 //
1258 return;
1259 }
1260
1261 //
1262 // Output Functions information into Fv Map file
1263 //
1264 while (fgets (Line, MAX_LINE_LEN, fpMapFile) != NULL) {
1265 //
1266 // Skip blank line
1267 //
1268 if (Line[0] == 0x0a) {
1269 if (FunctionType != 0) {
1270 //
1271 // read all section table data
1272 //
1273 FunctionType = 0;
1274 break;
1275 }
1276 FunctionType = 0;
1277 continue;
1278 }
1279
1280 //
1281 // By Start keyword
1282 //
1283 if (FunctionType == 0) {
1284 sscanf (Line, "%s", KeyWord);
1285 if (stricmp (KeyWord, "Start") == 0) {
1286 //
1287 // function list
1288 //
1289 FunctionType = 1;
1290 }
1291 continue;
1292 }
1293 //
1294 // Printf Function Information
1295 //
1296 if (FunctionType == 1) {
1297 sscanf (Line, "%x:%x %xH %s", &SectionNumber, &SectionOffset, &SectionLength, SectionName);
1298 if (stricmp (SectionName, ".xdata") == 0) {
1299 FunctionType = 2;
1300 break;
1301 }
1302 }
1303 }
1304
1305 if (FunctionType != 2) {
1306 //
1307 // no .xdata section is found
1308 //
1309 fclose (fpMapFile);
1310 return;
1311 }
1312
1313 //
1314 // Zero .xdata Section data
1315 //
1316 memset (FileBuffer + SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, 0, SectionLength);
1317 DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", SectionHeader[SectionNumber-1].PointerToRawData + SectionOffset, SectionLength);
1318 fclose (fpMapFile);
1319 return;
1320 }
1321
1322 int
1323 main (
1324 int argc,
1325 char *argv[]
1326 )
1327 /*++
1328
1329 Routine Description:
1330
1331 Main function.
1332
1333 Arguments:
1334
1335 argc - Number of command line parameters.
1336 argv - Array of pointers to command line parameter strings.
1337
1338 Returns:
1339 STATUS_SUCCESS - Utility exits successfully.
1340 STATUS_ERROR - Some error occurred during execution.
1341
1342 --*/
1343 {
1344 UINT32 Type;
1345 UINT32 InputFileNum;
1346 CHAR8 **InputFileName;
1347 char *OutImageName;
1348 char *ModuleType;
1349 CHAR8 *TimeStamp;
1350 UINT32 OutImageType;
1351 FILE *fpIn;
1352 FILE *fpOut;
1353 FILE *fpInOut;
1354 UINT32 Data;
1355 UINT32 *DataPointer;
1356 UINT32 *OldDataPointer;
1357 UINT32 CheckSum;
1358 UINT32 Index;
1359 UINT32 Index1;
1360 UINT32 Index2;
1361 UINT64 Temp64;
1362 UINT32 MciAlignment;
1363 UINT8 MciPadValue;
1364 UINT32 AllignedRelocSize;
1365 UINT8 *FileBuffer;
1366 UINT32 FileLength;
1367 UINT8 *OutputFileBuffer;
1368 UINT32 OutputFileLength;
1369 RUNTIME_FUNCTION *RuntimeFunction;
1370 UNWIND_INFO *UnwindInfo;
1371 STATUS Status;
1372 BOOLEAN ReplaceFlag;
1373 BOOLEAN KeepExceptionTableFlag;
1374 BOOLEAN KeepZeroPendingFlag;
1375 UINT64 LogLevel;
1376 EFI_TE_IMAGE_HEADER TEImageHeader;
1377 EFI_TE_IMAGE_HEADER *TeHdr;
1378 EFI_IMAGE_SECTION_HEADER *SectionHeader;
1379 EFI_IMAGE_DOS_HEADER *DosHdr;
1380 EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
1381 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
1382 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
1383 EFI_IMAGE_DOS_HEADER BackupDosHdr;
1384 MICROCODE_IMAGE_HEADER *MciHeader;
1385
1386 SetUtilityName (UTILITY_NAME);
1387
1388 //
1389 // Assign to fix compile warning
1390 //
1391 InputFileNum = 0;
1392 InputFileName = NULL;
1393 mInImageName = NULL;
1394 OutImageName = NULL;
1395 ModuleType = NULL;
1396 OutImageType = FW_DUMMY_IMAGE;
1397 Type = 0;
1398 Status = STATUS_SUCCESS;
1399 FileBuffer = NULL;
1400 fpIn = NULL;
1401 fpOut = NULL;
1402 fpInOut = NULL;
1403 TimeStamp = NULL;
1404 MciAlignment = DEFAULT_MC_ALIGNMENT;
1405 MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE;
1406 FileLength = 0;
1407 MciHeader = NULL;
1408 CheckSum = 0;
1409 ReplaceFlag = FALSE;
1410 LogLevel = 0;
1411 OutputFileBuffer = NULL;
1412 OutputFileLength = 0;
1413 Optional32 = NULL;
1414 Optional64 = NULL;
1415 KeepExceptionTableFlag = FALSE;
1416 KeepZeroPendingFlag = FALSE;
1417
1418 if (argc == 1) {
1419 Error (NULL, 0, 1001, "Missing options", "No input options.");
1420 Usage ();
1421 return STATUS_ERROR;
1422 }
1423
1424 argc --;
1425 argv ++;
1426
1427 if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
1428 Version ();
1429 Usage ();
1430 return STATUS_SUCCESS;
1431 }
1432
1433 if (stricmp (argv[0], "--version") == 0) {
1434 Version ();
1435 return STATUS_SUCCESS;
1436 }
1437
1438 while (argc > 0) {
1439 if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
1440 if (argv[1] == NULL || argv[1][0] == '-') {
1441 Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
1442 goto Finish;
1443 }
1444 OutImageName = argv[1];
1445 argc -= 2;
1446 argv += 2;
1447 continue;
1448 }
1449
1450 if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {
1451 if (argv[1] == NULL || argv[1][0] == '-') {
1452 Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
1453 goto Finish;
1454 }
1455 ModuleType = argv[1];
1456 if (OutImageType != FW_TE_IMAGE) {
1457 OutImageType = FW_EFI_IMAGE;
1458 }
1459 argc -= 2;
1460 argv += 2;
1461 continue;
1462 }
1463
1464 if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {
1465 OutImageType = FW_RELOC_STRIPEED_IMAGE;
1466 argc --;
1467 argv ++;
1468 continue;
1469 }
1470
1471 if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {
1472 OutImageType = FW_ACPI_IMAGE;
1473 argc --;
1474 argv ++;
1475 continue;
1476 }
1477
1478 if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {
1479 OutImageType = FW_TE_IMAGE;
1480 argc --;
1481 argv ++;
1482 continue;
1483 }
1484
1485 if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {
1486 OutImageType = DUMP_TE_HEADER;
1487 argc --;
1488 argv ++;
1489 continue;
1490 }
1491
1492 if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {
1493 OutImageType = FW_BIN_IMAGE;
1494 argc --;
1495 argv ++;
1496 continue;
1497 }
1498
1499 if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {
1500 OutImageType = FW_ZERO_DEBUG_IMAGE;
1501 argc --;
1502 argv ++;
1503 continue;
1504 }
1505
1506 if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {
1507 OutImageType = FW_SET_STAMP_IMAGE;
1508 if (argv[1] == NULL || argv[1][0] == '-') {
1509 Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
1510 goto Finish;
1511 }
1512 TimeStamp = argv[1];
1513 argc -= 2;
1514 argv += 2;
1515 continue;
1516 }
1517
1518 if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {
1519 ReplaceFlag = TRUE;
1520 argc --;
1521 argv ++;
1522 continue;
1523 }
1524
1525 if (stricmp (argv[0], "--keepexceptiontable") == 0) {
1526 KeepExceptionTableFlag = TRUE;
1527 argc --;
1528 argv ++;
1529 continue;
1530 }
1531
1532 if (stricmp (argv[0], "--keepzeropending") == 0) {
1533 KeepZeroPendingFlag = TRUE;
1534 argc --;
1535 argv ++;
1536 continue;
1537 }
1538
1539 if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {
1540 OutImageType = FW_MCI_IMAGE;
1541 argc --;
1542 argv ++;
1543 continue;
1544 }
1545
1546 if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {
1547 OutImageType = FW_MERGE_IMAGE;
1548 argc --;
1549 argv ++;
1550 continue;
1551 }
1552
1553 if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {
1554 if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
1555 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1556 goto Finish;
1557 }
1558 MciAlignment = (UINT32) Temp64;
1559 argc -= 2;
1560 argv += 2;
1561 continue;
1562 }
1563
1564 if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {
1565 if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
1566 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1567 goto Finish;
1568 }
1569 MciPadValue = (UINT8) Temp64;
1570 argc -= 2;
1571 argv += 2;
1572 continue;
1573 }
1574
1575 if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
1576 SetPrintLevel (VERBOSE_LOG_LEVEL);
1577 VerboseMsg ("Verbose output Mode Set!");
1578 argc --;
1579 argv ++;
1580 continue;
1581 }
1582
1583 if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
1584 SetPrintLevel (KEY_LOG_LEVEL);
1585 KeyMsg ("Quiet output Mode Set!");
1586 argc --;
1587 argv ++;
1588 continue;
1589 }
1590
1591 if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
1592 Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
1593 if (EFI_ERROR (Status)) {
1594 Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
1595 goto Finish;
1596 }
1597 if (LogLevel > 9) {
1598 Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, currnt input level is %d", LogLevel);
1599 goto Finish;
1600 }
1601 SetPrintLevel (LogLevel);
1602 DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
1603 argc -= 2;
1604 argv += 2;
1605 continue;
1606 }
1607
1608 if (argv[0][0] == '-') {
1609 Error (NULL, 0, 1000, "Unknown option", argv[0]);
1610 goto Finish;
1611 }
1612 //
1613 // Get Input file name
1614 //
1615 if ((InputFileNum == 0) && (InputFileName == NULL)) {
1616 InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
1617 if (InputFileName == NULL) {
1618 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1619 return EFI_OUT_OF_RESOURCES;
1620 }
1621
1622 memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1623 } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
1624 //
1625 // InputFileName buffer too small, need to realloc
1626 //
1627 InputFileName = (CHAR8 **) realloc (
1628 InputFileName,
1629 (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
1630 );
1631
1632 if (InputFileName == NULL) {
1633 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1634 return EFI_OUT_OF_RESOURCES;
1635 }
1636
1637 memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
1638 }
1639
1640 InputFileName [InputFileNum ++] = argv[0];
1641 argc --;
1642 argv ++;
1643 }
1644
1645 VerboseMsg ("%s tool start.", UTILITY_NAME);
1646
1647 if (OutImageType == FW_DUMMY_IMAGE) {
1648 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!");
1649 if (ReplaceFlag) {
1650 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.");
1651 }
1652 goto Finish;
1653 }
1654
1655 //
1656 // check input files
1657 //
1658 if (InputFileNum == 0) {
1659 Error (NULL, 0, 1001, "Missing option", "Input files");
1660 goto Finish;
1661 }
1662
1663 //
1664 // Combine MciBinary files to one file
1665 //
1666 if ((OutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {
1667 Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
1668 goto Finish;
1669 }
1670
1671 //
1672 // Input image file
1673 //
1674 mInImageName = InputFileName [InputFileNum - 1];
1675 VerboseMsg ("the input file name is %s", mInImageName);
1676
1677 //
1678 // Action will be taken for the input file.
1679 //
1680 switch (OutImageType) {
1681 case FW_EFI_IMAGE:
1682 VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);
1683 break;
1684 case FW_TE_IMAGE:
1685 VerboseMsg ("Create Te Image based on the input PE image.");
1686 break;
1687 case FW_ACPI_IMAGE:
1688 VerboseMsg ("Get acpi table data from the input PE image.");
1689 break;
1690 case FW_RELOC_STRIPEED_IMAGE:
1691 VerboseMsg ("Remove relocation section from Pe or Te image.");
1692 break;
1693 case FW_BIN_IMAGE:
1694 VerboseMsg ("Convert the input EXE to the output BIN file.");
1695 break;
1696 case FW_ZERO_DEBUG_IMAGE:
1697 VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
1698 break;
1699 case FW_SET_STAMP_IMAGE:
1700 VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);
1701 break;
1702 case DUMP_TE_HEADER:
1703 VerboseMsg ("Dump the TE header information of the input TE image.");
1704 break;
1705 case FW_MCI_IMAGE:
1706 VerboseMsg ("Conver input MicroCode.txt file to MicroCode.bin file.");
1707 break;
1708 case FW_MERGE_IMAGE:
1709 VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
1710 break;
1711 default:
1712 break;
1713 }
1714
1715 if (ReplaceFlag) {
1716 VerboseMsg ("Overwrite the input file with the output content.");
1717 }
1718
1719 //
1720 // Open output file and Write image into the output file.
1721 //
1722 if (OutImageName != NULL) {
1723 fpOut = fopen (OutImageName, "rb");
1724 if (fpOut != NULL) {
1725 OutputFileLength = _filelength (fileno (fpOut));
1726 OutputFileBuffer = malloc (OutputFileLength);
1727 if (OutputFileBuffer == NULL) {
1728 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1729 fclose (fpOut);
1730 fpOut = NULL;
1731 goto Finish;
1732 }
1733 fread (OutputFileBuffer, 1, OutputFileLength, fpOut);
1734 fclose (fpOut);
1735 }
1736 fpOut = fopen (OutImageName, "wb");
1737 if (!fpOut) {
1738 Error (NULL, 0, 0001, "Error opening output file", OutImageName);
1739 goto Finish;
1740 }
1741 VerboseMsg ("Output file name is %s", OutImageName);
1742 } else if (!ReplaceFlag) {
1743 if (OutImageType == DUMP_TE_HEADER) {
1744 fpOut = stdout;
1745 } else {
1746 Error (NULL, 0, 1001, "Missing option", "output file");
1747 goto Finish;
1748 }
1749 }
1750
1751 //
1752 // Combine MciBinary files to one file
1753 //
1754 if (OutImageType == FW_MERGE_IMAGE) {
1755 for (Index = 0; Index < InputFileNum; Index ++) {
1756 fpIn = fopen (InputFileName [Index], "rb");
1757 if (!fpIn) {
1758 Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
1759 goto Finish;
1760 }
1761
1762 FileLength = _filelength (fileno (fpIn));
1763 FileBuffer = malloc (FileLength);
1764 if (FileBuffer == NULL) {
1765 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1766 fclose (fpIn);
1767 goto Finish;
1768 }
1769
1770 fread (FileBuffer, 1, FileLength, fpIn);
1771 fclose (fpIn);
1772 //
1773 // write input file to out file
1774 //
1775 fwrite (FileBuffer, 1, FileLength, fpOut);
1776 //
1777 // write pad value to out file.
1778 //
1779 while (FileLength ++ % MciAlignment != 0) {
1780 fwrite (&MciPadValue, 1, 1, fpOut);
1781 }
1782 //
1783 // free allocated memory space
1784 //
1785 free (FileBuffer);
1786 FileBuffer = NULL;
1787 }
1788 //
1789 // Done successfully
1790 //
1791 goto Finish;
1792 }
1793
1794 //
1795 // Convert MicroCode.txt file to MicroCode.bin file
1796 //
1797 if (OutImageType == FW_MCI_IMAGE) {
1798 fpIn = fopen (mInImageName, "r");
1799 if (!fpIn) {
1800 Error (NULL, 0, 0001, "Error opening file", mInImageName);
1801 goto Finish;
1802 }
1803
1804 //
1805 // The first pass is to determine
1806 // how much data is in the file so we can allocate a working buffer.
1807 //
1808 FileLength = 0;
1809 do {
1810 Status = MicrocodeReadData (fpIn, &Data);
1811 if (Status == STATUS_SUCCESS) {
1812 FileLength += sizeof (Data);
1813 }
1814 if (Status == STATUS_IGNORE) {
1815 Status = STATUS_SUCCESS;
1816 }
1817 } while (Status == STATUS_SUCCESS);
1818 //
1819 // Error if no data.
1820 //
1821 if (FileLength == 0) {
1822 Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);
1823 goto Finish;
1824 }
1825 if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {
1826 Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);
1827 goto Finish;
1828 }
1829
1830 //
1831 // Allocate a buffer for the data
1832 //
1833 FileBuffer = malloc (FileLength);
1834 if (FileBuffer == NULL) {
1835 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1836 goto Finish;
1837 }
1838 //
1839 // Re-read the file, storing the data into our buffer
1840 //
1841 fseek (fpIn, 0, SEEK_SET);
1842 DataPointer = (UINT32 *) FileBuffer;
1843 OldDataPointer = DataPointer;
1844 do {
1845 OldDataPointer = DataPointer;
1846 Status = MicrocodeReadData (fpIn, DataPointer++);
1847 if (Status == STATUS_IGNORE) {
1848 DataPointer = OldDataPointer;
1849 Status = STATUS_SUCCESS;
1850 }
1851 } while (Status == STATUS_SUCCESS);
1852 //
1853 // close input file after read data
1854 //
1855 fclose (fpIn);
1856
1857 //
1858 // Can't do much checking on the header because, per the spec, the
1859 // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
1860 // and the TotalSize field is invalid (actually missing). Thus we can't
1861 // even verify the Reserved fields are 0.
1862 //
1863 MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;
1864 if (MciHeader->DataSize == 0) {
1865 Index = 2048;
1866 } else {
1867 Index = MciHeader->TotalSize;
1868 }
1869
1870 if (Index != FileLength) {
1871 Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, FileLength, Index);
1872 goto Finish;
1873 }
1874
1875 //
1876 // Checksum the contents
1877 //
1878 DataPointer = (UINT32 *) FileBuffer;
1879 CheckSum = 0;
1880 Index = 0;
1881 while (Index < FileLength) {
1882 CheckSum += *DataPointer;
1883 DataPointer ++;
1884 Index += sizeof (*DataPointer);
1885 }
1886 if (CheckSum != 0) {
1887 Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", CheckSum, mInImageName);
1888 goto Finish;
1889 }
1890 //
1891 // Open the output file and write the buffer contents
1892 //
1893 if (fpOut != NULL) {
1894 if (fwrite (FileBuffer, FileLength, 1, fpOut) != 1) {
1895 Error (NULL, 0, 0002, "Error writing file", OutImageName);
1896 goto Finish;
1897 }
1898 }
1899
1900 if (ReplaceFlag) {
1901 fpInOut = fopen (mInImageName, "wb");
1902 if (fpInOut != NULL) {
1903 Error (NULL, 0, 0001, "Error opening file", mInImageName);
1904 goto Finish;
1905 }
1906 if (fwrite (FileBuffer, FileLength, 1, fpInOut) != 1) {
1907 Error (NULL, 0, 0002, "Error writing file", mInImageName);
1908 goto Finish;
1909 }
1910 }
1911 VerboseMsg ("the size of output file is %d bytes", FileLength);
1912 //
1913 // Convert Mci.TXT to Mci.bin file successfully
1914 //
1915 goto Finish;
1916 }
1917
1918 //
1919 // Open input file and read file data into file buffer.
1920 //
1921 fpIn = fopen (mInImageName, "rb");
1922 if (!fpIn) {
1923 Error (NULL, 0, 0001, "Error opening file", mInImageName);
1924 goto Finish;
1925 }
1926
1927 FileLength = _filelength (fileno (fpIn));
1928 FileBuffer = malloc (FileLength);
1929 if (FileBuffer == NULL) {
1930 Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
1931 fclose (fpIn);
1932 goto Finish;
1933 }
1934
1935 fread (FileBuffer, 1, FileLength, fpIn);
1936 fclose (fpIn);
1937
1938 DebugMsg (NULL, 0, 9, "input file info", "the input file size is %d bytes", FileLength);
1939
1940 //
1941 // Replace file
1942 //
1943 if (ReplaceFlag) {
1944 fpInOut = fopen (mInImageName, "wb");
1945 if (!fpInOut) {
1946 Error (NULL, 0, 0001, "Error opening file", mInImageName);
1947 goto Finish;
1948 }
1949 }
1950 //
1951 // Dump TeImage Header into output file.
1952 //
1953 if (OutImageType == DUMP_TE_HEADER) {
1954 memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));
1955 if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
1956 Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);
1957 goto Finish;
1958 }
1959 if (fpInOut != NULL) {
1960 fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);
1961 fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");
1962 fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);
1963 fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
1964 fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);
1965 fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
1966 fprintf (fpInOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);
1967 fprintf (fpInOut, "%17X base of code\n", TEImageHeader.BaseOfCode);
1968 fprintf (fpInOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);
1969 fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);
1970 fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);
1971 }
1972
1973 if (fpOut != NULL) {
1974 fprintf (fpOut, "Dump of file %s\n\n", mInImageName);
1975 fprintf (fpOut, "TE IMAGE HEADER VALUES\n");
1976 fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);
1977 fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
1978 fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);
1979 fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
1980 fprintf (fpOut, "%17X entry point\n", TEImageHeader.AddressOfEntryPoint);
1981 fprintf (fpOut, "%17X base of code\n", TEImageHeader.BaseOfCode);
1982 fprintf (fpOut, "%17lX image base\n", (long unsigned int)TEImageHeader.ImageBase);
1983 fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", TEImageHeader.DataDirectory[0].VirtualAddress, TEImageHeader.DataDirectory[0].Size);
1984 fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", TEImageHeader.DataDirectory[1].VirtualAddress, TEImageHeader.DataDirectory[1].Size);
1985 }
1986 goto Finish;
1987 }
1988
1989 //
1990 // Following code to convert dll to efi image or te image.
1991 // Get new image type
1992 //
1993 if ((OutImageType == FW_EFI_IMAGE) || (OutImageType == FW_TE_IMAGE)) {
1994 if (ModuleType == NULL) {
1995 if (OutImageType == FW_EFI_IMAGE) {
1996 Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");
1997 goto Finish;
1998 } else if (OutImageType == FW_TE_IMAGE) {
1999 //
2000 // Default TE Image Type is Boot service driver
2001 //
2002 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
2003 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2004 }
2005 } else {
2006 if (stricmp (ModuleType, "BASE") == 0 ||
2007 stricmp (ModuleType, "SEC") == 0 ||
2008 stricmp (ModuleType, "SECURITY_CORE") == 0 ||
2009 stricmp (ModuleType, "PEI_CORE") == 0 ||
2010 stricmp (ModuleType, "PEIM") == 0 ||
2011 stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||
2012 stricmp (ModuleType, "PIC_PEIM") == 0 ||
2013 stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||
2014 stricmp (ModuleType, "DXE_CORE") == 0 ||
2015 stricmp (ModuleType, "BS_DRIVER") == 0 ||
2016 stricmp (ModuleType, "DXE_DRIVER") == 0 ||
2017 stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 ||
2018 stricmp (ModuleType, "UEFI_DRIVER") == 0 ||
2019 stricmp (ModuleType, "SMM_DRIVER") == 0 ||
2020 stricmp (ModuleType, "SMM_CORE") == 0) {
2021 Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
2022 VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
2023
2024 } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||
2025 stricmp (ModuleType, "APPLICATION") == 0) {
2026 Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
2027 VerboseMsg ("Efi Image subsystem type is efi application.");
2028
2029 } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||
2030 stricmp (ModuleType, "RT_DRIVER") == 0) {
2031 Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
2032 VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
2033
2034 } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||
2035 stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {
2036 Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
2037 VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
2038
2039 } else {
2040 Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);
2041 goto Finish;
2042 }
2043 }
2044 }
2045
2046 //
2047 // Convert EFL image to PeImage
2048 //
2049 if (IsElfHeader(FileBuffer)) {
2050 VerboseMsg ("Convert the input ELF Image to Pe Image");
2051 ConvertElf(&FileBuffer, &FileLength);
2052 }
2053
2054 //
2055 // Remove reloc section from PE or TE image
2056 //
2057 if (OutImageType == FW_RELOC_STRIPEED_IMAGE) {
2058 //
2059 // Check TeImage
2060 //
2061 TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;
2062 if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
2063 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);
2064 for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {
2065 if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
2066 //
2067 // Check the reloc section is in the end of image.
2068 //
2069 if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==
2070 (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {
2071 //
2072 // Remove .reloc section and update TeImage Header
2073 //
2074 FileLength = FileLength - SectionHeader->SizeOfRawData;
2075 SectionHeader->SizeOfRawData = 0;
2076 SectionHeader->Misc.VirtualSize = 0;
2077 TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2078 TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
2079 break;
2080 }
2081 }
2082 }
2083 } else {
2084 //
2085 // Check PE Image
2086 //
2087 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
2088 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2089 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
2090 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2091 Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);
2092 goto Finish;
2093 }
2094 DosHdr = NULL;
2095 } else {
2096 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
2097 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2098 Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
2099 goto Finish;
2100 }
2101 }
2102 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2103 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
2104 if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
2105 //
2106 // Check the reloc section is in the end of image.
2107 //
2108 if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {
2109 //
2110 // Remove .reloc section and update PeImage Header
2111 //
2112 FileLength = FileLength - SectionHeader->SizeOfRawData;
2113
2114 PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
2115 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2116 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2117 Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;
2118 Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
2119 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2120 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2121 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
2122 }
2123 }
2124 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2125 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2126 Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;
2127 Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
2128 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2129 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
2130 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
2131 }
2132 }
2133 SectionHeader->Misc.VirtualSize = 0;
2134 SectionHeader->SizeOfRawData = 0;
2135 break;
2136 }
2137 }
2138 }
2139 }
2140 //
2141 // Write file
2142 //
2143 goto WriteFile;
2144 }
2145 //
2146 // Read the dos & pe hdrs of the image
2147 //
2148 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
2149 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2150 // NO DOS header, check for PE/COFF header
2151 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
2152 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2153 Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);
2154 goto Finish;
2155 }
2156 DosHdr = NULL;
2157 } else {
2158
2159 PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
2160 if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
2161 Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
2162 goto Finish;
2163 }
2164 }
2165
2166 if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
2167 // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
2168 // so patch back to the offical UEFI value.
2169 PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;
2170 }
2171
2172 //
2173 // Extract bin data from Pe image.
2174 //
2175 if (OutImageType == FW_BIN_IMAGE) {
2176 if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
2177 Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);
2178 goto Finish;
2179 }
2180 //
2181 // Output bin data from exe file
2182 //
2183 if (fpOut != NULL) {
2184 fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpOut);
2185 }
2186 if (fpInOut != NULL) {
2187 fwrite (FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, 1, FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders, fpInOut);
2188 }
2189 VerboseMsg ("the size of output file is %d bytes", FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders);
2190 goto Finish;
2191 }
2192
2193 //
2194 // Zero Debug Information of Pe Image
2195 //
2196 if (OutImageType == FW_ZERO_DEBUG_IMAGE) {
2197 Status = ZeroDebugData (FileBuffer, TRUE);
2198 if (EFI_ERROR (Status)) {
2199 Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%lx", (UINTN) Status);
2200 goto Finish;
2201 }
2202
2203 if (fpOut != NULL) {
2204 fwrite (FileBuffer, 1, FileLength, fpOut);
2205 }
2206 if (fpInOut != NULL) {
2207 fwrite (FileBuffer, 1, FileLength, fpInOut);
2208 }
2209 VerboseMsg ("the size of output file is %d bytes", FileLength);
2210 goto Finish;
2211 }
2212
2213 //
2214 // Set Time Stamp of Pe Image
2215 //
2216 if (OutImageType == FW_SET_STAMP_IMAGE) {
2217 Status = SetStamp (FileBuffer, TimeStamp);
2218 if (EFI_ERROR (Status)) {
2219 goto Finish;
2220 }
2221
2222 if (fpOut != NULL) {
2223 fwrite (FileBuffer, 1, FileLength, fpOut);
2224 }
2225 if (fpInOut != NULL) {
2226 fwrite (FileBuffer, 1, FileLength, fpInOut);
2227 }
2228 VerboseMsg ("the size of output file is %d bytes", FileLength);
2229 goto Finish;
2230 }
2231
2232 //
2233 // Extract acpi data from pe image.
2234 //
2235 if (OutImageType == FW_ACPI_IMAGE) {
2236 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2237 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
2238 if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {
2239 //
2240 // Check Acpi Table
2241 //
2242 if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {
2243 FileLength = SectionHeader->Misc.VirtualSize;
2244 } else {
2245 FileLength = SectionHeader->SizeOfRawData;
2246 }
2247
2248 if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {
2249 Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);
2250 goto Finish;
2251 }
2252
2253 //
2254 // Output Apci data to file
2255 //
2256 if (fpOut != NULL) {
2257 fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpOut);
2258 }
2259 if (fpInOut != NULL) {
2260 fwrite (FileBuffer + SectionHeader->PointerToRawData, 1, FileLength, fpInOut);
2261 }
2262 VerboseMsg ("the size of output file is %d bytes", FileLength);
2263 goto Finish;
2264 }
2265 }
2266 Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);
2267 goto Finish;
2268 }
2269 //
2270 // Zero all unused fields of the DOS header
2271 //
2272 if (DosHdr != NULL) {
2273 memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
2274 memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
2275 DosHdr->e_magic = BackupDosHdr.e_magic;
2276 DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
2277
2278 for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {
2279 FileBuffer[Index] = DosHdr->e_cp;
2280 }
2281 }
2282
2283 //
2284 // Initialize TeImage Header
2285 //
2286 memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
2287 TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
2288 TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine;
2289 TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;
2290 TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);
2291 TEImageHeader.Subsystem = (UINT8) Type;
2292
2293 //
2294 // Patch the PE header
2295 //
2296 PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;
2297
2298 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
2299 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
2300 Optional32->MajorLinkerVersion = 0;
2301 Optional32->MinorLinkerVersion = 0;
2302 Optional32->MajorOperatingSystemVersion = 0;
2303 Optional32->MinorOperatingSystemVersion = 0;
2304 Optional32->MajorImageVersion = 0;
2305 Optional32->MinorImageVersion = 0;
2306 Optional32->MajorSubsystemVersion = 0;
2307 Optional32->MinorSubsystemVersion = 0;
2308 Optional32->Win32VersionValue = 0;
2309 Optional32->CheckSum = 0;
2310 Optional32->SizeOfStackReserve = 0;
2311 Optional32->SizeOfStackCommit = 0;
2312 Optional32->SizeOfHeapReserve = 0;
2313 Optional32->SizeOfHeapCommit = 0;
2314
2315 TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;
2316 TEImageHeader.BaseOfCode = Optional32->BaseOfCode;
2317 TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase);
2318
2319 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2320 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
2321 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2322 }
2323
2324 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2325 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2326 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
2327 }
2328
2329 //
2330 // Zero .pdata section data.
2331 //
2332 if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
2333 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
2334 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
2335 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2336 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2337 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
2338 //
2339 // Zero .pdata Section data
2340 //
2341 memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);
2342 //
2343 // Zero .pdata Section header name
2344 //
2345 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
2346 //
2347 // Zero Execption Table
2348 //
2349 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
2350 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
2351 DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);
2352 break;
2353 }
2354 }
2355 }
2356
2357 //
2358 // Strip zero padding at the end of the .reloc section
2359 //
2360 if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2361 if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
2362 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2363 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2364 //
2365 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2366 //
2367 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
2368 SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2369 AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
2370 //
2371 // Check to see if there is zero padding at the end of the base relocations
2372 //
2373 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2374 //
2375 // Check to see if the base relocations are at the end of the file
2376 //
2377 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
2378 //
2379 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2380 //
2381 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2382 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2383 SectionHeader->SizeOfRawData = AllignedRelocSize;
2384 FileLength = Optional32->SizeOfImage;
2385 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);
2386 }
2387 }
2388 }
2389 }
2390 }
2391 }
2392 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
2393 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
2394 Optional64->MajorLinkerVersion = 0;
2395 Optional64->MinorLinkerVersion = 0;
2396 Optional64->MajorOperatingSystemVersion = 0;
2397 Optional64->MinorOperatingSystemVersion = 0;
2398 Optional64->MajorImageVersion = 0;
2399 Optional64->MinorImageVersion = 0;
2400 Optional64->MajorSubsystemVersion = 0;
2401 Optional64->MinorSubsystemVersion = 0;
2402 Optional64->Win32VersionValue = 0;
2403 Optional64->CheckSum = 0;
2404 Optional64->SizeOfStackReserve = 0;
2405 Optional64->SizeOfStackCommit = 0;
2406 Optional64->SizeOfHeapReserve = 0;
2407 Optional64->SizeOfHeapCommit = 0;
2408
2409 TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;
2410 TEImageHeader.BaseOfCode = Optional64->BaseOfCode;
2411 TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);
2412
2413 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
2414 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
2415 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2416 }
2417
2418 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2419 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2420 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
2421 }
2422
2423 //
2424 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
2425 // For Itaninum and X64 Image, remove .pdata section.
2426 //
2427 if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
2428 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
2429 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
2430 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
2431 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2432 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2433 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
2434 //
2435 // Zero .pdata Section header name
2436 //
2437 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
2438
2439 RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
2440 for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
2441 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2442 for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {
2443 if (RuntimeFunction->UnwindInfoAddress > SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
2444 UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
2445 if (UnwindInfo->Version == 1) {
2446 memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
2447 memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
2448 }
2449 }
2450 }
2451 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
2452 }
2453 //
2454 // Zero Execption Table
2455 //
2456 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
2457 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
2458 DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);
2459 break;
2460 }
2461 }
2462 }
2463 }
2464
2465 //
2466 // Strip zero padding at the end of the .reloc section
2467 //
2468 if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
2469 if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
2470 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2471 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
2472 //
2473 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
2474 //
2475 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
2476 SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
2477 AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
2478 //
2479 // Check to see if there is zero padding at the end of the base relocations
2480 //
2481 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
2482 //
2483 // Check to see if the base relocations are at the end of the file
2484 //
2485 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
2486 //
2487 // All the required conditions are met to strip the zero padding of the end of the base relocations section
2488 //
2489 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2490 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
2491 SectionHeader->SizeOfRawData = AllignedRelocSize;
2492 FileLength = Optional64->SizeOfImage;
2493 DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %d", SectionHeader->SizeOfRawData - AllignedRelocSize);
2494 }
2495 }
2496 }
2497 }
2498 }
2499 }
2500 } else {
2501 Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);
2502 goto Finish;
2503 }
2504
2505 if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \
2506 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \
2507 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {
2508 //
2509 // PeImage can be loaded into memory, but it has no relocation section.
2510 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
2511 //
2512 if (Optional32 != NULL) {
2513 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
2514 } else if (Optional64 != NULL) {
2515 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
2516 }
2517 }
2518
2519 //
2520 // Zero ExceptionTable Xdata
2521 //
2522 if (!KeepExceptionTableFlag) {
2523 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
2524 ZeroXdataSection(mInImageName, FileBuffer, SectionHeader, PeHdr->Pe32.FileHeader.NumberOfSections);
2525 }
2526
2527 //
2528 // Zero Time/Data field
2529 //
2530 ZeroDebugData (FileBuffer, FALSE);
2531
2532 if (OutImageType == FW_TE_IMAGE) {
2533 if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {
2534 //
2535 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
2536 //
2537 Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);
2538 goto Finish;
2539 }
2540
2541 if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {
2542 //
2543 // TeImage has the same section alignment and file alignment.
2544 //
2545 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);
2546 goto Finish;
2547 }
2548
2549 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 %X",
2550 TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, TEImageHeader.AddressOfEntryPoint, TEImageHeader.BaseOfCode, TEImageHeader.ImageBase);
2551 //
2552 // Update Image to TeImage
2553 //
2554 if (fpOut != NULL) {
2555 fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpOut);
2556 fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpOut);
2557 }
2558 if (fpInOut != NULL) {
2559 fwrite (&TEImageHeader, 1, sizeof (EFI_TE_IMAGE_HEADER), fpInOut);
2560 fwrite (FileBuffer + TEImageHeader.StrippedSize, 1, FileLength - TEImageHeader.StrippedSize, fpInOut);
2561 }
2562 VerboseMsg ("the size of output file is %d bytes", FileLength - TEImageHeader.StrippedSize);
2563 goto Finish;
2564 }
2565 WriteFile:
2566 //
2567 // Update Image to EfiImage
2568 //
2569 if (fpOut != NULL) {
2570 fwrite (FileBuffer, 1, FileLength, fpOut);
2571 }
2572 if (fpInOut != NULL) {
2573 fwrite (FileBuffer, 1, FileLength, fpInOut);
2574 }
2575 VerboseMsg ("the size of output file is %d bytes", FileLength);
2576
2577 Finish:
2578 if (fpInOut != NULL) {
2579 if (GetUtilityStatus () != STATUS_SUCCESS) {
2580 //
2581 // when file updates failed, original file is still recoveried.
2582 //
2583 fwrite (FileBuffer, 1, FileLength, fpInOut);
2584 }
2585 //
2586 // Write converted data into fpInOut file and close input file.
2587 //
2588 fclose (fpInOut);
2589 }
2590
2591 if (FileBuffer != NULL) {
2592 free (FileBuffer);
2593 }
2594
2595 if (InputFileName != NULL) {
2596 free (InputFileName);
2597 }
2598
2599 if (fpOut != NULL) {
2600 //
2601 // Write converted data into fpOut file and close output file.
2602 //
2603 fclose (fpOut);
2604 if (GetUtilityStatus () != STATUS_SUCCESS) {
2605 if (OutputFileBuffer == NULL) {
2606 remove (OutImageName);
2607 } else {
2608 fpOut = fopen (OutImageName, "wb");
2609 fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
2610 fclose (fpOut);
2611 free (OutputFileBuffer);
2612 }
2613 }
2614 }
2615
2616 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
2617
2618 return GetUtilityStatus ();
2619 }
2620
2621 STATIC
2622 EFI_STATUS
2623 ZeroDebugData (
2624 IN OUT UINT8 *FileBuffer,
2625 BOOLEAN ZeroDebugFlag
2626 )
2627 /*++
2628
2629 Routine Description:
2630
2631 Zero debug information in PeImage.
2632
2633 Arguments:
2634
2635 FileBuffer - Pointer to PeImage.
2636 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
2637
2638 Returns:
2639
2640 EFI_ABORTED - PeImage is invalid.
2641 EFI_SUCCESS - Zero debug data successfully.
2642
2643 --*/
2644 {
2645 UINT32 Index;
2646 UINT32 DebugDirectoryEntryRva;
2647 UINT32 DebugDirectoryEntryFileOffset;
2648 UINT32 ExportDirectoryEntryRva;
2649 UINT32 ExportDirectoryEntryFileOffset;
2650 UINT32 ResourceDirectoryEntryRva;
2651 UINT32 ResourceDirectoryEntryFileOffset;
2652 EFI_IMAGE_DOS_HEADER *DosHdr;
2653 EFI_IMAGE_FILE_HEADER *FileHdr;
2654 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
2655 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
2656 EFI_IMAGE_SECTION_HEADER *SectionHeader;
2657 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
2658 UINT32 *NewTimeStamp;
2659
2660 //
2661 // Init variable.
2662 //
2663 DebugDirectoryEntryRva = 0;
2664 ExportDirectoryEntryRva = 0;
2665 ResourceDirectoryEntryRva = 0;
2666 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
2667 FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
2668
2669
2670 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
2671 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2672 // NO DOS header, must start with PE/COFF header
2673 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
2674 } else {
2675 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
2676 }
2677
2678 //
2679 // Get Debug, Export and Resource EntryTable RVA address.
2680 // Resource Directory entry need to review.
2681 //
2682 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
2683 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2684 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
2685 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2686 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2687 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2688 }
2689 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2690 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2691 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2692 }
2693 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2694 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2695 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2696 if (ZeroDebugFlag) {
2697 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
2698 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
2699 }
2700 }
2701 } else {
2702 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2703 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
2704 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2705 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2706 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2707 }
2708 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2709 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2710 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2711 }
2712 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2713 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2714 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2715 if (ZeroDebugFlag) {
2716 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
2717 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
2718 }
2719 }
2720 }
2721
2722 //
2723 // Get DirectoryEntryTable file offset.
2724 //
2725 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
2726 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2727 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2728 DebugDirectoryEntryFileOffset =
2729 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2730 }
2731 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2732 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2733 ExportDirectoryEntryFileOffset =
2734 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2735 }
2736 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2737 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2738 ResourceDirectoryEntryFileOffset =
2739 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2740 }
2741 }
2742
2743 //
2744 //Zero Debug Data and TimeStamp
2745 //
2746 FileHdr->TimeDateStamp = 0;
2747
2748 if (ExportDirectoryEntryRva != 0) {
2749 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
2750 *NewTimeStamp = 0;
2751 }
2752
2753 if (ResourceDirectoryEntryRva != 0) {
2754 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
2755 *NewTimeStamp = 0;
2756 }
2757
2758 if (DebugDirectoryEntryRva != 0) {
2759 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
2760 DebugEntry->TimeDateStamp = 0;
2761 if (ZeroDebugFlag) {
2762 memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
2763 memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
2764 }
2765 }
2766
2767 return EFI_SUCCESS;
2768 }
2769
2770 STATIC
2771 EFI_STATUS
2772 SetStamp (
2773 IN OUT UINT8 *FileBuffer,
2774 IN CHAR8 *TimeStamp
2775 )
2776 /*++
2777
2778 Routine Description:
2779
2780 Set new time stamp into PeImage FileHdr and Directory table:
2781 Debug, Export and Resource.
2782
2783 Arguments:
2784
2785 FileBuffer - Pointer to PeImage.
2786 TimeStamp - Time stamp string.
2787
2788 Returns:
2789
2790 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
2791 EFI_SUCCESS - Set new time stamp in this image successfully.
2792
2793 --*/
2794 {
2795 struct tm stime;
2796 struct tm *ptime;
2797 time_t newtime;
2798 UINT32 Index;
2799 UINT32 DebugDirectoryEntryRva;
2800 UINT32 DebugDirectoryEntryFileOffset;
2801 UINT32 ExportDirectoryEntryRva;
2802 UINT32 ExportDirectoryEntryFileOffset;
2803 UINT32 ResourceDirectoryEntryRva;
2804 UINT32 ResourceDirectoryEntryFileOffset;
2805 EFI_IMAGE_DOS_HEADER *DosHdr;
2806 EFI_IMAGE_FILE_HEADER *FileHdr;
2807 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
2808 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
2809 EFI_IMAGE_SECTION_HEADER *SectionHeader;
2810 UINT32 *NewTimeStamp;
2811
2812 //
2813 // Init variable.
2814 //
2815 DebugDirectoryEntryRva = 0;
2816 ExportDirectoryEntryRva = 0;
2817 ResourceDirectoryEntryRva = 0;
2818 //
2819 // Get time and date that will be set.
2820 //
2821 if (TimeStamp == NULL) {
2822 Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
2823 return EFI_INVALID_PARAMETER;
2824 }
2825 //
2826 // compare the value with "NOW", if yes, current system time is set.
2827 //
2828 if (stricmp (TimeStamp, "NOW") == 0) {
2829 //
2830 // get system current time and date
2831 //
2832 time (&newtime);
2833 } else {
2834 //
2835 // Check Time Format strictly yyyy-mm-dd 00:00:00
2836 //
2837 for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {
2838 if (Index == 4 || Index == 7) {
2839 if (TimeStamp[Index] == '-') {
2840 continue;
2841 }
2842 } else if (Index == 13 || Index == 16) {
2843 if (TimeStamp[Index] == ':') {
2844 continue;
2845 }
2846 } else if (Index == 10 && TimeStamp[Index] == ' ') {
2847 continue;
2848 } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {
2849 break;
2850 }
2851 }
2852
2853 if (Index < 19 || TimeStamp[19] != '\0') {
2854 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
2855 return EFI_INVALID_PARAMETER;
2856 }
2857
2858 //
2859 // get the date and time from TimeStamp
2860 //
2861 if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",
2862 &stime.tm_year,
2863 &stime.tm_mon,
2864 &stime.tm_mday,
2865 &stime.tm_hour,
2866 &stime.tm_min,
2867 &stime.tm_sec
2868 ) != 6) {
2869 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
2870 return EFI_INVALID_PARAMETER;
2871 }
2872
2873 //
2874 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
2875 //
2876 if (stime.tm_mon <= 0 || stime.tm_mday <=0) {
2877 Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);
2878 return EFI_INVALID_PARAMETER;
2879 }
2880 stime.tm_mon -= 1;
2881
2882 //
2883 // in struct, Year (current year minus 1900)
2884 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
2885 //
2886 //
2887 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
2888 //
2889 if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {
2890 //
2891 // convert 1970 -> 70, 2000 -> 100, ...
2892 //
2893 stime.tm_year -= 1900;
2894 } else {
2895 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
2896 return EFI_INVALID_PARAMETER;
2897 }
2898
2899 //
2900 // convert the date and time to time_t format
2901 //
2902 newtime = mktime (&stime);
2903 if (newtime == (time_t) - 1) {
2904 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
2905 return EFI_INVALID_PARAMETER;
2906 }
2907 }
2908
2909 ptime = localtime (&newtime);
2910 DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
2911 ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
2912 //
2913 // Set new time and data into PeImage.
2914 //
2915 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
2916 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
2917 // NO DOS header, must start with PE/COFF header
2918 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
2919 } else {
2920 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
2921 }
2922
2923 //
2924 // Get Debug, Export and Resource EntryTable RVA address.
2925 // Resource Directory entry need to review.
2926 //
2927 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
2928 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2929 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
2930 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2931 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2932 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2933 }
2934 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2935 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2936 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2937 }
2938 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2939 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2940 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2941 }
2942 } else {
2943 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
2944 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
2945 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
2946 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
2947 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
2948 }
2949 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
2950 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
2951 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
2952 }
2953 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
2954 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
2955 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
2956 }
2957 }
2958
2959 //
2960 // Get DirectoryEntryTable file offset.
2961 //
2962 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
2963 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2964 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2965 DebugDirectoryEntryFileOffset =
2966 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2967 }
2968 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2969 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2970 ExportDirectoryEntryFileOffset =
2971 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2972 }
2973 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
2974 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
2975 ResourceDirectoryEntryFileOffset =
2976 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
2977 }
2978 }
2979
2980 //
2981 // Set new stamp
2982 //
2983 FileHdr->TimeDateStamp = (UINT32) newtime;
2984
2985 if (ExportDirectoryEntryRva != 0) {
2986 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
2987 *NewTimeStamp = (UINT32) newtime;
2988 }
2989
2990 if (ResourceDirectoryEntryRva != 0) {
2991 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
2992 *NewTimeStamp = (UINT32) newtime;
2993 }
2994
2995 if (DebugDirectoryEntryRva != 0) {
2996 NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));
2997 *NewTimeStamp = (UINT32) newtime;
2998 }
2999
3000 return EFI_SUCCESS;
3001 }
3002
3003 STATIC
3004 STATUS
3005 MicrocodeReadData (
3006 FILE *InFptr,
3007 UINT32 *Data
3008 )
3009 /*++
3010
3011 Routine Description:
3012 Read a 32-bit microcode data value from a text file and convert to raw binary form.
3013
3014 Arguments:
3015 InFptr - file pointer to input text file
3016 Data - pointer to where to return the data parsed
3017
3018 Returns:
3019 STATUS_SUCCESS - no errors or warnings, Data contains valid information
3020 STATUS_ERROR - errors were encountered
3021
3022 --*/
3023 {
3024 CHAR8 Line[MAX_LINE_LEN];
3025 CHAR8 *cptr;
3026
3027 Line[MAX_LINE_LEN - 1] = 0;
3028 while (1) {
3029 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
3030 return STATUS_ERROR;
3031 }
3032 //
3033 // If it was a binary file, then it may have overwritten our null terminator
3034 //
3035 if (Line[MAX_LINE_LEN - 1] != 0) {
3036 return STATUS_ERROR;
3037 }
3038
3039 //
3040 // strip space
3041 //
3042 for (cptr = Line; *cptr && isspace(*cptr); cptr++) {
3043 }
3044
3045 // Skip Blank Lines and Comment Lines
3046 if ((strlen(cptr) != 0) && (*cptr != ';')) {
3047 break;
3048 }
3049 }
3050
3051 // Look for
3052 // dd 000000001h ; comment
3053 // dd XXXXXXXX
3054 // DD XXXXXXXXX
3055 // DD XXXXXXXXX
3056 //
3057 if ((tolower(cptr[0]) == 'd') && (tolower(cptr[1]) == 'd') && isspace (cptr[2])) {
3058 //
3059 // Skip blanks and look for a hex digit
3060 //
3061 cptr += 3;
3062 for (; *cptr && isspace(*cptr); cptr++) {
3063 }
3064 if (isxdigit (*cptr)) {
3065 if (sscanf (cptr, "%X", Data) != 1) {
3066 return STATUS_ERROR;
3067 }
3068 }
3069 return STATUS_SUCCESS;
3070 }
3071
3072 return STATUS_ERROR;
3073 }