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