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