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