1 /****************************************************************************** 2 * 3 * Module Name: dtcompile.c - Front-end for data table compiler 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, 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 DtFreeFieldList (); 145 146 if (ACPI_FAILURE (Status)) 147 { 148 /* TBD: temporary error message. Msgs should come from function above */ 149 150 DtError (ASL_ERROR, ASL_MSG_SYNTAX, NULL, 151 "Could not compile input file"); 152 153 goto CleanupAndExit; 154 } 155 156 /* Create/open the binary output file */ 157 158 Gbl_Files[ASL_FILE_AML_OUTPUT].Filename = NULL; 159 Status = FlOpenAmlOutputFile (Gbl_OutputFilenamePrefix); 160 if (ACPI_FAILURE (Status)) 161 { 162 goto CleanupAndExit; 163 } 164 165 /* Write the binary, then the optional hex file */ 166 167 DtOutputBinary (Gbl_RootTable); 168 LsDoHexOutput (); 169 DtWriteTableToListing (); 170 171 CleanupAndExit: 172 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 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 = UtLocalCalloc (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_COMPARE_NAME (Signature, ACPI_SIG_RSDP)) 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 Out; 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 Out: 395 /* Set the final table length and then the checksum */ 396 397 DtSetTableLength (); 398 AcpiTableHeader = ACPI_CAST_PTR ( 399 ACPI_TABLE_HEADER, Gbl_RootTable->Buffer); 400 DtSetTableChecksum (&AcpiTableHeader->Checksum); 401 402 return (AE_OK); 403 } 404 405 406 /****************************************************************************** 407 * 408 * FUNCTION: DtCompileTable 409 * 410 * PARAMETERS: Field - Current field list pointer 411 * Info - Info table for this ACPI table 412 * RetSubtable - Compile result of table 413 * Required - If this subtable must exist 414 * 415 * RETURN: Status 416 * 417 * DESCRIPTION: Compile a subtable 418 * 419 *****************************************************************************/ 420 421 ACPI_STATUS 422 DtCompileTable ( 423 DT_FIELD **Field, 424 ACPI_DMTABLE_INFO *Info, 425 DT_SUBTABLE **RetSubtable, 426 BOOLEAN Required) 427 { 428 DT_FIELD *LocalField; 429 UINT32 Length; 430 DT_SUBTABLE *Subtable; 431 DT_SUBTABLE *InlineSubtable; 432 UINT32 FieldLength = 0; 433 UINT8 FieldType; 434 UINT8 *Buffer; 435 UINT8 *FlagBuffer = NULL; 436 UINT32 CurrentFlagByteOffset = 0; 437 ACPI_STATUS Status; 438 439 440 if (!Field || !*Field) 441 { 442 return (AE_BAD_PARAMETER); 443 } 444 445 Length = DtGetSubtableLength (*Field, Info); 446 if (Length == ASL_EOF) 447 { 448 return (AE_ERROR); 449 } 450 451 Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); 452 453 if (Length > 0) 454 { 455 Subtable->Buffer = UtLocalCalloc (Length); 456 } 457 Subtable->Length = Length; 458 Subtable->TotalLength = Length; 459 Buffer = Subtable->Buffer; 460 461 LocalField = *Field; 462 463 /* 464 * Main loop walks the info table for this ACPI table or subtable 465 */ 466 for (; Info->Name; Info++) 467 { 468 if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 469 { 470 continue; 471 } 472 473 if (!LocalField) 474 { 475 sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 476 Info->Name); 477 DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 478 Status = AE_BAD_DATA; 479 goto Error; 480 } 481 482 /* Maintain table offsets */ 483 484 LocalField->TableOffset = Gbl_CurrentTableOffset; 485 FieldLength = DtGetFieldLength (LocalField, Info); 486 Gbl_CurrentTableOffset += FieldLength; 487 488 FieldType = DtGetFieldType (Info); 489 Gbl_InputFieldCount++; 490 491 switch (FieldType) 492 { 493 case DT_FIELD_TYPE_FLAGS_INTEGER: 494 /* 495 * Start of the definition of a flags field. 496 * This master flags integer starts at value zero, in preparation 497 * to compile and insert the flag fields from the individual bits 498 */ 499 LocalField = LocalField->Next; 500 *Field = LocalField; 501 502 FlagBuffer = Buffer; 503 CurrentFlagByteOffset = Info->Offset; 504 break; 505 506 case DT_FIELD_TYPE_FLAG: 507 508 /* Individual Flag field, can be multiple bits */ 509 510 if (FlagBuffer) 511 { 512 /* 513 * We must increment the FlagBuffer when we have crossed 514 * into the next flags byte within the flags field 515 * of type DT_FIELD_TYPE_FLAGS_INTEGER. 516 */ 517 FlagBuffer += (Info->Offset - CurrentFlagByteOffset); 518 CurrentFlagByteOffset = Info->Offset; 519 520 DtCompileFlag (FlagBuffer, LocalField, Info); 521 } 522 else 523 { 524 /* TBD - this is an internal error */ 525 } 526 527 LocalField = LocalField->Next; 528 *Field = LocalField; 529 break; 530 531 case DT_FIELD_TYPE_INLINE_SUBTABLE: 532 /* 533 * Recursion (one level max): compile GAS (Generic Address) 534 * or Notify in-line subtable 535 */ 536 *Field = LocalField; 537 538 if (Info->Opcode == ACPI_DMT_GAS) 539 { 540 Status = DtCompileTable (Field, AcpiDmTableInfoGas, 541 &InlineSubtable, TRUE); 542 } 543 else 544 { 545 Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify, 546 &InlineSubtable, TRUE); 547 } 548 549 if (ACPI_FAILURE (Status)) 550 { 551 goto Error; 552 } 553 554 DtSetSubtableLength (InlineSubtable); 555 556 ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength); 557 ACPI_FREE (InlineSubtable->Buffer); 558 ACPI_FREE (InlineSubtable); 559 LocalField = *Field; 560 break; 561 562 case DT_FIELD_TYPE_LABEL: 563 564 DtWriteFieldToListing (Buffer, LocalField, 0); 565 LocalField = LocalField->Next; 566 break; 567 568 default: 569 570 /* Normal case for most field types (Integer, String, etc.) */ 571 572 DtCompileOneField (Buffer, LocalField, 573 FieldLength, FieldType, Info->Flags); 574 575 DtWriteFieldToListing (Buffer, LocalField, FieldLength); 576 LocalField = LocalField->Next; 577 578 if (Info->Flags & DT_LENGTH) 579 { 580 /* Field is an Integer that will contain a subtable length */ 581 582 Subtable->LengthField = Buffer; 583 Subtable->SizeOfLengthField = FieldLength; 584 } 585 586 break; 587 } 588 589 Buffer += FieldLength; 590 } 591 592 *Field = LocalField; 593 *RetSubtable = Subtable; 594 return (AE_OK); 595 596 Error: 597 ACPI_FREE (Subtable->Buffer); 598 ACPI_FREE (Subtable); 599 return (Status); 600 } 601