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