]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/C/GenFw/GenFw.c
ee02f851204a06e3ea02e2fba3bcf7e9488ed3d7
[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->MajorOperatingSystemVersion = 0;
3217 Optional32->MinorOperatingSystemVersion = 0;
3218 Optional32->MajorImageVersion = 0;
3219 Optional32->MinorImageVersion = 0;
3220 Optional32->MajorSubsystemVersion = 0;
3221 Optional32->MinorSubsystemVersion = 0;
3222 Optional32->Win32VersionValue = 0;
3223 Optional32->CheckSum = 0;
3224 Optional32->SizeOfStackReserve = 0;
3225 Optional32->SizeOfStackCommit = 0;
3226 Optional32->SizeOfHeapReserve = 0;
3227 Optional32->SizeOfHeapCommit = 0;
3228
3229 TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;
3230 TEImageHeader.BaseOfCode = Optional32->BaseOfCode;
3231 TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase);
3232
3233 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
3234 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
3235 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
3236 }
3237
3238 if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
3239 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3240 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
3241 }
3242
3243 //
3244 // Zero .pdata section data.
3245 //
3246 if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
3247 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
3248 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
3249 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3250 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
3251 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
3252 //
3253 // Zero .pdata Section data
3254 //
3255 memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);
3256 //
3257 // Zero .pdata Section header name
3258 //
3259 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
3260 //
3261 // Zero Execption Table
3262 //
3263 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
3264 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
3265 DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);
3266 break;
3267 }
3268 }
3269 }
3270
3271 //
3272 // Strip zero padding at the end of the .reloc section
3273 //
3274 if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
3275 if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
3276 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3277 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
3278 //
3279 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3280 //
3281 if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
3282 SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
3283 AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
3284 //
3285 // Check to see if there is zero padding at the end of the base relocations
3286 //
3287 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
3288 //
3289 // Check to see if the base relocations are at the end of the file
3290 //
3291 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
3292 //
3293 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3294 //
3295 Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
3296 Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
3297 SectionHeader->SizeOfRawData = AllignedRelocSize;
3298 FileLength = Optional32->SizeOfImage;
3299 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));
3300 }
3301 }
3302 }
3303 }
3304 }
3305 }
3306 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
3307 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
3308 Optional64->MajorOperatingSystemVersion = 0;
3309 Optional64->MinorOperatingSystemVersion = 0;
3310 Optional64->MajorImageVersion = 0;
3311 Optional64->MinorImageVersion = 0;
3312 Optional64->MajorSubsystemVersion = 0;
3313 Optional64->MinorSubsystemVersion = 0;
3314 Optional64->Win32VersionValue = 0;
3315 Optional64->CheckSum = 0;
3316 Optional64->SizeOfStackReserve = 0;
3317 Optional64->SizeOfStackCommit = 0;
3318 Optional64->SizeOfHeapReserve = 0;
3319 Optional64->SizeOfHeapCommit = 0;
3320
3321 TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;
3322 TEImageHeader.BaseOfCode = Optional64->BaseOfCode;
3323 TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);
3324
3325 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
3326 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
3327 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
3328 }
3329
3330 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
3331 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3332 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
3333 }
3334
3335 //
3336 // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
3337 // For Itaninum and X64 Image, remove .pdata section.
3338 //
3339 if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64) || PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_IA64) {
3340 if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
3341 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
3342 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
3343 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3344 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
3345 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
3346 //
3347 // Zero .pdata Section header name
3348 //
3349 memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
3350
3351 RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
3352 for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
3353 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3354 for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {
3355 if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
3356 UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
3357 if (UnwindInfo->Version == 1) {
3358 memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
3359 memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
3360 }
3361 break;
3362 }
3363 }
3364 memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
3365 }
3366 //
3367 // Zero Execption Table
3368 //
3369 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
3370 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
3371 DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);
3372 break;
3373 }
3374 }
3375 }
3376 }
3377
3378 //
3379 // Strip zero padding at the end of the .reloc section
3380 //
3381 if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
3382 if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
3383 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3384 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
3385 //
3386 // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
3387 //
3388 if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
3389 SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
3390 AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
3391 //
3392 // Check to see if there is zero padding at the end of the base relocations
3393 //
3394 if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
3395 //
3396 // Check to see if the base relocations are at the end of the file
3397 //
3398 if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
3399 //
3400 // All the required conditions are met to strip the zero padding of the end of the base relocations section
3401 //
3402 Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
3403 Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
3404 SectionHeader->SizeOfRawData = AllignedRelocSize;
3405 FileLength = Optional64->SizeOfImage;
3406 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));
3407 }
3408 }
3409 }
3410 }
3411 }
3412 }
3413 } else {
3414 Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);
3415 goto Finish;
3416 }
3417
3418 if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \
3419 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \
3420 (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {
3421 //
3422 // PeImage can be loaded into memory, but it has no relocation section.
3423 // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
3424 //
3425 if (Optional32 != NULL) {
3426 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
3427 } else if (Optional64 != NULL) {
3428 TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
3429 }
3430 }
3431
3432 //
3433 // Fill HII section data
3434 //
3435 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3436 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
3437 if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {
3438 //
3439 // Update resource section header offset
3440 //
3441 SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);
3442 //
3443 // Update resource section name
3444 //
3445 strcpy((char *) SectionHeader[Index].Name, ".rsrc");
3446 //
3447 // Update resource data directory.
3448 //
3449 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
3450 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
3451 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
3452 Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
3453 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
3454 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
3455 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
3456 Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
3457 }
3458 break;
3459 }
3460 }
3461
3462 //
3463 // Zero ExceptionTable Xdata
3464 //
3465 if (!KeepExceptionTableFlag) {
3466 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
3467 for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
3468 if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {
3469 //
3470 // zero .xdata section
3471 //
3472 memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);
3473 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);
3474 break;
3475 }
3476 }
3477 }
3478
3479 //
3480 // Zero Time/Data field
3481 //
3482 ZeroDebugData (FileBuffer, FALSE);
3483
3484 if (OutImageType == FW_TE_IMAGE) {
3485 if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {
3486 //
3487 // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
3488 //
3489 Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);
3490 goto Finish;
3491 }
3492
3493 if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {
3494 //
3495 // TeImage has the same section alignment and file alignment.
3496 //
3497 Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);
3498 goto Finish;
3499 }
3500
3501 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",
3502 TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);
3503 //
3504 // Update Image to TeImage
3505 //
3506 FileLength = FileLength - TEImageHeader.StrippedSize;
3507 memcpy (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);
3508 FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);
3509 memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));
3510 VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));
3511 } else {
3512
3513 //
3514 // Following codes are to fix the objcopy's issue:
3515 // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
3516 // It cause issue for EFI image which has no ".reloc" sections.
3517 // Following codes will be removed when objcopy in binutil fix this problem for PE image.
3518 //
3519 if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {
3520 if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
3521 Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
3522 if (Optional32->ImageBase == 0) {
3523 PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
3524 }
3525 } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
3526 Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
3527 if (Optional64->ImageBase == 0) {
3528 PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
3529 }
3530 }
3531 }
3532 }
3533
3534 WriteFile:
3535 //
3536 // Update Image to EfiImage or TE image
3537 //
3538 if (ReplaceFlag) {
3539 if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {
3540 //
3541 // Update File when File is changed.
3542 //
3543 fpInOut = fopen (mInImageName, "wb");
3544 if (fpInOut == NULL) {
3545 Error (NULL, 0, 0001, "Error opening file", mInImageName);
3546 goto Finish;
3547 }
3548 fwrite (FileBuffer, 1, FileLength, fpInOut);
3549 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
3550 }
3551 } else {
3552 if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {
3553 //
3554 // Update File when File is changed or File is old.
3555 //
3556 fpOut = fopen (OutImageName, "wb");
3557 if (fpOut == NULL) {
3558 Error (NULL, 0, 0001, "Error opening output file", OutImageName);
3559 goto Finish;
3560 }
3561 fwrite (FileBuffer, 1, FileLength, fpOut);
3562 VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
3563 }
3564 }
3565 mImageSize = FileLength;
3566
3567 Finish:
3568 if (fpInOut != NULL) {
3569 if (GetUtilityStatus () != STATUS_SUCCESS) {
3570 //
3571 // when file updates failed, original file is still recovered.
3572 //
3573 fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);
3574 }
3575 //
3576 // Write converted data into fpInOut file and close input file.
3577 //
3578 fclose (fpInOut);
3579 }
3580
3581 if (FileBuffer != NULL) {
3582 free (FileBuffer);
3583 }
3584
3585 if (InputFileName != NULL) {
3586 free (InputFileName);
3587 }
3588
3589 if (fpOut != NULL) {
3590 //
3591 // Write converted data into fpOut file and close output file.
3592 //
3593 fclose (fpOut);
3594 if (GetUtilityStatus () != STATUS_SUCCESS) {
3595 if (OutputFileBuffer == NULL) {
3596 remove (OutImageName);
3597 } else {
3598 fpOut = fopen (OutImageName, "wb");
3599 fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
3600 fclose (fpOut);
3601 }
3602 }
3603 }
3604
3605 if (InputFileBuffer != NULL) {
3606 free (InputFileBuffer);
3607 }
3608
3609 if (OutputFileBuffer != NULL) {
3610 free (OutputFileBuffer);
3611 }
3612
3613 //
3614 // Write module size and time stamp to report file.
3615 //
3616 if (OutImageName != NULL) {
3617 FileLen = strlen (OutImageName);
3618 }
3619 if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {
3620 ReportFileName = (CHAR8 *) malloc (FileLen + 1);
3621 if (ReportFileName != NULL) {
3622 strcpy (ReportFileName, OutImageName);
3623 strcpy (ReportFileName + (FileLen - 4), ".txt");
3624 ReportFile = fopen (ReportFileName, "w+");
3625 if (ReportFile != NULL) {
3626 fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);
3627 fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);
3628 fclose(ReportFile);
3629 }
3630 free (ReportFileName);
3631 }
3632 }
3633 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
3634
3635 return GetUtilityStatus ();
3636 }
3637
3638 STATIC
3639 EFI_STATUS
3640 ZeroDebugData (
3641 IN OUT UINT8 *FileBuffer,
3642 BOOLEAN ZeroDebugFlag
3643 )
3644 /*++
3645
3646 Routine Description:
3647
3648 Zero debug information in PeImage.
3649
3650 Arguments:
3651
3652 FileBuffer - Pointer to PeImage.
3653 ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
3654
3655 Returns:
3656
3657 EFI_ABORTED - PeImage is invalid.
3658 EFI_SUCCESS - Zero debug data successfully.
3659
3660 --*/
3661 {
3662 UINT32 Index;
3663 UINT32 DebugDirectoryEntryRva;
3664 UINT32 DebugDirectoryEntryFileOffset;
3665 UINT32 ExportDirectoryEntryRva;
3666 UINT32 ExportDirectoryEntryFileOffset;
3667 UINT32 ResourceDirectoryEntryRva;
3668 UINT32 ResourceDirectoryEntryFileOffset;
3669 EFI_IMAGE_DOS_HEADER *DosHdr;
3670 EFI_IMAGE_FILE_HEADER *FileHdr;
3671 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
3672 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
3673 EFI_IMAGE_SECTION_HEADER *SectionHeader;
3674 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
3675 UINT32 *NewTimeStamp;
3676
3677 //
3678 // Init variable.
3679 //
3680 DebugDirectoryEntryRva = 0;
3681 ExportDirectoryEntryRva = 0;
3682 ResourceDirectoryEntryRva = 0;
3683 DebugDirectoryEntryFileOffset = 0;
3684 ExportDirectoryEntryFileOffset = 0;
3685 ResourceDirectoryEntryFileOffset = 0;
3686 DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
3687 FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
3688
3689
3690 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
3691 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
3692 // NO DOS header, must start with PE/COFF header
3693 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
3694 } else {
3695 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
3696 }
3697
3698 //
3699 // Get Debug, Export and Resource EntryTable RVA address.
3700 // Resource Directory entry need to review.
3701 //
3702 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
3703 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3704 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
3705 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3706 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3707 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3708 }
3709 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3710 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3711 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3712 }
3713 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3714 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3715 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3716 if (ZeroDebugFlag) {
3717 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
3718 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
3719 }
3720 }
3721 } else {
3722 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3723 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
3724 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3725 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3726 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3727 }
3728 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3729 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3730 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3731 }
3732 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3733 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3734 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3735 if (ZeroDebugFlag) {
3736 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
3737 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
3738 }
3739 }
3740 }
3741
3742 //
3743 // Get DirectoryEntryTable file offset.
3744 //
3745 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
3746 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3747 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3748 DebugDirectoryEntryFileOffset =
3749 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3750 }
3751 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3752 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3753 ExportDirectoryEntryFileOffset =
3754 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3755 }
3756 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3757 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3758 ResourceDirectoryEntryFileOffset =
3759 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3760 }
3761 }
3762
3763 //
3764 //Zero Debug Data and TimeStamp
3765 //
3766 FileHdr->TimeDateStamp = 0;
3767 mImageTimeStamp = 0;
3768 if (ExportDirectoryEntryFileOffset != 0) {
3769 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
3770 *NewTimeStamp = 0;
3771 }
3772
3773 if (ResourceDirectoryEntryFileOffset != 0) {
3774 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
3775 *NewTimeStamp = 0;
3776 }
3777
3778 if (DebugDirectoryEntryFileOffset != 0) {
3779 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
3780 DebugEntry->TimeDateStamp = 0;
3781 mImageTimeStamp = 0;
3782 if (ZeroDebugFlag) {
3783 memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
3784 memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
3785 }
3786 }
3787
3788 return EFI_SUCCESS;
3789 }
3790
3791 STATIC
3792 EFI_STATUS
3793 SetStamp (
3794 IN OUT UINT8 *FileBuffer,
3795 IN CHAR8 *TimeStamp
3796 )
3797 /*++
3798
3799 Routine Description:
3800
3801 Set new time stamp into PeImage FileHdr and Directory table:
3802 Debug, Export and Resource.
3803
3804 Arguments:
3805
3806 FileBuffer - Pointer to PeImage.
3807 TimeStamp - Time stamp string.
3808
3809 Returns:
3810
3811 EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
3812 EFI_SUCCESS - Set new time stamp in this image successfully.
3813
3814 --*/
3815 {
3816 struct tm stime;
3817 struct tm *ptime;
3818 time_t newtime;
3819 UINT32 Index;
3820 UINT32 DebugDirectoryEntryRva;
3821 UINT32 DebugDirectoryEntryFileOffset;
3822 UINT32 ExportDirectoryEntryRva;
3823 UINT32 ExportDirectoryEntryFileOffset;
3824 UINT32 ResourceDirectoryEntryRva;
3825 UINT32 ResourceDirectoryEntryFileOffset;
3826 EFI_IMAGE_DOS_HEADER *DosHdr;
3827 EFI_IMAGE_FILE_HEADER *FileHdr;
3828 EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
3829 EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
3830 EFI_IMAGE_SECTION_HEADER *SectionHeader;
3831 UINT32 *NewTimeStamp;
3832
3833 //
3834 // Init variable.
3835 //
3836 DebugDirectoryEntryRva = 0;
3837 DebugDirectoryEntryFileOffset = 0;
3838 ExportDirectoryEntryRva = 0;
3839 ExportDirectoryEntryFileOffset = 0;
3840 ResourceDirectoryEntryRva = 0;
3841 ResourceDirectoryEntryFileOffset = 0;
3842 //
3843 // Get time and date that will be set.
3844 //
3845 if (TimeStamp == NULL) {
3846 Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
3847 return EFI_INVALID_PARAMETER;
3848 }
3849 //
3850 // compare the value with "NOW", if yes, current system time is set.
3851 //
3852 if (stricmp (TimeStamp, "NOW") == 0) {
3853 //
3854 // get system current time and date
3855 //
3856 time (&newtime);
3857 } else {
3858 //
3859 // Check Time Format strictly yyyy-mm-dd 00:00:00
3860 //
3861 for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {
3862 if (Index == 4 || Index == 7) {
3863 if (TimeStamp[Index] == '-') {
3864 continue;
3865 }
3866 } else if (Index == 13 || Index == 16) {
3867 if (TimeStamp[Index] == ':') {
3868 continue;
3869 }
3870 } else if (Index == 10 && TimeStamp[Index] == ' ') {
3871 continue;
3872 } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {
3873 break;
3874 }
3875 }
3876
3877 if (Index < 19 || TimeStamp[19] != '\0') {
3878 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
3879 return EFI_INVALID_PARAMETER;
3880 }
3881
3882 //
3883 // get the date and time from TimeStamp
3884 //
3885 if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",
3886 &stime.tm_year,
3887 &stime.tm_mon,
3888 &stime.tm_mday,
3889 &stime.tm_hour,
3890 &stime.tm_min,
3891 &stime.tm_sec
3892 ) != 6) {
3893 Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
3894 return EFI_INVALID_PARAMETER;
3895 }
3896
3897 //
3898 // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
3899 //
3900 if (stime.tm_mon <= 0 || stime.tm_mday <=0) {
3901 Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);
3902 return EFI_INVALID_PARAMETER;
3903 }
3904 stime.tm_mon -= 1;
3905
3906 //
3907 // in struct, Year (current year minus 1900)
3908 // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
3909 //
3910 //
3911 // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
3912 //
3913 if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {
3914 //
3915 // convert 1970 -> 70, 2000 -> 100, ...
3916 //
3917 stime.tm_year -= 1900;
3918 } else {
3919 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
3920 return EFI_INVALID_PARAMETER;
3921 }
3922
3923 //
3924 // convert the date and time to time_t format
3925 //
3926 newtime = mktime (&stime);
3927 if (newtime == (time_t) - 1) {
3928 Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
3929 return EFI_INVALID_PARAMETER;
3930 }
3931 }
3932
3933 ptime = localtime (&newtime);
3934 DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
3935 ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
3936 //
3937 // Set new time and data into PeImage.
3938 //
3939 DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
3940 if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
3941 // NO DOS header, must start with PE/COFF header
3942 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
3943 } else {
3944 FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
3945 }
3946
3947 //
3948 // Get Debug, Export and Resource EntryTable RVA address.
3949 // Resource Directory entry need to review.
3950 //
3951 if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
3952 Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3953 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
3954 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3955 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3956 ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3957 }
3958 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3959 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3960 ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3961 }
3962 if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3963 Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3964 DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3965 }
3966 } else {
3967 Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
3968 SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
3969 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
3970 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
3971 ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
3972 }
3973 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
3974 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
3975 ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
3976 }
3977 if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
3978 Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
3979 DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
3980 }
3981 }
3982
3983 //
3984 // Get DirectoryEntryTable file offset.
3985 //
3986 for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
3987 if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3988 DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3989 DebugDirectoryEntryFileOffset =
3990 DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3991 }
3992 if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3993 ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3994 ExportDirectoryEntryFileOffset =
3995 ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
3996 }
3997 if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
3998 ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
3999 ResourceDirectoryEntryFileOffset =
4000 ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
4001 }
4002 }
4003
4004 //
4005 // Set new stamp
4006 //
4007 FileHdr->TimeDateStamp = (UINT32) newtime;
4008 mImageTimeStamp = (UINT32) newtime;
4009 if (ExportDirectoryEntryRva != 0) {
4010 NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
4011 *NewTimeStamp = (UINT32) newtime;
4012 }
4013
4014 if (ResourceDirectoryEntryRva != 0) {
4015 NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
4016 *NewTimeStamp = (UINT32) newtime;
4017 }
4018
4019 if (DebugDirectoryEntryRva != 0) {
4020 NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));
4021 *NewTimeStamp = (UINT32) newtime;
4022 }
4023
4024 return EFI_SUCCESS;
4025 }
4026
4027 STATIC
4028 STATUS
4029 MicrocodeReadData (
4030 FILE *InFptr,
4031 UINT32 *Data
4032 )
4033 /*++
4034
4035 Routine Description:
4036 Read a 32-bit microcode data value from a text file and convert to raw binary form.
4037
4038 Arguments:
4039 InFptr - file pointer to input text file
4040 Data - pointer to where to return the data parsed
4041
4042 Returns:
4043 STATUS_SUCCESS - no errors or warnings, Data contains valid information
4044 STATUS_ERROR - errors were encountered
4045
4046 --*/
4047 {
4048 CHAR8 Line[MAX_LINE_LEN];
4049 CHAR8 *cptr;
4050 unsigned ScannedData = 0;
4051
4052 Line[MAX_LINE_LEN - 1] = 0;
4053 while (1) {
4054 if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
4055 return STATUS_ERROR;
4056 }
4057 //
4058 // If it was a binary file, then it may have overwritten our null terminator
4059 //
4060 if (Line[MAX_LINE_LEN - 1] != 0) {
4061 return STATUS_ERROR;
4062 }
4063
4064 //
4065 // strip space
4066 //
4067 for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {
4068 }
4069
4070 // Skip Blank Lines and Comment Lines
4071 if ((strlen(cptr) != 0) && (*cptr != ';')) {
4072 break;
4073 }
4074 }
4075
4076 // Look for
4077 // dd 000000001h ; comment
4078 // dd XXXXXXXX
4079 // DD XXXXXXXXX
4080 // DD XXXXXXXXX
4081 //
4082 if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {
4083 //
4084 // Skip blanks and look for a hex digit
4085 //
4086 cptr += 3;
4087 for (; *cptr && isspace((int)*cptr); cptr++) {
4088 }
4089 if (isxdigit ((int)*cptr)) {
4090 if (sscanf (cptr, "%X", &ScannedData) != 1) {
4091 return STATUS_ERROR;
4092 }
4093 }
4094 *Data = (UINT32) ScannedData;
4095 return STATUS_SUCCESS;
4096 }
4097
4098 return STATUS_ERROR;
4099 }