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