]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/CCode/Source/GenAcpiTable/GenAcpiTable.c
Add checking code for GenAcpiTable tools.
[mirror_edk2.git] / Tools / CCode / Source / GenAcpiTable / GenAcpiTable.c
CommitLineData
d25c4bf0 1/*++\r
2\r
ad1f8df0 3Copyright (c) 2004-2006 Intel Corporation. All rights reserved\r
4This program and the accompanying materials are licensed and made available \r
5under the terms and conditions of the BSD License which accompanies this \r
6distribution. 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
d25c4bf0 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
f6ab0cee 32//\r
33// Acpi Table definition\r
34//\r
35#include "Acpi.h"\r
36#include "Acpi1_0.h"\r
37#include "Acpi2_0.h"\r
38#include "Acpi3_0.h"\r
39#include "MemoryMappedConfigurationSpaceAccessTable.h"\r
40\r
d25c4bf0 41//\r
42// Version of this utility\r
43//\r
f091efb3 44#define UTILITY_NAME "GenAcpiTable"\r
45#define UTILITY_MAJOR_VERSION 0\r
46#define UTILITY_MINOR_VERSION 11\r
d25c4bf0 47\r
48//\r
49// Define the max length of a filename\r
50//\r
51#define MAX_PATH 256\r
52#define DEFAULT_OUTPUT_EXTENSION ".acpi"\r
53\r
54//\r
55// Use this to track our command-line options and globals\r
56//\r
57struct {\r
58 INT8 OutFileName[MAX_PATH];\r
59 INT8 InFileName[MAX_PATH];\r
60} mOptions;\r
61\r
62//\r
63// Use these to convert from machine type value to a named type\r
64//\r
65typedef struct {\r
66 UINT16 Value;\r
67 INT8 *Name;\r
68} STRING_LOOKUP;\r
69\r
70static STRING_LOOKUP mMachineTypes[] = {\r
71 EFI_IMAGE_MACHINE_IA32,\r
72 "IA32",\r
73 EFI_IMAGE_MACHINE_IA64,\r
74 "IA64",\r
75 EFI_IMAGE_MACHINE_EBC,\r
76 "EBC",\r
77 0,\r
78 NULL\r
79};\r
80\r
81static STRING_LOOKUP mSubsystemTypes[] = {\r
82 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION,\r
83 "EFI application",\r
84 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER,\r
85 "EFI boot service driver",\r
86 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER,\r
87 "EFI runtime driver",\r
88 0,\r
89 NULL\r
90};\r
91//\r
92// Function prototypes\r
93//\r
f091efb3 94static\r
95void\r
96Version (\r
97 VOID\r
98 );\r
99\r
d25c4bf0 100static\r
101void\r
102Usage (\r
103 VOID\r
104 );\r
105\r
106static\r
107STATUS\r
108ParseCommandLine (\r
109 int Argc,\r
110 char *Argv[]\r
111 );\r
112\r
f6ab0cee 113static\r
114STATUS\r
115CheckAcpiTable (\r
116 VOID *AcpiTable,\r
117 UINT32 Length\r
118 );\r
119\r
d25c4bf0 120static\r
121STATUS\r
122CheckPE32File (\r
123 INT8 *FileName,\r
124 FILE *Fptr,\r
125 UINT16 *MachineType,\r
126 UINT16 *SubSystem\r
127 );\r
128\r
129static\r
130STATUS\r
131ProcessFile (\r
132 INT8 *InFileName,\r
133 INT8 *OutFileName\r
134 );\r
135\r
136static\r
137void\r
138DumpImage (\r
139 INT8 *FileName\r
140 );\r
141\r
142main (\r
143 int Argc,\r
144 char *Argv[]\r
145 )\r
146/*++\r
147\r
148Routine Description:\r
149 \r
150\r
151Arguments:\r
152\r
153 Argc - standard C main() argument count\r
154\r
155 Argv - standard C main() argument list\r
156\r
157Returns:\r
158\r
159 0 success\r
160 non-zero otherwise\r
161\r
162--*/\r
163// GC_TODO: ] - add argument and description to function comment\r
164{\r
165 UINT32 Status;\r
166\r
167 SetUtilityName (UTILITY_NAME);\r
168 //\r
169 // Parse the command line arguments\r
170 //\r
171 if (ParseCommandLine (Argc, Argv)) {\r
172 return STATUS_ERROR;\r
173 }\r
174 //\r
175 // Make sure we don't have the same filename for input and output files\r
176 //\r
177 if (stricmp (mOptions.OutFileName, mOptions.InFileName) == 0) {\r
178 Error (NULL, 0, 0, mOptions.OutFileName, "input and output file names must be different");\r
179 goto Finish;\r
180 }\r
181 //\r
182 // Process the file\r
183 //\r
184 ProcessFile (mOptions.InFileName, mOptions.OutFileName);\r
185Finish:\r
186 Status = GetUtilityStatus ();\r
187 return Status;\r
188}\r
189\r
190static\r
191STATUS\r
192ProcessFile (\r
193 INT8 *InFileName,\r
194 INT8 *OutFileName\r
195 )\r
196/*++\r
197\r
198Routine Description:\r
199 \r
200 Process a PE32 EFI file.\r
201\r
202Arguments:\r
203\r
204 InFileName - Name of the PE32 EFI file to process.\r
205 OutFileName - Name of the output file for the processed data.\r
206\r
207Returns:\r
208\r
209 0 - successful\r
210\r
211--*/\r
212{\r
213 STATUS Status;\r
214 UINTN Index;\r
215 FILE *InFptr;\r
216 FILE *OutFptr;\r
217 UINT16 MachineType;\r
218 UINT16 SubSystem;\r
219 UINT32 PESigOffset;\r
220 EFI_IMAGE_FILE_HEADER FileHeader;\r
221 EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader32;\r
928fbe8f 222 EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader64;\r
d25c4bf0 223 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
224 UINT8 *Buffer;\r
225 long SaveFilePosition;\r
226\r
227 InFptr = NULL;\r
228 OutFptr = NULL;\r
229 Buffer = NULL;\r
230 Status = STATUS_ERROR;\r
231 //\r
232 // Try to open the input file\r
233 //\r
234 if ((InFptr = fopen (InFileName, "rb")) == NULL) {\r
235 Error (NULL, 0, 0, InFileName, "failed to open input file for reading");\r
236 return STATUS_ERROR;\r
237 }\r
238 //\r
239 // Double-check the file to make sure it's what we expect it to be\r
240 //\r
241 if (CheckPE32File (InFileName, InFptr, &MachineType, &SubSystem) != STATUS_SUCCESS) {\r
242 goto Finish;\r
243 }\r
244 //\r
245 // Per the PE/COFF specification, at offset 0x3C in the file is a 32-bit\r
246 // offset (from the start of the file) to the PE signature, which always\r
247 // follows the MSDOS stub. The PE signature is immediately followed by the\r
248 // COFF file header.\r
249 //\r
250 //\r
251 if (fseek (InFptr, 0x3C, SEEK_SET) != 0) {\r
252 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature in file", NULL);\r
253 goto Finish;\r
254 }\r
255\r
256 if (fread (&PESigOffset, sizeof (PESigOffset), 1, InFptr) != 1) {\r
257 Error (NULL, 0, 0, InFileName, "failed to read PE signature offset from file");\r
258 goto Finish;\r
259 }\r
260\r
261 if (fseek (InFptr, PESigOffset + 4, SEEK_SET) != 0) {\r
262 Error (NULL, 0, 0, InFileName, "failed to seek to PE signature");\r
263 goto Finish;\r
264 }\r
265 //\r
266 // We should now be at the COFF file header. Read it in and verify it's\r
267 // of an image type we support.\r
268 //\r
269 if (fread (&FileHeader, sizeof (EFI_IMAGE_FILE_HEADER), 1, InFptr) != 1) {\r
270 Error (NULL, 0, 0, InFileName, "failed to read file header from image");\r
271 goto Finish;\r
272 }\r
273\r
274 if ((FileHeader.Machine != EFI_IMAGE_MACHINE_IA32) && (FileHeader.Machine != EFI_IMAGE_MACHINE_IA64) && (FileHeader.Machine != EFI_IMAGE_MACHINE_X64)) {\r
275 Error (NULL, 0, 0, InFileName, "image is of an unsupported machine type 0x%X", (UINT32) FileHeader.Machine);\r
276 goto Finish;\r
277 }\r
278 //\r
279 // Read in the optional header. Assume PE32, and if not, then re-read as PE32+\r
280 //\r
281 SaveFilePosition = ftell (InFptr);\r
282 if (fread (&OptionalHeader32, sizeof (EFI_IMAGE_OPTIONAL_HEADER32), 1, InFptr) != 1) {\r
283 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
284 goto Finish;\r
285 }\r
286\r
287 if (OptionalHeader32.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
288 if (fseek (InFptr, SaveFilePosition, SEEK_SET) != 0) {\r
289 Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
290 goto Finish;\r
291 }\r
292\r
928fbe8f 293 if (fread (&OptionalHeader64, sizeof (EFI_IMAGE_OPTIONAL_HEADER64), 1, InFptr) != 1) {\r
d25c4bf0 294 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
295 goto Finish;\r
296 }\r
297 }\r
298 //\r
299 // Search for the ".data" section\r
300 //\r
301 for (Index = 0; Index < FileHeader.NumberOfSections; Index++) {\r
302 if (fread (&SectionHeader, sizeof (EFI_IMAGE_SECTION_HEADER), 1, InFptr) != 1) {\r
303 Error (NULL, 0, 0, InFileName, "failed to read optional header from input file");\r
304 goto Finish;\r
305 }\r
306\r
c6137cfd 307 if (strcmp (SectionHeader.Name, ".data") == 0 || strcmp (SectionHeader.Name, ".sdata") == 0) {\r
d25c4bf0 308 if (fseek (InFptr, SectionHeader.PointerToRawData, SEEK_SET) != 0) {\r
309 Error (NULL, 0, 0, InFileName, "failed to seek to .data section");\r
310 goto Finish;\r
311 }\r
312\r
313 Buffer = (UINT8 *) malloc (SectionHeader.Misc.VirtualSize);\r
314 if (Buffer == NULL) {\r
315 Status = EFI_OUT_OF_RESOURCES;\r
316 goto Finish;\r
317 }\r
318 if (fread (Buffer, SectionHeader.Misc.VirtualSize, 1, InFptr) != 1) {\r
319 Error (NULL, 0, 0, InFileName, "failed to .data section");\r
320 goto Finish;\r
321 }\r
f6ab0cee 322\r
323 //\r
324 // Check Acpi Table\r
325 //\r
326 if (CheckAcpiTable (Buffer, SectionHeader.Misc.VirtualSize) != STATUS_SUCCESS) {\r
327 Error (NULL, 0, 0, InFileName, "failed to check ACPI table");\r
328 goto Finish;\r
329 }\r
330\r
d25c4bf0 331 //\r
332 // Now open our output file\r
333 //\r
334 if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {\r
335 Error (NULL, 0, 0, OutFileName, "failed to open output file for writing");\r
336 goto Finish;\r
337 }\r
338\r
339 if (fwrite (Buffer, SectionHeader.Misc.VirtualSize, 1, OutFptr) != 1) {\r
340 Error (NULL, 0, 0, OutFileName, "failed to write .data section");\r
341 goto Finish;\r
342 }\r
343\r
344 Status = STATUS_SUCCESS;\r
345 goto Finish;\r
346 }\r
347 }\r
348\r
349 Status = STATUS_ERROR;\r
350\r
351Finish:\r
352 if (InFptr != NULL) {\r
353 fclose (InFptr);\r
354 }\r
355 //\r
356 // Close the output file. If there was an error, delete the output file so\r
357 // that a subsequent build will rebuild it.\r
358 //\r
359 if (OutFptr != NULL) {\r
360 fclose (OutFptr);\r
361 if (GetUtilityStatus () == STATUS_ERROR) {\r
362 remove (OutFileName);\r
363 }\r
364 }\r
365\r
366 //\r
367 // Free up our buffer\r
368 //\r
369 if (Buffer != NULL) {\r
370 free (Buffer);\r
371 }\r
372\r
373 return Status;\r
374}\r
375\r
f6ab0cee 376static\r
377STATUS\r
378CheckAcpiTable (\r
379 VOID *AcpiTable,\r
380 UINT32 Length\r
381 )\r
382/*++\r
383\r
384Routine Description:\r
385 \r
386 Check Acpi Table \r
387\r
388Arguments:\r
389\r
390 AcpiTable Buffer for AcpiSection\r
391 Length AcpiSection Length\r
392\r
393Returns:\r
394\r
395 0 success\r
396 non-zero otherwise\r
397\r
398--*/\r
399{\r
400 EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;\r
401 EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;\r
402 UINT32 ExpectedLength;\r
403\r
404 AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;\r
405\r
406 //\r
407 // Generic check for AcpiTable length.\r
408 //\r
409 if (AcpiHeader->Length > Length) {\r
410 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass AcpiTable Length check");\r
411 return STATUS_ERROR;\r
412 }\r
413\r
414 //\r
415 // Currently, we only check must-have tables: FADT, FACS, DSDT,\r
416 // and some important tables: MADT, MCFG.\r
417 //\r
418 switch (AcpiHeader->Signature) {\r
419\r
420 //\r
421 // "FACP" Fixed ACPI Description Table\r
422 //\r
423 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:\r
424 switch (AcpiHeader->Revision) {\r
425 case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
426 ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
427 break;\r
428 case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
429 ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
430 break;\r
431 case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:\r
432 ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);\r
433 break;\r
434 default:\r
435 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP revision check");\r
436 return STATUS_ERROR;\r
437 }\r
438 if (ExpectedLength != AcpiHeader->Length) {\r
439 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACP Length check");\r
440 return STATUS_ERROR;\r
441 }\r
442 break;\r
443\r
444 //\r
445 // "FACS" Firmware ACPI Control Structure\r
446 //\r
447 case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:\r
448 Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;\r
449 if ((Facs->Version != 0) &&\r
450 (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&\r
451 (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){\r
452 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS version check");\r
453 return STATUS_ERROR;\r
454 }\r
455 if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
456 (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&\r
457 (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {\r
458 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass FACS Length check");\r
459 return STATUS_ERROR;\r
460 }\r
461 break;\r
462\r
463 //\r
464 // "DSDT" Differentiated System Description Table\r
465 //\r
466 case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:\r
467 if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {\r
468 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT revision check");\r
469 return STATUS_ERROR;\r
470 }\r
471 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {\r
472 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass DSDT Length check");\r
473 return STATUS_ERROR;\r
474 }\r
475 break;\r
476\r
477 //\r
478 // "APIC" Multiple APIC Description Table\r
479 //\r
480 case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:\r
481 if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
482 (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&\r
483 (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {\r
484 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC revision check");\r
485 return STATUS_ERROR;\r
486 }\r
487 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {\r
488 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass APIC Length check");\r
489 return STATUS_ERROR;\r
490 }\r
491 break;\r
492\r
493 //\r
494 // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table\r
495 //\r
496 case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:\r
497 if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {\r
498 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG revision check");\r
499 return STATUS_ERROR;\r
500 }\r
501 if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {\r
502 Error (NULL, 0, 0, "CheckAcpiTable", "failed to pass MCFG Length check");\r
503 return STATUS_ERROR;\r
504 }\r
505 break;\r
506\r
507 //\r
508 // Other table pass check\r
509 //\r
510 default:\r
511 break;\r
512 }\r
513\r
514 return STATUS_SUCCESS;\r
515}\r
516\r
d25c4bf0 517static\r
518STATUS\r
519CheckPE32File (\r
520 INT8 *FileName,\r
521 FILE *Fptr,\r
522 UINT16 *MachineType,\r
523 UINT16 *SubSystem\r
524 )\r
525/*++\r
526\r
527Routine Description:\r
528\r
529 GC_TODO: Add function description\r
530\r
531Arguments:\r
532\r
533 FileName - GC_TODO: add argument description\r
534 Fptr - GC_TODO: add argument description\r
535 MachineType - GC_TODO: add argument description\r
536 SubSystem - GC_TODO: add argument description\r
537\r
538Returns:\r
539\r
540 GC_TODO: add return values\r
541\r
542--*/\r
543{\r
544 /*++\r
545\r
546Routine Description:\r
547 \r
548 Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
549 PE32 image file, and then return the machine type in the supplied pointer.\r
550\r
551Arguments:\r
552\r
553 Fptr File pointer to the already-opened PE32 file\r
554 MachineType Location to stuff the machine type of the PE32 file. This is needed\r
555 because the image may be Itanium-based, IA32, or EBC.\r
556\r
557Returns:\r
558\r
559 0 success\r
560 non-zero otherwise\r
561\r
562--*/\r
563 EFI_IMAGE_DOS_HEADER DosHeader;\r
564 EFI_IMAGE_FILE_HEADER FileHdr;\r
565 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr;\r
566 UINT32 PESig;\r
567 STATUS Status;\r
568\r
569 Status = STATUS_ERROR;\r
570 //\r
571 // Position to the start of the file\r
572 //\r
573 fseek (Fptr, 0, SEEK_SET);\r
574 //\r
575 // Read the DOS header\r
576 //\r
577 if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {\r
578 Error (NULL, 0, 0, FileName, "failed to read the DOS stub from the input file");\r
579 goto Finish;\r
580 }\r
581 //\r
582 // Check the magic number (0x5A4D)\r
583 //\r
584 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {\r
585 Error (NULL, 0, 0, FileName, "input file does not appear to be a PE32 image (magic number)");\r
586 goto Finish;\r
587 }\r
588 //\r
589 // Position into the file and check the PE signature\r
590 //\r
591 fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);\r
592 if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {\r
593 Error (NULL, 0, 0, FileName, "failed to read PE signature bytes");\r
594 goto Finish;\r
595 }\r
596 //\r
597 // Check the PE signature in the header "PE\0\0"\r
598 //\r
599 if (PESig != EFI_IMAGE_NT_SIGNATURE) {\r
600 Error (NULL, 0, 0, FileName, "file does not appear to be a PE32 image (signature)");\r
601 goto Finish;\r
602 }\r
603 //\r
604 // Read the file header\r
605 //\r
606 if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {\r
607 Error (NULL, 0, 0, FileName, "failed to read PE file header from input file");\r
608 goto Finish;\r
609 }\r
610 //\r
611 // Read the optional header so we can get the subsystem\r
612 //\r
613 if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) {\r
614 Error (NULL, 0, 0, FileName, "failed to read COFF optional header from input file");\r
615 goto Finish;\r
616 }\r
617\r
618 *SubSystem = OptionalHdr.Subsystem;\r
619 //\r
620 // Good to go\r
621 //\r
622 Status = STATUS_SUCCESS;\r
623Finish:\r
624 fseek (Fptr, 0, SEEK_SET);\r
625 return Status;\r
626}\r
627\r
628static\r
629int\r
630ParseCommandLine (\r
631 int Argc,\r
632 char *Argv[]\r
633 )\r
634/*++\r
635\r
636Routine Description:\r
637 \r
638 Given the Argc/Argv program arguments, and a pointer to an options structure,\r
639 parse the command-line options and check their validity.\r
640\r
641\r
642Arguments:\r
643\r
644 Argc - standard C main() argument count\r
645 Argv - standard C main() argument list\r
646\r
647Returns:\r
648\r
649 STATUS_SUCCESS success\r
650 non-zero otherwise\r
651\r
652--*/\r
653// GC_TODO: ] - add argument and description to function comment\r
654{\r
655 //\r
656 // Clear out the options\r
657 //\r
658 memset ((char *) &mOptions, 0, sizeof (mOptions));\r
659 //\r
660 // Skip over the program name\r
661 //\r
662 Argc--;\r
663 Argv++;\r
664\r
f091efb3 665 if (Argc < 1) {\r
666 Usage();\r
667 return STATUS_ERROR;\r
668 }\r
669 \r
670 if ((strcmp(Argv[0], "-h") == 0) || (strcmp(Argv[0], "--help") == 0) ||\r
671 (strcmp(Argv[0], "-?") == 0) || (strcmp(Argv[0], "/?") == 0)) {\r
672 Usage();\r
673 return STATUS_ERROR;\r
674 }\r
675 \r
676 if ((strcmp(Argv[0], "-V") == 0) || (strcmp(Argv[0], "--version") == 0)) {\r
677 Version();\r
678 return STATUS_ERROR;\r
679 }\r
680\r
d25c4bf0 681 if (Argc != 2) {\r
682 Usage ();\r
683 return STATUS_ERROR;\r
684 }\r
685\r
686 strcpy (mOptions.InFileName, Argv[0]);\r
687 //\r
688 // Next argument\r
689 //\r
690 Argv++;\r
691 Argc--;\r
692\r
693 strcpy (mOptions.OutFileName, Argv[0]);\r
694\r
695 return STATUS_SUCCESS;\r
696}\r
697\r
f091efb3 698static\r
699void\r
700Version (\r
701 VOID\r
702 )\r
703{\r
704 printf ("%s v%d.%d -EDK Utility for generating ACPI Table image from an EFI PE32 image.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
705 printf ("Copyright (c) 1999-2006 Intel Corporation. All rights reserved.\n");\r
706}\r
707\r
708\r
d25c4bf0 709static\r
710void\r
711Usage (\r
712 VOID\r
713 )\r
714/*++\r
715\r
716Routine Description:\r
717 \r
718 Print usage information for this utility.\r
719\r
720Arguments:\r
721\r
722 None.\r
723\r
724Returns:\r
725\r
726 Nothing.\r
727\r
728--*/\r
729{\r
730 int Index;\r
731 static const char *Msg[] = {\r
f091efb3 732 "\nUsage: "UTILITY_NAME " {-h|--help|-?|/?|-V|--version} InFileName OutFileName",\r
733 " where:",\r
734 " InFileName - name of the input PE32 file",\r
735 " OutFileName - to write output to OutFileName rather than InFileName"DEFAULT_OUTPUT_EXTENSION,\r
d25c4bf0 736 NULL\r
737 };\r
f091efb3 738 \r
739 Version();\r
d25c4bf0 740 for (Index = 0; Msg[Index] != NULL; Index++) {\r
741 fprintf (stdout, "%s\n", Msg[Index]);\r
742 }\r
743}\r