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