1 /****************************************************************************** 2 * 3 * Module Name: dtcompile.c - Front-end for data table compiler 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 #define _DECLARE_DT_GLOBALS 45 46 #include <contrib/dev/acpica/compiler/aslcompiler.h> 47 #include <contrib/dev/acpica/compiler/dtcompiler.h> 48 49 #define _COMPONENT DT_COMPILER 50 ACPI_MODULE_NAME ("dtcompile") 51 52 static char VersionString[9]; 53 54 55 /* Local prototypes */ 56 57 static ACPI_STATUS 58 DtInitialize ( 59 void); 60 61 static ACPI_STATUS 62 DtCompileDataTable ( 63 DT_FIELD **Field); 64 65 static void 66 DtInsertCompilerIds ( 67 DT_FIELD *FieldList); 68 69 70 /****************************************************************************** 71 * 72 * FUNCTION: DtDoCompile 73 * 74 * PARAMETERS: None 75 * 76 * RETURN: Status 77 * 78 * DESCRIPTION: Main entry point for the data table compiler. 79 * 80 * Note: Assumes Gbl_Files[ASL_FILE_INPUT] is initialized and the file is 81 * open at seek offset zero. 82 * 83 *****************************************************************************/ 84 85 ACPI_STATUS 86 DtDoCompile ( 87 void) 88 { 89 ACPI_STATUS Status; 90 UINT8 Event; 91 DT_FIELD *FieldList; 92 93 94 /* Initialize globals */ 95 96 Status = DtInitialize (); 97 if (ACPI_FAILURE (Status)) 98 { 99 printf ("Error during compiler initialization, 0x%X\n", Status); 100 return (Status); 101 } 102 103 /* Preprocessor */ 104 105 Event = UtBeginEvent ("Preprocess input file"); 106 PrDoPreprocess (); 107 UtEndEvent (Event); 108 109 if (Gbl_PreprocessOnly) 110 { 111 return (AE_OK); 112 } 113 114 /* 115 * Scan the input file (file is already open) and 116 * build the parse tree 117 */ 118 Event = UtBeginEvent ("Scan and parse input file"); 119 FieldList = DtScanFile (Gbl_Files[ASL_FILE_INPUT].Handle); 120 UtEndEvent (Event); 121 122 /* Did the parse tree get successfully constructed? */ 123 124 if (!FieldList) 125 { 126 /* TBD: temporary error message. Msgs should come from function above */ 127 128 DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, 129 "Input file does not appear to be an ASL or data table source file"); 130 131 Status = AE_ERROR; 132 goto CleanupAndExit; 133 } 134 135 Event = UtBeginEvent ("Compile parse tree"); 136 137 /* 138 * Compile the parse tree 139 */ 140 Status = DtCompileDataTable (&FieldList); 141 UtEndEvent (Event); 142 143 if (ACPI_FAILURE (Status)) 144 { 145 /* TBD: temporary error message. Msgs should come from function above */ 146 147 DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, 148 "Could not compile input file"); 149 150 goto CleanupAndExit; 151 } 152 153 /* Create/open the binary output file */ 154 155 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL; 156 Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); 157 if (ACPI_FAILURE (Status)) 158 { 159 goto CleanupAndExit; 160 } 161 162 /* Write the binary, then the optional hex file */ 163 164 DtOutputBinary (Gbl_RootTable); 165 HxDoHexOutput (); 166 DtWriteTableToListing (); 167 168 CleanupAndExit: 169 170 AcpiUtDeleteCaches (); 171 DtDeleteCaches (); 172 CmCleanupAndExit (); 173 return (Status); 174 } 175 176 177 /****************************************************************************** 178 * 179 * FUNCTION: DtInitialize 180 * 181 * PARAMETERS: None 182 * 183 * RETURN: Status 184 * 185 * DESCRIPTION: Initialize data table compiler globals. Enables multiple 186 * compiles per invocation. 187 * 188 *****************************************************************************/ 189 190 static ACPI_STATUS 191 DtInitialize ( 192 void) 193 { 194 ACPI_STATUS Status; 195 196 197 Status = AcpiOsInitialize (); 198 if (ACPI_FAILURE (Status)) 199 { 200 return (Status); 201 } 202 203 Status = AcpiUtInitGlobals (); 204 if (ACPI_FAILURE (Status)) 205 { 206 return (Status); 207 } 208 209 Gbl_FieldList = NULL; 210 Gbl_RootTable = NULL; 211 Gbl_SubtableStack = NULL; 212 213 sprintf (VersionString, "%X", (UINT32) ACPI_CA_VERSION); 214 return (AE_OK); 215 } 216 217 218 /****************************************************************************** 219 * 220 * FUNCTION: DtInsertCompilerIds 221 * 222 * PARAMETERS: FieldList - Current field list pointer 223 * 224 * RETURN: None 225 * 226 * DESCRIPTION: Insert the IDs (Name, Version) of the current compiler into 227 * the original ACPI table header. 228 * 229 *****************************************************************************/ 230 231 static void 232 DtInsertCompilerIds ( 233 DT_FIELD *FieldList) 234 { 235 DT_FIELD *Next; 236 UINT32 i; 237 238 239 /* 240 * Don't insert current compiler ID if requested. Used for compiler 241 * debug/validation only. 242 */ 243 if (Gbl_UseOriginalCompilerId) 244 { 245 return; 246 } 247 248 /* Walk to the Compiler fields at the end of the header */ 249 250 Next = FieldList; 251 for (i = 0; i < 7; i++) 252 { 253 Next = Next->Next; 254 } 255 256 Next->Value = ASL_CREATOR_ID; 257 Next->Flags = DT_FIELD_NOT_ALLOCATED; 258 259 Next = Next->Next; 260 Next->Value = VersionString; 261 Next->Flags = DT_FIELD_NOT_ALLOCATED; 262 } 263 264 265 /****************************************************************************** 266 * 267 * FUNCTION: DtCompileDataTable 268 * 269 * PARAMETERS: FieldList - Current field list pointer 270 * 271 * RETURN: Status 272 * 273 * DESCRIPTION: Entry point to compile one data table 274 * 275 *****************************************************************************/ 276 277 static ACPI_STATUS 278 DtCompileDataTable ( 279 DT_FIELD **FieldList) 280 { 281 ACPI_DMTABLE_DATA *TableData; 282 DT_SUBTABLE *Subtable; 283 char *Signature; 284 ACPI_TABLE_HEADER *AcpiTableHeader; 285 ACPI_STATUS Status; 286 DT_FIELD *RootField = *FieldList; 287 288 289 /* Verify that we at least have a table signature and save it */ 290 291 Signature = DtGetFieldValue (*FieldList); 292 if (!Signature) 293 { 294 sprintf (MsgBuffer, "Expected \"%s\"", "Signature"); 295 DtNameError (ASL_ERROR, ASL_MSG_INVALID_FIELD_NAME, 296 *FieldList, MsgBuffer); 297 return (AE_ERROR); 298 } 299 300 Gbl_Signature = UtStringCacheCalloc (ACPI_STRLEN (Signature) + 1); 301 strcpy (Gbl_Signature, Signature); 302 303 /* 304 * Handle tables that don't use the common ACPI table header structure. 305 * Currently, these are the FACS and RSDP. Also check for an OEMx table, 306 * these tables have user-defined contents. 307 */ 308 if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS)) 309 { 310 Status = DtCompileFacs (FieldList); 311 if (ACPI_FAILURE (Status)) 312 { 313 return (Status); 314 } 315 316 DtSetTableLength (); 317 return (Status); 318 } 319 else if (ACPI_VALIDATE_RSDP_SIG (Signature)) 320 { 321 Status = DtCompileRsdp (FieldList); 322 return (Status); 323 } 324 else if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_S3PT)) 325 { 326 Status = DtCompileS3pt (FieldList); 327 if (ACPI_FAILURE (Status)) 328 { 329 return (Status); 330 } 331 332 DtSetTableLength (); 333 return (Status); 334 } 335 336 /* 337 * All other tables must use the common ACPI table header. Insert the 338 * current iASL IDs (name, version), and compile the header now. 339 */ 340 DtInsertCompilerIds (*FieldList); 341 342 Status = DtCompileTable (FieldList, AcpiDmTableInfoHeader, 343 &Gbl_RootTable, TRUE); 344 if (ACPI_FAILURE (Status)) 345 { 346 return (Status); 347 } 348 349 DtPushSubtable (Gbl_RootTable); 350 351 /* Validate the signature via the ACPI table list */ 352 353 TableData = AcpiDmGetTableData (Signature); 354 if (!TableData || Gbl_CompileGeneric) 355 { 356 DtCompileGeneric ((void **) FieldList); 357 goto FinishHeader; 358 } 359 360 /* Dispatch to per-table compile */ 361 362 if (TableData->CmTableHandler) 363 { 364 /* Complex table, has a handler */ 365 366 Status = TableData->CmTableHandler ((void **) FieldList); 367 if (ACPI_FAILURE (Status)) 368 { 369 return (Status); 370 } 371 } 372 else if (TableData->TableInfo) 373 { 374 /* Simple table, just walk the info table */ 375 376 Subtable = NULL; 377 Status = DtCompileTable (FieldList, TableData->TableInfo, 378 &Subtable, TRUE); 379 if (ACPI_FAILURE (Status)) 380 { 381 return (Status); 382 } 383 384 DtInsertSubtable (Gbl_RootTable, Subtable); 385 DtPopSubtable (); 386 } 387 else 388 { 389 DtFatal (ASL_MSG_COMPILER_INTERNAL, *FieldList, 390 "Missing table dispatch info"); 391 return (AE_ERROR); 392 } 393 394 FinishHeader: 395 396 /* Set the final table length and then the checksum */ 397 398 DtSetTableLength (); 399 AcpiTableHeader = ACPI_CAST_PTR ( 400 ACPI_TABLE_HEADER, Gbl_RootTable->Buffer); 401 DtSetTableChecksum (&AcpiTableHeader->Checksum); 402 403 DtDumpFieldList (RootField); 404 DtDumpSubtableList (); 405 return (AE_OK); 406 } 407 408 409 /****************************************************************************** 410 * 411 * FUNCTION: DtCompileTable 412 * 413 * PARAMETERS: Field - Current field list pointer 414 * Info - Info table for this ACPI table 415 * RetSubtable - Compile result of table 416 * Required - If this subtable must exist 417 * 418 * RETURN: Status 419 * 420 * DESCRIPTION: Compile a subtable 421 * 422 *****************************************************************************/ 423 424 ACPI_STATUS 425 DtCompileTable ( 426 DT_FIELD **Field, 427 ACPI_DMTABLE_INFO *Info, 428 DT_SUBTABLE **RetSubtable, 429 BOOLEAN Required) 430 { 431 DT_FIELD *LocalField; 432 UINT32 Length; 433 DT_SUBTABLE *Subtable; 434 DT_SUBTABLE *InlineSubtable; 435 UINT32 FieldLength = 0; 436 UINT8 FieldType; 437 UINT8 *Buffer; 438 UINT8 *FlagBuffer = NULL; 439 char *String; 440 UINT32 CurrentFlagByteOffset = 0; 441 ACPI_STATUS Status; 442 443 444 if (!Field || !*Field) 445 { 446 return (AE_BAD_PARAMETER); 447 } 448 449 /* Ignore optional subtable if name does not match */ 450 451 if ((Info->Flags & DT_OPTIONAL) && 452 ACPI_STRCMP ((*Field)->Name, Info->Name)) 453 { 454 *RetSubtable = NULL; 455 return (AE_OK); 456 } 457 458 Length = DtGetSubtableLength (*Field, Info); 459 if (Length == ASL_EOF) 460 { 461 return (AE_ERROR); 462 } 463 464 Subtable = UtSubtableCacheCalloc (); 465 466 if (Length > 0) 467 { 468 String = UtStringCacheCalloc (Length); 469 Subtable->Buffer = ACPI_CAST_PTR (UINT8, String); 470 } 471 472 Subtable->Length = Length; 473 Subtable->TotalLength = Length; 474 Buffer = Subtable->Buffer; 475 476 LocalField = *Field; 477 478 /* 479 * Main loop walks the info table for this ACPI table or subtable 480 */ 481 for (; Info->Name; Info++) 482 { 483 if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 484 { 485 continue; 486 } 487 488 if (!LocalField) 489 { 490 sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 491 Info->Name); 492 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 493 Status = AE_BAD_DATA; 494 goto Error; 495 } 496 497 /* Maintain table offsets */ 498 499 LocalField->TableOffset = Gbl_CurrentTableOffset; 500 FieldLength = DtGetFieldLength (LocalField, Info); 501 Gbl_CurrentTableOffset += FieldLength; 502 503 FieldType = DtGetFieldType (Info); 504 Gbl_InputFieldCount++; 505 506 switch (FieldType) 507 { 508 case DT_FIELD_TYPE_FLAGS_INTEGER: 509 /* 510 * Start of the definition of a flags field. 511 * This master flags integer starts at value zero, in preparation 512 * to compile and insert the flag fields from the individual bits 513 */ 514 LocalField = LocalField->Next; 515 *Field = LocalField; 516 517 FlagBuffer = Buffer; 518 CurrentFlagByteOffset = Info->Offset; 519 break; 520 521 case DT_FIELD_TYPE_FLAG: 522 523 /* Individual Flag field, can be multiple bits */ 524 525 if (FlagBuffer) 526 { 527 /* 528 * We must increment the FlagBuffer when we have crossed 529 * into the next flags byte within the flags field 530 * of type DT_FIELD_TYPE_FLAGS_INTEGER. 531 */ 532 FlagBuffer += (Info->Offset - CurrentFlagByteOffset); 533 CurrentFlagByteOffset = Info->Offset; 534 535 DtCompileFlag (FlagBuffer, LocalField, Info); 536 } 537 else 538 { 539 /* TBD - this is an internal error */ 540 } 541 542 LocalField = LocalField->Next; 543 *Field = LocalField; 544 break; 545 546 case DT_FIELD_TYPE_INLINE_SUBTABLE: 547 /* 548 * Recursion (one level max): compile GAS (Generic Address) 549 * or Notify in-line subtable 550 */ 551 *Field = LocalField; 552 553 if (Info->Opcode == ACPI_DMT_GAS) 554 { 555 Status = DtCompileTable (Field, AcpiDmTableInfoGas, 556 &InlineSubtable, TRUE); 557 } 558 else 559 { 560 Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify, 561 &InlineSubtable, TRUE); 562 } 563 564 if (ACPI_FAILURE (Status)) 565 { 566 goto Error; 567 } 568 569 DtSetSubtableLength (InlineSubtable); 570 571 ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength); 572 LocalField = *Field; 573 break; 574 575 case DT_FIELD_TYPE_LABEL: 576 577 DtWriteFieldToListing (Buffer, LocalField, 0); 578 LocalField = LocalField->Next; 579 break; 580 581 default: 582 583 /* Normal case for most field types (Integer, String, etc.) */ 584 585 DtCompileOneField (Buffer, LocalField, 586 FieldLength, FieldType, Info->Flags); 587 588 DtWriteFieldToListing (Buffer, LocalField, FieldLength); 589 LocalField = LocalField->Next; 590 591 if (Info->Flags & DT_LENGTH) 592 { 593 /* Field is an Integer that will contain a subtable length */ 594 595 Subtable->LengthField = Buffer; 596 Subtable->SizeOfLengthField = FieldLength; 597 } 598 599 break; 600 } 601 602 Buffer += FieldLength; 603 } 604 605 *Field = LocalField; 606 *RetSubtable = Subtable; 607 return (AE_OK); 608 609 Error: 610 ACPI_FREE (Subtable->Buffer); 611 ACPI_FREE (Subtable); 612 return (Status); 613 } 614