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