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