]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/GenAcpiTable/GenAcpiTable.c
Fix capitalization
[mirror_edk2.git] / Tools / Source / TianoTools / GenAcpiTable / GenAcpiTable.c
CommitLineData
d25c4bf0 1/*++\r
2\r
3Copyright (c) 2002 Intel Corporation. All rights reserved\r
4This software and associated documentation (if any) is furnished\r
5under a license and may only be used or copied in accordance\r
6with the terms of the license. Except as permitted by such\r
7license, no part of this software or documentation may be\r
8reproduced, stored in a retrieval system, or transmitted in any\r
9form or by any means without the express written consent of\r
10Intel Corporation.\r
11\r
12Module Name:\r
13\r
14 GenAcpiTable.c\r
15 \r
16Abstract:\r
17\r
18 A utility that extracts the .DATA section from a PE/COFF image.\r
19\r
20--*/\r
21\r
22#include <stdio.h>\r
23#include <string.h>\r
24#include <stdlib.h>\r
25\r
26#include "Tiano.h"\r
27#include "TianoCommon.h"\r
28#include "EfiImage.h" // for PE32 structure definitions\r
29#include "EfiUtilityMsgs.h"\r
30\r
31//\r
32// Version of this utility\r
33//\r
34#define UTILITY_NAME "GenAcpiTable"\r
35#define UTILITY_VERSION "v0.11"\r
36\r
37//\r
38// Define the max length of a filename\r
39//\r
40#define MAX_PATH 256\r
41#define DEFAULT_OUTPUT_EXTENSION ".acpi"\r
42\r
43//\r
44// Use this to track our command-line options and globals\r
45//\r
46struct {\r
47 INT8 OutFileName[MAX_PATH];\r
48 INT8 InFileName[MAX_PATH];\r
49} mOptions;\r
50\r
51//\r
52// Use these to convert from machine type value to a named type\r
53//\r
54typedef struct {\r
55 UINT16 Value;\r
56 INT8 *Name;\r
57} STRING_LOOKUP;\r
58\r
59static STRING_LOOKUP mMachineTypes[] = {\r
60 EFI_IMAGE_MACHINE_IA32,\r
61 "IA32",\r
62 EFI_IMAGE_MACHINE_IA64,\r
63 "IA64",\r
64 EFI_IMAGE_MACHINE_EBC,\r
65 "EBC",\r
66 0,\r
67 NULL\r
68};\r
69\r
70static STRING_LOOKUP mSubsystemTypes[] = {\r
71 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
72 "EFI application",\r
73 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
74 "EFI boot service driver",\r
75 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
76 "EFI runtime driver",\r
77 0,\r
78 NULL\r
79};\r
80//\r
81// Function prototypes\r
82//\r
83static\r
84void\r
85Usage (\r
86 VOID\r
87 );\r
88\r
89static\r
90STATUS\r
91ParseCommandLine (\r
92 int Argc,\r
93 char *Argv[]\r
94 );\r
95\r
96static\r
97STATUS\r
98CheckPE32File (\r
99 INT8 *FileName,\r
100 FILE *Fptr,\r
101 UINT16 *MachineType,\r
102 UINT16 *SubSystem\r
103 );\r
104\r
105static\r
106STATUS\r
107ProcessFile (\r
108 INT8 *InFileName,\r
109 INT8 *OutFileName\r
110 );\r
111\r
112static\r
113void\r
114DumpImage (\r
115 INT8 *FileName\r
116 );\r
117\r
118main (\r
119 int Argc,\r
120 char *Argv[]\r
121 )\r
122/*++\r
123\r
124Routine Description:\r
125 \r
126\r
127Arguments:\r
128\r
129 Argc - standard C main() argument count\r
130\r
131 Argv - standard C main() argument list\r
132\r
133Returns:\r
134\r
135 0 success\r
136 non-zero otherwise\r
137\r
138--*/\r
139// GC_TODO: ] - add argument and description to function comment\r
140{\r
141 UINT32 Status;\r
142\r
143 SetUtilityName (UTILITY_NAME);\r
144 //\r
145 // Parse the command line arguments\r
146 //\r
147 if (ParseCommandLine (Argc, Argv)) {\r
148 return STATUS_ERROR;\r
149 }\r
150 //\r
151 // Make sure we don't have the same filename for input and output files\r
152 //\r
153 if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
154 Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
155 goto Finish;\r
156 }\r
157 //\r
158 // Process the file\r
159 //\r
160 ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
161Finish:\r
162 Status = GetUtilityStatus ();\r
163 return Status;\r
164}\r
165\r
166static\r
167STATUS\r
168ProcessFile (\r
169 INT8 *InFileName,\r
170 INT8 *OutFileName\r
171 )\r
172/*++\r
173\r
174Routine Description:\r
175 \r
176 Process a PE32 EFI file.\r
177\r
178Arguments:\r
179\r
180 InFileName - Name of the PE32 EFI file to process.\r
181 OutFileName - Name of the output file for the processed data.\r
182\r
183Returns:\r
184\r
185 0 - successful\r
186\r
187--*/\r
188{\r
189 STATUS Status;\r
190 UINTN Index;\r
191 FILE *InFptr;\r
192 FILE *OutFptr;\r
193 UINT16 MachineType;\r
194 UINT16 SubSystem;\r
195 UINT32 PESigOffset;\r
196 EFI_IMAGE_FILE_HEADER FileHeader;\r
197 EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
198 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
199 UINT8 *Buffer;\r
200 long SaveFilePosition;\r
201\r
202 InFptr = NULL;\r
203 OutFptr = NULL;\r
204 Buffer = NULL;\r
205 Status = STATUS_ERROR;\r
206 //\r
207 // Try to open the input file\r
208 //\r
209 if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
210 Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
211 return STATUS_ERROR;\r
212 }\r
213 //\r
214 // Double-check the file to make sure it's what we expect it to be\r
215 //\r
216 if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
217 goto Finish;\r
218 }\r
219 //\r
220 // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
221 // offset (from the start of the file) to the PE signature, which always\r
222 // follows the MSDOS stub. The PE signature is immediately followed by the\r
223 // COFF file header.\r
224 //\r
225 //\r
226 if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
227 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
228 goto Finish;\r
229 }\r
230\r
231 if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
232 Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
233 goto Finish;\r
234 }\r
235\r
236 if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
237 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
238 goto Finish;\r
239 }\r
240 //\r
241 // We should now be at the COFF file header. Read it in and verify it's\r
242 // of an image type we support.\r
243 //\r
244 if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
245 Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
246 goto Finish;\r
247 }\r
248\r
249 if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {\r
250 Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
251 goto Finish;\r
252 }\r
253 //\r
254 // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
255 //\r
256 SaveFilePosition = ftell (InFptr);\r
257 if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
258 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
259 goto Finish;\r
260 }\r
261\r
262 if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
263 if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {\r
264 Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
265 goto Finish;\r
266 }\r
267\r
268 if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
269 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
270 goto Finish;\r
271 }\r
272 }\r
273 //\r
274 // Search for the ".data" section\r
275 //\r
276 for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {\r
277 if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {\r
278 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
279 goto Finish;\r
280 }\r
281\r
282 if (strcmp (SectionHeader.Name, ".data") == 0) {\r
283 if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {\r
284 Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
285 goto Finish;\r
286 }\r
287\r
288 Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);\r
289 if (Buffer == NULL) {\r
290 Status = EFI_OUT_OF_RESOURCES;\r
291 goto Finish;\r
292 }\r
293 if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {\r
294 Error (NULL, 0, 0, InFileName, "failed to .data section");\r
295 goto Finish;\r
296 }\r
297 //\r
298 // Now open our output file\r
299 //\r
300 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
301 Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
302 goto Finish;\r
303 }\r
304\r
305 if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {\r
306 Error (NULL, 0, 0, OutFileName, "failed to write .data section");\r
307 goto Finish;\r
308 }\r
309\r
310 Status = STATUS_SUCCESS;\r
311 goto Finish;\r
312 }\r
313 }\r
314\r
315 Status = STATUS_ERROR;\r
316\r
317Finish:\r
318 if (InFptr != NULL) {\r
319 fclose (InFptr);\r
320 }\r
321 //\r
322 // Close the output file. If there was an error, delete the output file so\r
323 // that a subsequent build will rebuild it.\r
324 //\r
325 if (OutFptr != NULL) {\r
326 fclose (OutFptr);\r
327 if (GetUtilityStatus () == STATUS_ERROR) {\r
328 remove (OutFileName);\r
329 }\r
330 }\r
331\r
332 //\r
333 // Free up our buffer\r
334 //\r
335 if (Buffer != NULL) {\r
336 free (Buffer);\r
337 }\r
338\r
339 return Status;\r
340}\r
341\r
342static\r
343STATUS\r
344CheckPE32File (\r
345 INT8 *FileName,\r
346 FILE *Fptr,\r
347 UINT16 *MachineType,\r
348 UINT16 *SubSystem\r
349 )\r
350/*++\r
351\r
352Routine Description:\r
353\r
354 GC_TODO: Add function description\r
355\r
356Arguments:\r
357\r
358 FileName - GC_TODO: add argument description\r
359 Fptr - GC_TODO: add argument description\r
360 MachineType - GC_TODO: add argument description\r
361 SubSystem - GC_TODO: add argument description\r
362\r
363Returns:\r
364\r
365 GC_TODO: add return values\r
366\r
367--*/\r
368{\r
369 /*++\r
370\r
371Routine Description:\r
372 \r
373 Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
374 PE32 image file, and then return the machine type in the supplied pointer.\r
375\r
376Arguments:\r
377\r
378 Fptr File pointer to the already-opened PE32 file\r
379 MachineType Location to stuff the machine type of the PE32 file. This is needed\r
380 because the image may be Itanium-based, IA32, or EBC.\r
381\r
382Returns:\r
383\r
384 0 success\r
385 non-zero otherwise\r
386\r
387--*/\r
388 EFI_IMAGE_DOS_HEADER DosHeader;\r
389 EFI_IMAGE_FILE_HEADER FileHdr;\r
390 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
391 UINT32 PESig;\r
392 STATUS Status;\r
393\r
394 Status = STATUS_ERROR;\r
395 //\r
396 // Position to the start of the file\r
397 //\r
398 fseek (Fptr, 0, SEEK_SET);\r
399 //\r
400 // Read the DOS header\r
401 //\r
402 if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
403 Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
404 goto Finish;\r
405 }\r
406 //\r
407 // Check the magic number (0x5A4D)\r
408 //\r
409 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
410 Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
411 goto Finish;\r
412 }\r
413 //\r
414 // Position into the file and check the PE signature\r
415 //\r
416 fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
417 if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
418 Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
419 goto Finish;\r
420 }\r
421 //\r
422 // Check the PE signature in the header "PE\0\0"\r
423 //\r
424 if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
425 Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
426 goto Finish;\r
427 }\r
428 //\r
429 // Read the file header\r
430 //\r
431 if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
432 Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
433 goto Finish;\r
434 }\r
435 //\r
436 // Read the optional header so we can get the subsystem\r
437 //\r
438 if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
439 Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
440 goto Finish;\r
441 }\r
442\r
443 *SubSystem = OptionalHdr.Subsystem;\r
444 //\r
445 // Good to go\r
446 //\r
447 Status = STATUS_SUCCESS;\r
448Finish:\r
449 fseek (Fptr, 0, SEEK_SET);\r
450 return Status;\r
451}\r
452\r
453static\r
454int\r
455ParseCommandLine (\r
456 int Argc,\r
457 char *Argv[]\r
458 )\r
459/*++\r
460\r
461Routine Description:\r
462 \r
463 Given the Argc/Argv program arguments, and a pointer to an options structure,\r
464 parse the command-line options and check their validity.\r
465\r
466\r
467Arguments:\r
468\r
469 Argc - standard C main() argument count\r
470 Argv - standard C main() argument list\r
471\r
472Returns:\r
473\r
474 STATUS_SUCCESS success\r
475 non-zero otherwise\r
476\r
477--*/\r
478// GC_TODO: ] - add argument and description to function comment\r
479{\r
480 //\r
481 // Clear out the options\r
482 //\r
483 memset ((char *) &mOptions, 0, sizeof (mOptions));\r
484 //\r
485 // Skip over the program name\r
486 //\r
487 Argc--;\r
488 Argv++;\r
489\r
490 if (Argc != 2) {\r
491 Usage ();\r
492 return STATUS_ERROR;\r
493 }\r
494\r
495 strcpy (mOptions.InFileName, Argv[0]);\r
496 //\r
497 // Next argument\r
498 //\r
499 Argv++;\r
500 Argc--;\r
501\r
502 strcpy (mOptions.OutFileName, Argv[0]);\r
503\r
504 return STATUS_SUCCESS;\r
505}\r
506\r
507static\r
508void\r
509Usage (\r
510 VOID\r
511 )\r
512/*++\r
513\r
514Routine Description:\r
515 \r
516 Print usage information for this utility.\r
517\r
518Arguments:\r
519\r
520 None.\r
521\r
522Returns:\r
523\r
524 Nothing.\r
525\r
526--*/\r
527{\r
528 int Index;\r
529 static const char *Msg[] = {\r
530 UTILITY_NAME " version "UTILITY_VERSION " - Generate ACPI Table image utility",\r
531 " Generate an ACPI Table image from an EFI PE32 image",\r
532 " Usage: "UTILITY_NAME " InFileName OutFileName",\r
533 " where:",\r
534 " InFileName - name of the input PE32 file",\r
535 " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
536 "",\r
537 NULL\r
538 };\r
539 for (Index = 0; Msg[Index] != NULL; Index++) {\r
540 fprintf (stdout, "%s\n", Msg[Index]);\r
541 }\r
542}\r