adisasm.c revision 1.1.1.4.2.3 1 /******************************************************************************
2 *
3 * Module Name: adisasm - Application-level disassembler routines
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44 #include "aslcompiler.h"
45 #include "amlcode.h"
46 #include "acdisasm.h"
47 #include "acdispat.h"
48 #include "acnamesp.h"
49 #include "acparser.h"
50 #include "acapps.h"
51
52 #include <stdio.h>
53
54
55 #define _COMPONENT ACPI_TOOLS
56 ACPI_MODULE_NAME ("adisasm")
57
58 /* Local prototypes */
59
60 static ACPI_STATUS
61 AdDoExternalFileList (
62 char *Filename);
63
64 static ACPI_STATUS
65 AdDisassembleOneTable (
66 ACPI_TABLE_HEADER *Table,
67 FILE *File,
68 char *Filename,
69 char *DisasmFilename);
70
71 static ACPI_STATUS
72 AdReparseOneTable (
73 ACPI_TABLE_HEADER *Table,
74 FILE *File,
75 ACPI_OWNER_ID OwnerId);
76
77
78 ACPI_TABLE_DESC LocalTables[1];
79 ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot;
80
81
82 /* Stubs for everything except ASL compiler */
83
84 #ifndef ACPI_ASL_COMPILER
85 BOOLEAN
86 AcpiDsIsResultUsed (
87 ACPI_PARSE_OBJECT *Op,
88 ACPI_WALK_STATE *WalkState)
89 {
90 return (TRUE);
91 }
92
93 ACPI_STATUS
94 AcpiDsMethodError (
95 ACPI_STATUS Status,
96 ACPI_WALK_STATE *WalkState)
97 {
98 return (Status);
99 }
100 #endif
101
102
103 /*******************************************************************************
104 *
105 * FUNCTION: AdInitialize
106 *
107 * PARAMETERS: None
108 *
109 * RETURN: Status
110 *
111 * DESCRIPTION: ACPICA and local initialization
112 *
113 ******************************************************************************/
114
115 ACPI_STATUS
116 AdInitialize (
117 void)
118 {
119 ACPI_STATUS Status;
120
121
122 /* ACPICA subsystem initialization */
123
124 Status = AcpiOsInitialize ();
125 if (ACPI_FAILURE (Status))
126 {
127 return (Status);
128 }
129
130 Status = AcpiUtInitGlobals ();
131 if (ACPI_FAILURE (Status))
132 {
133 return (Status);
134 }
135
136 Status = AcpiUtMutexInitialize ();
137 if (ACPI_FAILURE (Status))
138 {
139 return (Status);
140 }
141
142 Status = AcpiNsRootInitialize ();
143 if (ACPI_FAILURE (Status))
144 {
145 return (Status);
146 }
147
148 /* Setup the Table Manager (cheat - there is no RSDT) */
149
150 AcpiGbl_RootTableList.MaxTableCount = 1;
151 AcpiGbl_RootTableList.CurrentTableCount = 0;
152 AcpiGbl_RootTableList.Tables = LocalTables;
153
154 return (Status);
155 }
156
157
158 /******************************************************************************
159 *
160 * FUNCTION: AdAmlDisassemble
161 *
162 * PARAMETERS: Filename - AML input filename
163 * OutToFile - TRUE if output should go to a file
164 * Prefix - Path prefix for output
165 * OutFilename - where the filename is returned
166 *
167 * RETURN: Status
168 *
169 * DESCRIPTION: Disassembler entry point. Disassemble an entire ACPI table.
170 *
171 *****************************************************************************/
172
173 ACPI_STATUS
174 AdAmlDisassemble (
175 BOOLEAN OutToFile,
176 char *Filename,
177 char *Prefix,
178 char **OutFilename)
179 {
180 ACPI_STATUS Status;
181 char *DisasmFilename = NULL;
182 FILE *File = NULL;
183 ACPI_TABLE_HEADER *Table = NULL;
184 ACPI_NEW_TABLE_DESC *ListHead = NULL;
185
186
187 /*
188 * Input: AML code from either a file or via GetTables (memory or
189 * registry)
190 */
191 if (Filename)
192 {
193 /* Get the list of all AML tables in the file */
194
195 Status = AcGetAllTablesFromFile (Filename,
196 ACPI_GET_ALL_TABLES, &ListHead);
197 if (ACPI_FAILURE (Status))
198 {
199 AcpiOsPrintf ("Could not get ACPI tables from %s, %s\n",
200 Filename, AcpiFormatException (Status));
201 return (Status);
202 }
203
204 /* Process any user-specified files for external objects */
205
206 Status = AdDoExternalFileList (Filename);
207 if (ACPI_FAILURE (Status))
208 {
209 return (Status);
210 }
211 }
212 else
213 {
214 Status = AdGetLocalTables ();
215 if (ACPI_FAILURE (Status))
216 {
217 AcpiOsPrintf ("Could not get ACPI tables, %s\n",
218 AcpiFormatException (Status));
219 return (Status);
220 }
221
222 if (!AcpiGbl_DmOpt_Disasm)
223 {
224 return (AE_OK);
225 }
226
227 /* Obtained the local tables, just disassemble the DSDT */
228
229 Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
230 if (ACPI_FAILURE (Status))
231 {
232 AcpiOsPrintf ("Could not get DSDT, %s\n",
233 AcpiFormatException (Status));
234 return (Status);
235 }
236
237 AcpiOsPrintf ("\nDisassembly of DSDT\n");
238 Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
239 }
240
241 /*
242 * Output: ASL code. Redirect to a file if requested
243 */
244 if (OutToFile)
245 {
246 /* Create/Open a disassembly output file */
247
248 DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
249 if (!DisasmFilename)
250 {
251 fprintf (stderr, "Could not generate output filename\n");
252 Status = AE_ERROR;
253 goto Cleanup;
254 }
255
256 File = fopen (DisasmFilename, "w+");
257 if (!File)
258 {
259 fprintf (stderr, "Could not open output file %s\n",
260 DisasmFilename);
261 Status = AE_ERROR;
262 goto Cleanup;
263 }
264
265 AcpiOsRedirectOutput (File);
266 }
267
268 *OutFilename = DisasmFilename;
269
270 /* Disassemble all AML tables within the file */
271
272 while (ListHead)
273 {
274 Status = AdDisassembleOneTable (ListHead->Table,
275 File, Filename, DisasmFilename);
276 if (ACPI_FAILURE (Status))
277 {
278 break;
279 }
280
281 ListHead = ListHead->Next;
282 }
283
284 Cleanup:
285
286 if (Table &&
287 !AcpiGbl_ForceAmlDisassembly &&
288 !AcpiUtIsAmlTable (Table))
289 {
290 ACPI_FREE (Table);
291 }
292
293 if (File)
294 {
295 fclose (File);
296 AcpiOsRedirectOutput (stdout);
297 }
298
299 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
300 AcpiGbl_ParseOpRoot = NULL;
301 return (Status);
302 }
303
304
305 /******************************************************************************
306 *
307 * FUNCTION: AdDisassembleOneTable
308 *
309 * PARAMETERS: Table - Raw AML table
310 * File - Pointer for the input file
311 * Filename - AML input filename
312 * DisasmFilename - Output filename
313 *
314 * RETURN: Status
315 *
316 * DESCRIPTION: Disassemble a single ACPI table. AML or data table.
317 *
318 *****************************************************************************/
319
320 static ACPI_STATUS
321 AdDisassembleOneTable (
322 ACPI_TABLE_HEADER *Table,
323 FILE *File,
324 char *Filename,
325 char *DisasmFilename)
326 {
327 ACPI_STATUS Status;
328 ACPI_OWNER_ID OwnerId;
329
330
331 /* ForceAmlDisassembly means to assume the table contains valid AML */
332
333 if (!AcpiGbl_ForceAmlDisassembly && !AcpiUtIsAmlTable (Table))
334 {
335 AdDisassemblerHeader (Filename, ACPI_IS_DATA_TABLE);
336
337 /* This is a "Data Table" (non-AML table) */
338
339 AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
340 Table->Signature);
341 AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength] "
342 "FieldName : FieldValue\n */\n\n");
343
344 AcpiDmDumpDataTable (Table);
345 fprintf (stderr, "Acpi Data Table [%4.4s] decoded\n",
346 Table->Signature);
347
348 if (File)
349 {
350 fprintf (stderr, "Formatted output: %s - %u bytes\n",
351 DisasmFilename, CmGetFileSize (File));
352 }
353
354 return (AE_OK);
355 }
356
357 /*
358 * This is an AML table (DSDT or SSDT).
359 * Always parse the tables, only option is what to display
360 */
361 Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
362 if (ACPI_FAILURE (Status))
363 {
364 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
365 AcpiFormatException (Status));
366 return (Status);
367 }
368
369 /* Debug output, namespace and parse tree */
370
371 if (AslCompilerdebug && File)
372 {
373 AcpiOsPrintf ("/**** Before second load\n");
374
375 NsSetupNamespaceListing (File);
376 NsDisplayNamespace ();
377
378 AcpiOsPrintf ("*****/\n");
379 }
380
381 /* Load namespace from names created within control methods */
382
383 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
384 AcpiGbl_RootNode, OwnerId);
385
386 /*
387 * Cross reference the namespace here, in order to
388 * generate External() statements
389 */
390 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
391 AcpiGbl_RootNode, OwnerId);
392
393 if (AslCompilerdebug)
394 {
395 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
396 }
397
398 /* Find possible calls to external control methods */
399
400 AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);
401
402 /*
403 * If we found any external control methods, we must reparse
404 * the entire tree with the new information (namely, the
405 * number of arguments per method)
406 */
407 if (AcpiDmGetExternalMethodCount ())
408 {
409 Status = AdReparseOneTable (Table, File, OwnerId);
410 if (ACPI_FAILURE (Status))
411 {
412 return (Status);
413 }
414 }
415
416 /*
417 * Now that the namespace is finalized, we can perform namespace
418 * transforms.
419 *
420 * 1) Convert fixed-offset references to resource descriptors
421 * to symbolic references (Note: modifies namespace)
422 */
423 AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);
424
425 /* Optional displays */
426
427 if (AcpiGbl_DmOpt_Disasm)
428 {
429 /* This is the real disassembly */
430
431 AdDisplayTables (Filename, Table);
432
433 /* Dump hex table if requested (-vt) */
434
435 AcpiDmDumpDataTable (Table);
436
437 fprintf (stderr, "Disassembly completed\n");
438 if (File)
439 {
440 fprintf (stderr, "ASL Output: %s - %u bytes\n",
441 DisasmFilename, CmGetFileSize (File));
442 }
443
444 if (Gbl_MapfileFlag)
445 {
446 fprintf (stderr, "%14s %s - %u bytes\n",
447 Gbl_Files[ASL_FILE_MAP_OUTPUT].ShortDescription,
448 Gbl_Files[ASL_FILE_MAP_OUTPUT].Filename,
449 FlGetFileSize (ASL_FILE_MAP_OUTPUT));
450 }
451 }
452
453 return (AE_OK);
454 }
455
456
457 /******************************************************************************
458 *
459 * FUNCTION: AdReparseOneTable
460 *
461 * PARAMETERS: Table - Raw AML table
462 * File - Pointer for the input file
463 * OwnerId - ID for this table
464 *
465 * RETURN: Status
466 *
467 * DESCRIPTION: Reparse a table that has already been loaded. Used to
468 * integrate information about external control methods.
469 * These methods may have been previously parsed incorrectly.
470 *
471 *****************************************************************************/
472
473 static ACPI_STATUS
474 AdReparseOneTable (
475 ACPI_TABLE_HEADER *Table,
476 FILE *File,
477 ACPI_OWNER_ID OwnerId)
478 {
479 ACPI_STATUS Status;
480
481
482 fprintf (stderr,
483 "\nFound %u external control methods, "
484 "reparsing with new information\n",
485 AcpiDmGetExternalMethodCount ());
486
487 /* Reparse, rebuild namespace */
488
489 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
490 AcpiGbl_ParseOpRoot = NULL;
491 AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);
492
493 AcpiGbl_RootNode = NULL;
494 AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
495 AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
496 AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE;
497 AcpiGbl_RootNodeStruct.Parent = NULL;
498 AcpiGbl_RootNodeStruct.Child = NULL;
499 AcpiGbl_RootNodeStruct.Peer = NULL;
500 AcpiGbl_RootNodeStruct.Object = NULL;
501 AcpiGbl_RootNodeStruct.Flags = 0;
502
503 Status = AcpiNsRootInitialize ();
504 if (ACPI_FAILURE (Status))
505 {
506 return (Status);
507 }
508
509 /* New namespace, add the external definitions first */
510
511 AcpiDmAddExternalsToNamespace ();
512
513 /* Parse the table again. No need to reload it, however */
514
515 Status = AdParseTable (Table, NULL, FALSE, FALSE);
516 if (ACPI_FAILURE (Status))
517 {
518 AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
519 AcpiFormatException (Status));
520 return (Status);
521 }
522
523 /* Cross reference the namespace again */
524
525 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
526 AcpiGbl_RootNode, OwnerId);
527
528 AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot,
529 AcpiGbl_RootNode, OwnerId);
530
531 /* Debug output - namespace and parse tree */
532
533 if (AslCompilerdebug)
534 {
535 AcpiOsPrintf ("/**** After second load and resource conversion\n");
536 if (File)
537 {
538 NsSetupNamespaceListing (File);
539 NsDisplayNamespace ();
540 }
541
542 AcpiOsPrintf ("*****/\n");
543 AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
544 }
545
546 return (AE_OK);
547 }
548
549
550 /******************************************************************************
551 *
552 * FUNCTION: AdDoExternalFileList
553 *
554 * PARAMETERS: Filename - Input file for the table
555 *
556 * RETURN: Status
557 *
558 * DESCRIPTION: Process all tables found in the -e external files list
559 *
560 *****************************************************************************/
561
562 static ACPI_STATUS
563 AdDoExternalFileList (
564 char *Filename)
565 {
566 ACPI_EXTERNAL_FILE *ExternalFileList;
567 char *ExternalFilename;
568 ACPI_NEW_TABLE_DESC *ExternalListHead = NULL;
569 ACPI_STATUS Status;
570 ACPI_STATUS GlobalStatus = AE_OK;
571 ACPI_OWNER_ID OwnerId;
572
573
574 /*
575 * External filenames are specified on the command line like this:
576 * Example: iasl -e file1,file2,file3 -d xxx.aml
577 */
578 ExternalFileList = AcpiGbl_ExternalFileList;
579
580 /* Process each external file */
581
582 while (ExternalFileList)
583 {
584 ExternalFilename = ExternalFileList->Path;
585 if (!strcmp (ExternalFilename, Filename))
586 {
587 /* Next external file */
588
589 ExternalFileList = ExternalFileList->Next;
590 continue;
591 }
592
593 AcpiOsPrintf ("External object resolution file %16s\n",
594 ExternalFilename);
595
596 Status = AcGetAllTablesFromFile (
597 ExternalFilename, ACPI_GET_ONLY_AML_TABLES, &ExternalListHead);
598 if (ACPI_FAILURE (Status))
599 {
600 if (Status == AE_TYPE)
601 {
602 ExternalFileList = ExternalFileList->Next;
603 GlobalStatus = AE_TYPE;
604 Status = AE_OK;
605 continue;
606 }
607
608 return (Status);
609 }
610
611 /* Load external tables for symbol resolution */
612
613 while (ExternalListHead)
614 {
615 Status = AdParseTable (
616 ExternalListHead->Table, &OwnerId, TRUE, TRUE);
617 if (ACPI_FAILURE (Status))
618 {
619 AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
620 AcpiFormatException (Status));
621 return (Status);
622 }
623
624 /*
625 * Load namespace from names created within control methods
626 * Set owner id of nodes in external table
627 */
628 AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
629 AcpiGbl_RootNode, OwnerId);
630 AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
631
632 ExternalListHead = ExternalListHead->Next;
633 }
634
635 /* Next external file */
636
637 ExternalFileList = ExternalFileList->Next;
638 }
639
640 if (ACPI_FAILURE (GlobalStatus))
641 {
642 return (GlobalStatus);
643 }
644
645 /* Clear external list generated by Scope in external tables */
646
647 if (AcpiGbl_ExternalFileList)
648 {
649 AcpiDmClearExternalList ();
650 }
651
652 /* Load any externals defined in the optional external ref file */
653
654 AcpiDmGetExternalsFromFile ();
655 return (AE_OK);
656 }
657