1 /****************************************************************************** 2 * 3 * Module Name: dmtables - disassembler ACPI table support 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2023, 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 MERCHANTABILITY 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 "acdispat.h" 46 #include "acnamesp.h" 47 #include "actables.h" 48 #include "acparser.h" 49 #include "acapps.h" 50 #include "acmacros.h" 51 #include "acconvert.h" 52 53 54 #define _COMPONENT ACPI_TOOLS 55 ACPI_MODULE_NAME ("dmtables") 56 57 58 /* Local prototypes */ 59 60 static void 61 AdCreateTableHeader ( 62 char *Filename, 63 ACPI_TABLE_HEADER *Table); 64 65 static ACPI_STATUS 66 AdStoreTable ( 67 ACPI_TABLE_HEADER *Table, 68 UINT32 *TableIndex); 69 70 71 extern ACPI_TABLE_DESC LocalTables[1]; 72 extern ACPI_PARSE_OBJECT *AcpiGbl_ParseOpRoot; 73 74 75 /****************************************************************************** 76 * 77 * FUNCTION: AdDisassemblerHeader 78 * 79 * PARAMETERS: Filename - Input file for the table 80 * TableType - Either AML or DataTable 81 * 82 * RETURN: None 83 * 84 * DESCRIPTION: Create the disassembler header, including ACPICA signon with 85 * optional current time and date. 86 * 87 *****************************************************************************/ 88 89 void 90 AdDisassemblerHeader ( 91 char *Filename, 92 UINT8 TableType) 93 { 94 time_t Timer; 95 96 97 /* Header and input table info */ 98 99 AcpiOsPrintf ("/*\n"); 100 AcpiOsPrintf (ACPI_COMMON_HEADER (AML_DISASSEMBLER_NAME, " * ")); 101 102 if (TableType == ACPI_IS_AML_TABLE) 103 { 104 if (AcpiGbl_CstyleDisassembly) 105 { 106 AcpiOsPrintf ( 107 " * Disassembling to symbolic ASL+ operators\n" 108 " *\n"); 109 } 110 else 111 { 112 AcpiOsPrintf ( 113 " * Disassembling to non-symbolic legacy ASL operators\n" 114 " *\n"); 115 } 116 } 117 118 if (AslGbl_Deterministic) 119 { 120 AcpiOsPrintf (" * Disassembly of %s\n", Filename); 121 } 122 else 123 { 124 time (&Timer); 125 AcpiOsPrintf (" * Disassembly of %s, %s", Filename, ctime (&Timer)); 126 } 127 AcpiOsPrintf (" *\n"); 128 } 129 130 131 /****************************************************************************** 132 * 133 * FUNCTION: AdCreateTableHeader 134 * 135 * PARAMETERS: Filename - Input file for the table 136 * Table - Pointer to the raw table 137 * 138 * RETURN: None 139 * 140 * DESCRIPTION: Create the ASL table header, including ACPICA signon with 141 * current time and date. 142 * 143 *****************************************************************************/ 144 145 static void 146 AdCreateTableHeader ( 147 char *Filename, 148 ACPI_TABLE_HEADER *Table) 149 { 150 UINT8 Checksum; 151 152 153 /* Reset globals for External statements */ 154 155 AcpiGbl_NumExternalMethods = 0; 156 AcpiGbl_ResolvedExternalMethods = 0; 157 158 /* 159 * Print file header and dump original table header 160 */ 161 AdDisassemblerHeader (Filename, ACPI_IS_AML_TABLE); 162 163 AcpiOsPrintf (" * Original Table Header:\n"); 164 AcpiOsPrintf (" * Signature \"%4.4s\"\n", Table->Signature); 165 AcpiOsPrintf (" * Length 0x%8.8X (%u)\n", Table->Length, Table->Length); 166 167 /* Print and validate the revision */ 168 169 AcpiOsPrintf (" * Revision 0x%2.2X", Table->Revision); 170 171 switch (Table->Revision) 172 { 173 case 0: 174 175 AcpiOsPrintf (" **** Invalid Revision"); 176 break; 177 178 case 1: 179 180 /* Revision of DSDT controls the ACPI integer width */ 181 182 if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_DSDT)) 183 { 184 AcpiOsPrintf (" **** 32-bit table (V1), no 64-bit math support"); 185 } 186 break; 187 188 default: 189 190 break; 191 } 192 193 /* Print and validate the table checksum */ 194 195 AcpiOsPrintf ("\n * Checksum 0x%2.2X", Table->Checksum); 196 197 Checksum = AcpiUtChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length); 198 if (Checksum) 199 { 200 AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X", 201 (UINT8) (Table->Checksum - Checksum)); 202 } 203 204 AcpiOsPrintf ("\n"); 205 AcpiOsPrintf (" * OEM ID \"%.6s\"\n", Table->OemId); 206 AcpiOsPrintf (" * OEM Table ID \"%.8s\"\n", Table->OemTableId); 207 AcpiOsPrintf (" * OEM Revision 0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision); 208 AcpiOsPrintf (" * Compiler ID \"%.4s\"\n", Table->AslCompilerId); 209 AcpiOsPrintf (" * Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision); 210 AcpiOsPrintf (" */\n"); 211 212 /* 213 * Print comments that come before this definition block. 214 */ 215 if (AcpiGbl_CaptureComments) 216 { 217 ASL_CV_PRINT_ONE_COMMENT(AcpiGbl_ParseOpRoot,AML_COMMENT_STANDARD, NULL, 0); 218 } 219 220 /* 221 * Open the ASL definition block. 222 * 223 * Note: the AMLFilename string is left zero-length in order to just let 224 * the compiler create it when the disassembled file is compiled. This 225 * makes it easier to rename the disassembled ASL file if needed. 226 */ 227 AcpiOsPrintf ( 228 "DefinitionBlock (\"\", \"%4.4s\", %u, \"%.6s\", \"%.8s\", 0x%8.8X)\n", 229 Table->Signature, Table->Revision, 230 Table->OemId, Table->OemTableId, Table->OemRevision); 231 } 232 233 234 /****************************************************************************** 235 * 236 * FUNCTION: AdDisplayTables 237 * 238 * PARAMETERS: Filename - Input file for the table 239 * Table - Pointer to the raw table 240 * 241 * RETURN: Status 242 * 243 * DESCRIPTION: Display (disassemble) loaded tables and dump raw tables 244 * 245 *****************************************************************************/ 246 247 ACPI_STATUS 248 AdDisplayTables ( 249 char *Filename, 250 ACPI_TABLE_HEADER *Table) 251 { 252 253 254 if (!AcpiGbl_ParseOpRoot) 255 { 256 return (AE_NOT_EXIST); 257 } 258 259 if (!AcpiGbl_DmOpt_Listing) 260 { 261 AdCreateTableHeader (Filename, Table); 262 } 263 264 AcpiDmDisassemble (NULL, AcpiGbl_ParseOpRoot, ACPI_UINT32_MAX); 265 MpEmitMappingInfo (); 266 267 if (AcpiGbl_DmOpt_Listing) 268 { 269 AcpiOsPrintf ("\n\nTable Header:\n"); 270 AcpiUtDebugDumpBuffer ((UINT8 *) Table, sizeof (ACPI_TABLE_HEADER), 271 DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 272 273 AcpiOsPrintf ("Table Body (Length 0x%X)\n", Table->Length); 274 AcpiUtDebugDumpBuffer (((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)), 275 Table->Length, DB_BYTE_DISPLAY, ACPI_UINT32_MAX); 276 } 277 278 return (AE_OK); 279 } 280 281 282 /******************************************************************************* 283 * 284 * FUNCTION: AdStoreTable 285 * 286 * PARAMETERS: Table - Table header 287 * TableIndex - Where the table index is returned 288 * 289 * RETURN: Status and table index. 290 * 291 * DESCRIPTION: Add an ACPI table to the global table list 292 * 293 ******************************************************************************/ 294 295 static ACPI_STATUS 296 AdStoreTable ( 297 ACPI_TABLE_HEADER *Table, 298 UINT32 *TableIndex) 299 { 300 ACPI_STATUS Status; 301 ACPI_TABLE_DESC *TableDesc; 302 303 304 Status = AcpiTbGetNextTableDescriptor (TableIndex, &TableDesc); 305 if (ACPI_FAILURE (Status)) 306 { 307 return (Status); 308 } 309 310 /* Initialize added table */ 311 312 AcpiTbInitTableDescriptor (TableDesc, ACPI_PTR_TO_PHYSADDR (Table), 313 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table); 314 Status = AcpiTbValidateTable (TableDesc); 315 return (Status); 316 } 317 318 319 /****************************************************************************** 320 * 321 * FUNCTION: AdGetLocalTables 322 * 323 * PARAMETERS: None 324 * 325 * RETURN: Status 326 * 327 * DESCRIPTION: Get the ACPI tables from either memory or a file 328 * 329 *****************************************************************************/ 330 331 ACPI_STATUS 332 AdGetLocalTables ( 333 void) 334 { 335 ACPI_STATUS Status; 336 ACPI_TABLE_HEADER TableHeader; 337 ACPI_TABLE_HEADER *NewTable; 338 UINT32 TableIndex; 339 340 341 /* Get the DSDT via table override */ 342 343 ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT); 344 Status = AcpiOsTableOverride (&TableHeader, &NewTable); 345 if (ACPI_FAILURE (Status) || !NewTable) 346 { 347 fprintf (stderr, "Could not obtain DSDT\n"); 348 return (AE_NO_ACPI_TABLES); 349 } 350 351 AdWriteTable (NewTable, NewTable->Length, 352 ACPI_SIG_DSDT, NewTable->OemTableId); 353 354 /* Store DSDT in the Table Manager */ 355 356 Status = AdStoreTable (NewTable, &TableIndex); 357 if (ACPI_FAILURE (Status)) 358 { 359 fprintf (stderr, "Could not store DSDT\n"); 360 return (AE_NO_ACPI_TABLES); 361 } 362 363 return (AE_OK); 364 } 365 366 367 /****************************************************************************** 368 * 369 * FUNCTION: AdParseTable 370 * 371 * PARAMETERS: Table - Pointer to the raw table 372 * OwnerId - Returned OwnerId of the table 373 * LoadTable - If add table to the global table list 374 * External - If this is an external table 375 * 376 * RETURN: Status 377 * 378 * DESCRIPTION: Parse an ACPI AML table 379 * 380 *****************************************************************************/ 381 382 ACPI_STATUS 383 AdParseTable ( 384 ACPI_TABLE_HEADER *Table, 385 ACPI_OWNER_ID *OwnerId, 386 BOOLEAN LoadTable, 387 BOOLEAN External) 388 { 389 ACPI_STATUS Status = AE_OK; 390 ACPI_WALK_STATE *WalkState; 391 UINT8 *AmlStart; 392 UINT32 AmlLength; 393 UINT32 TableIndex; 394 395 396 if (!Table) 397 { 398 return (AE_NOT_EXIST); 399 } 400 401 /* Pass 1: Parse everything except control method bodies */ 402 403 fprintf (stderr, "Pass 1 parse of [%4.4s]\n", (char *) Table->Signature); 404 405 AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); 406 AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER)); 407 408 AcpiUtSetIntegerWidth (Table->Revision); 409 410 /* Create the root object */ 411 412 AcpiGbl_ParseOpRoot = AcpiPsCreateScopeOp (AmlStart); 413 if (!AcpiGbl_ParseOpRoot) 414 { 415 return (AE_NO_MEMORY); 416 } 417 418 #ifdef ACPI_ASL_COMPILER 419 if (AcpiGbl_CaptureComments) 420 { 421 AcpiGbl_ParseOpRoot->Common.CvFilename = AcpiGbl_FileTreeRoot->Filename; 422 } 423 else 424 { 425 AcpiGbl_ParseOpRoot->Common.CvFilename = NULL; 426 } 427 #endif 428 429 /* Create and initialize a new walk state */ 430 431 WalkState = AcpiDsCreateWalkState (0, AcpiGbl_ParseOpRoot, NULL, NULL); 432 if (!WalkState) 433 { 434 return (AE_NO_MEMORY); 435 } 436 437 Status = AcpiDsInitAmlWalk (WalkState, AcpiGbl_ParseOpRoot, 438 NULL, AmlStart, AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); 439 if (ACPI_FAILURE (Status)) 440 { 441 return (Status); 442 } 443 444 WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; 445 446 Status = AcpiPsParseAml (WalkState); 447 if (ACPI_FAILURE (Status)) 448 { 449 return (Status); 450 } 451 452 /* If LoadTable is FALSE, we are parsing the last loaded table */ 453 454 TableIndex = AcpiGbl_RootTableList.CurrentTableCount - 1; 455 456 /* Pass 2 */ 457 458 if (LoadTable) 459 { 460 Status = AdStoreTable (Table, &TableIndex); 461 if (ACPI_FAILURE (Status)) 462 { 463 return (Status); 464 } 465 Status = AcpiTbAllocateOwnerId (TableIndex); 466 if (ACPI_FAILURE (Status)) 467 { 468 return (Status); 469 } 470 if (OwnerId) 471 { 472 Status = AcpiTbGetOwnerId (TableIndex, OwnerId); 473 if (ACPI_FAILURE (Status)) 474 { 475 return (Status); 476 } 477 } 478 } 479 480 fprintf (stderr, "Pass 2 parse of [%4.4s]\n", (char *) Table->Signature); 481 482 Status = AcpiNsOneCompleteParse (ACPI_IMODE_LOAD_PASS2, TableIndex, NULL); 483 if (ACPI_FAILURE (Status)) 484 { 485 return (Status); 486 } 487 488 /* No need to parse control methods of external table */ 489 490 if (External) 491 { 492 return (AE_OK); 493 } 494 495 /* 496 * Pass 3: Parse control methods and link their parse trees 497 * into the main parse tree 498 */ 499 fprintf (stderr, 500 "Parsing Deferred Opcodes (Methods/Buffers/Packages/Regions)\n"); 501 502 (void) AcpiDmParseDeferredOps (AcpiGbl_ParseOpRoot); 503 fprintf (stderr, "\n"); 504 505 /* Process Resource Templates */ 506 507 AcpiDmFindResources (AcpiGbl_ParseOpRoot); 508 509 fprintf (stderr, "Parsing completed\n"); 510 return (AE_OK); 511 } 512