1208625Sjkim/****************************************************************************** 2208625Sjkim * 3208625Sjkim * Module Name: dtio.c - File I/O support for data table compiler 4208625Sjkim * 5208625Sjkim *****************************************************************************/ 6208625Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9208625Sjkim * All rights reserved. 10208625Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25208625Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29208625Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43208625Sjkim 44209746Sjkim#include <contrib/dev/acpica/compiler/aslcompiler.h> 45209746Sjkim#include <contrib/dev/acpica/compiler/dtcompiler.h> 46281075Sdim#include <contrib/dev/acpica/include/acapps.h> 47208625Sjkim 48208625Sjkim#define _COMPONENT DT_COMPILER 49208625Sjkim ACPI_MODULE_NAME ("dtio") 50208625Sjkim 51208625Sjkim 52209734Sjkim/* Local prototypes */ 53208625Sjkim 54209734Sjkimstatic char * 55209734SjkimDtTrim ( 56209734Sjkim char *String); 57208625Sjkim 58209734Sjkimstatic void 59209734SjkimDtLinkField ( 60209734Sjkim DT_FIELD *Field); 61208625Sjkim 62217365Sjkimstatic ACPI_STATUS 63209734SjkimDtParseLine ( 64209734Sjkim char *LineBuffer, 65209734Sjkim UINT32 Line, 66209734Sjkim UINT32 Offset); 67208625Sjkim 68209734Sjkimstatic void 69209734SjkimDtWriteBinary ( 70209734Sjkim DT_SUBTABLE *Subtable, 71209734Sjkim void *Context, 72209734Sjkim void *ReturnValue); 73208625Sjkim 74217365Sjkimstatic void 75217365SjkimDtDumpBuffer ( 76217365Sjkim UINT32 FileId, 77217365Sjkim UINT8 *Buffer, 78218590Sjkim UINT32 Offset, 79217365Sjkim UINT32 Length); 80209734Sjkim 81245582Sjkimstatic void 82245582SjkimDtDumpSubtableInfo ( 83245582Sjkim DT_SUBTABLE *Subtable, 84245582Sjkim void *Context, 85245582Sjkim void *ReturnValue); 86218590Sjkim 87245582Sjkimstatic void 88245582SjkimDtDumpSubtableTree ( 89245582Sjkim DT_SUBTABLE *Subtable, 90245582Sjkim void *Context, 91245582Sjkim void *ReturnValue); 92245582Sjkim 93245582Sjkim 94209734Sjkim/* States for DtGetNextLine */ 95209734Sjkim 96209734Sjkim#define DT_NORMAL_TEXT 0 97209734Sjkim#define DT_START_QUOTED_STRING 1 98209734Sjkim#define DT_START_COMMENT 2 99209734Sjkim#define DT_SLASH_ASTERISK_COMMENT 3 100209734Sjkim#define DT_SLASH_SLASH_COMMENT 4 101209734Sjkim#define DT_END_COMMENT 5 102220663Sjkim#define DT_MERGE_LINES 6 103234623Sjkim#define DT_ESCAPE_SEQUENCE 7 104209734Sjkim 105306536Sjkimstatic UINT32 Gbl_NextLineOffset; 106209734Sjkim 107209734Sjkim 108208625Sjkim/****************************************************************************** 109208625Sjkim * 110208625Sjkim * FUNCTION: DtTrim 111208625Sjkim * 112208625Sjkim * PARAMETERS: String - Current source code line to trim 113208625Sjkim * 114208625Sjkim * RETURN: Trimmed line. Must be freed by caller. 115208625Sjkim * 116208625Sjkim * DESCRIPTION: Trim left and right spaces 117208625Sjkim * 118208625Sjkim *****************************************************************************/ 119208625Sjkim 120208625Sjkimstatic char * 121208625SjkimDtTrim ( 122208625Sjkim char *String) 123208625Sjkim{ 124208625Sjkim char *Start; 125208625Sjkim char *End; 126208625Sjkim char *ReturnString; 127208625Sjkim ACPI_SIZE Length; 128208625Sjkim 129208625Sjkim 130208625Sjkim /* Skip lines that start with a space */ 131208625Sjkim 132306536Sjkim if (!strcmp (String, " ")) 133208625Sjkim { 134281075Sdim ReturnString = UtStringCacheCalloc (1); 135208625Sjkim return (ReturnString); 136208625Sjkim } 137208625Sjkim 138208625Sjkim /* Setup pointers to start and end of input string */ 139208625Sjkim 140208625Sjkim Start = String; 141306536Sjkim End = String + strlen (String) - 1; 142208625Sjkim 143208625Sjkim /* Find first non-whitespace character */ 144208625Sjkim 145208625Sjkim while ((Start <= End) && ((*Start == ' ') || (*Start == '\t'))) 146208625Sjkim { 147208625Sjkim Start++; 148208625Sjkim } 149208625Sjkim 150208625Sjkim /* Find last non-space character */ 151208625Sjkim 152208625Sjkim while (End >= Start) 153208625Sjkim { 154208625Sjkim if (*End == '\r' || *End == '\n') 155208625Sjkim { 156208625Sjkim End--; 157208625Sjkim continue; 158208625Sjkim } 159208625Sjkim 160208625Sjkim if (*End != ' ') 161208625Sjkim { 162208625Sjkim break; 163208625Sjkim } 164208625Sjkim 165208625Sjkim End--; 166208625Sjkim } 167208625Sjkim 168208625Sjkim /* Remove any quotes around the string */ 169208625Sjkim 170208625Sjkim if (*Start == '\"') 171208625Sjkim { 172208625Sjkim Start++; 173208625Sjkim } 174208625Sjkim if (*End == '\"') 175208625Sjkim { 176208625Sjkim End--; 177208625Sjkim } 178208625Sjkim 179208625Sjkim /* Create the trimmed return string */ 180208625Sjkim 181208625Sjkim Length = ACPI_PTR_DIFF (End, Start) + 1; 182281075Sdim ReturnString = UtStringCacheCalloc (Length + 1); 183306536Sjkim if (strlen (Start)) 184208625Sjkim { 185306536Sjkim strncpy (ReturnString, Start, Length); 186208625Sjkim } 187208625Sjkim 188208625Sjkim ReturnString[Length] = 0; 189208625Sjkim return (ReturnString); 190208625Sjkim} 191208625Sjkim 192208625Sjkim 193208625Sjkim/****************************************************************************** 194208625Sjkim * 195208625Sjkim * FUNCTION: DtLinkField 196208625Sjkim * 197208625Sjkim * PARAMETERS: Field - New field object to link 198208625Sjkim * 199208625Sjkim * RETURN: None 200208625Sjkim * 201208625Sjkim * DESCRIPTION: Link one field name and value to the list 202208625Sjkim * 203208625Sjkim *****************************************************************************/ 204208625Sjkim 205208625Sjkimstatic void 206208625SjkimDtLinkField ( 207208625Sjkim DT_FIELD *Field) 208208625Sjkim{ 209208625Sjkim DT_FIELD *Prev; 210208625Sjkim DT_FIELD *Next; 211208625Sjkim 212208625Sjkim 213208625Sjkim Prev = Next = Gbl_FieldList; 214208625Sjkim 215208625Sjkim while (Next) 216208625Sjkim { 217208625Sjkim Prev = Next; 218208625Sjkim Next = Next->Next; 219208625Sjkim } 220208625Sjkim 221208625Sjkim if (Prev) 222208625Sjkim { 223208625Sjkim Prev->Next = Field; 224208625Sjkim } 225208625Sjkim else 226208625Sjkim { 227208625Sjkim Gbl_FieldList = Field; 228208625Sjkim } 229208625Sjkim} 230208625Sjkim 231208625Sjkim 232208625Sjkim/****************************************************************************** 233208625Sjkim * 234208625Sjkim * FUNCTION: DtParseLine 235208625Sjkim * 236208625Sjkim * PARAMETERS: LineBuffer - Current source code line 237208625Sjkim * Line - Current line number in the source 238208625Sjkim * Offset - Current byte offset of the line 239208625Sjkim * 240217365Sjkim * RETURN: Status 241208625Sjkim * 242208625Sjkim * DESCRIPTION: Parse one source line 243208625Sjkim * 244208625Sjkim *****************************************************************************/ 245208625Sjkim 246217365Sjkimstatic ACPI_STATUS 247208625SjkimDtParseLine ( 248208625Sjkim char *LineBuffer, 249208625Sjkim UINT32 Line, 250208625Sjkim UINT32 Offset) 251208625Sjkim{ 252208625Sjkim char *Start; 253208625Sjkim char *End; 254208625Sjkim char *TmpName; 255208625Sjkim char *TmpValue; 256208625Sjkim char *Name; 257208625Sjkim char *Value; 258208625Sjkim char *Colon; 259208625Sjkim UINT32 Length; 260208625Sjkim DT_FIELD *Field; 261208625Sjkim UINT32 Column; 262208625Sjkim UINT32 NameColumn; 263220663Sjkim BOOLEAN IsNullString = FALSE; 264208625Sjkim 265208625Sjkim 266209734Sjkim if (!LineBuffer) 267208625Sjkim { 268217365Sjkim return (AE_OK); 269208625Sjkim } 270208625Sjkim 271217365Sjkim /* All lines after "Raw Table Data" are ingored */ 272217365Sjkim 273217365Sjkim if (strstr (LineBuffer, ACPI_RAW_TABLE_DATA_HEADER)) 274217365Sjkim { 275217365Sjkim return (AE_NOT_FOUND); 276217365Sjkim } 277217365Sjkim 278208625Sjkim Colon = strchr (LineBuffer, ':'); 279217365Sjkim if (!Colon) 280208625Sjkim { 281217365Sjkim return (AE_OK); 282208625Sjkim } 283208625Sjkim 284208625Sjkim Start = LineBuffer; 285208625Sjkim End = Colon; 286208625Sjkim 287208625Sjkim while (Start < Colon) 288208625Sjkim { 289252279Sjkim if (*Start == '[') 290208625Sjkim { 291252279Sjkim /* Found left bracket, go to the right bracket */ 292208625Sjkim 293208625Sjkim while (Start < Colon && *Start != ']') 294208625Sjkim { 295208625Sjkim Start++; 296208625Sjkim } 297208625Sjkim } 298252279Sjkim else if (*Start != ' ') 299252279Sjkim { 300252279Sjkim break; 301252279Sjkim } 302208625Sjkim 303252279Sjkim Start++; 304208625Sjkim } 305208625Sjkim 306208625Sjkim /* 307208625Sjkim * There are two column values. One for the field name, 308208625Sjkim * and one for the field value. 309208625Sjkim */ 310208625Sjkim Column = ACPI_PTR_DIFF (Colon, LineBuffer) + 3; 311208625Sjkim NameColumn = ACPI_PTR_DIFF (Start, LineBuffer) + 1; 312208625Sjkim 313208625Sjkim Length = ACPI_PTR_DIFF (End, Start); 314208625Sjkim 315208625Sjkim TmpName = UtLocalCalloc (Length + 1); 316306536Sjkim strncpy (TmpName, Start, Length); 317208625Sjkim Name = DtTrim (TmpName); 318208625Sjkim ACPI_FREE (TmpName); 319208625Sjkim 320208625Sjkim Start = End = (Colon + 1); 321208625Sjkim while (*End) 322208625Sjkim { 323208625Sjkim /* Found left quotation, go to the right quotation and break */ 324208625Sjkim 325208625Sjkim if (*End == '"') 326208625Sjkim { 327208625Sjkim End++; 328220663Sjkim 329220663Sjkim /* Check for an explicit null string */ 330220663Sjkim 331220663Sjkim if (*End == '"') 332220663Sjkim { 333220663Sjkim IsNullString = TRUE; 334220663Sjkim } 335218590Sjkim while (*End && (*End != '"')) 336208625Sjkim { 337208625Sjkim End++; 338208625Sjkim } 339208625Sjkim 340208625Sjkim End++; 341208625Sjkim break; 342208625Sjkim } 343208625Sjkim 344218590Sjkim /* 345218590Sjkim * Special "comment" fields at line end, ignore them. 346218590Sjkim * Note: normal slash-slash and slash-asterisk comments are 347218590Sjkim * stripped already by the DtGetNextLine parser. 348218590Sjkim * 349218590Sjkim * TBD: Perhaps DtGetNextLine should parse the following type 350218590Sjkim * of comments also. 351218590Sjkim */ 352220663Sjkim if (*End == '[') 353208625Sjkim { 354220663Sjkim End--; 355208625Sjkim break; 356208625Sjkim } 357306536Sjkim 358208625Sjkim End++; 359208625Sjkim } 360208625Sjkim 361208625Sjkim Length = ACPI_PTR_DIFF (End, Start); 362208625Sjkim TmpValue = UtLocalCalloc (Length + 1); 363219707Sjkim 364306536Sjkim strncpy (TmpValue, Start, Length); 365208625Sjkim Value = DtTrim (TmpValue); 366208625Sjkim ACPI_FREE (TmpValue); 367208625Sjkim 368220663Sjkim /* Create a new field object only if we have a valid value field */ 369220663Sjkim 370220663Sjkim if ((Value && *Value) || IsNullString) 371208625Sjkim { 372281075Sdim Field = UtFieldCacheCalloc (); 373208625Sjkim Field->Name = Name; 374208625Sjkim Field->Value = Value; 375208625Sjkim Field->Line = Line; 376208625Sjkim Field->ByteOffset = Offset; 377208625Sjkim Field->NameColumn = NameColumn; 378208625Sjkim Field->Column = Column; 379281687Sjkim Field->StringLength = Length; 380208625Sjkim 381208625Sjkim DtLinkField (Field); 382208625Sjkim } 383281075Sdim /* Else -- Ignore this field, it has no valid data */ 384219707Sjkim 385217365Sjkim return (AE_OK); 386208625Sjkim} 387208625Sjkim 388208625Sjkim 389208625Sjkim/****************************************************************************** 390208625Sjkim * 391209734Sjkim * FUNCTION: DtGetNextLine 392209734Sjkim * 393209734Sjkim * PARAMETERS: Handle - Open file handle for the source file 394209734Sjkim * 395220663Sjkim * RETURN: Filled line buffer and offset of start-of-line (ASL_EOF on EOF) 396209734Sjkim * 397209734Sjkim * DESCRIPTION: Get the next valid source line. Removes all comments. 398209734Sjkim * Ignores empty lines. 399209734Sjkim * 400209734Sjkim * Handles both slash-asterisk and slash-slash comments. 401209734Sjkim * Also, quoted strings, but no escapes within. 402209734Sjkim * 403209734Sjkim * Line is returned in Gbl_CurrentLineBuffer. 404209734Sjkim * Line number in original file is returned in Gbl_CurrentLineNumber. 405209734Sjkim * 406209734Sjkim *****************************************************************************/ 407209734Sjkim 408218590SjkimUINT32 409209734SjkimDtGetNextLine ( 410306536Sjkim FILE *Handle, 411306536Sjkim UINT32 Flags) 412209734Sjkim{ 413220663Sjkim BOOLEAN LineNotAllBlanks = FALSE; 414209734Sjkim UINT32 State = DT_NORMAL_TEXT; 415209734Sjkim UINT32 CurrentLineOffset; 416209734Sjkim UINT32 i; 417250838Sjkim int c; 418209734Sjkim 419209734Sjkim 420306536Sjkim memset (Gbl_CurrentLineBuffer, 0, Gbl_LineBufferSize); 421240716Sjkim for (i = 0; ;) 422209734Sjkim { 423240716Sjkim /* 424240716Sjkim * If line is too long, expand the line buffers. Also increases 425240716Sjkim * Gbl_LineBufferSize. 426240716Sjkim */ 427240716Sjkim if (i >= Gbl_LineBufferSize) 428240716Sjkim { 429240716Sjkim UtExpandLineBuffers (); 430240716Sjkim } 431240716Sjkim 432250838Sjkim c = getc (Handle); 433209734Sjkim if (c == EOF) 434209734Sjkim { 435218590Sjkim switch (State) 436218590Sjkim { 437218590Sjkim case DT_START_QUOTED_STRING: 438218590Sjkim case DT_SLASH_ASTERISK_COMMENT: 439218590Sjkim 440218590Sjkim AcpiOsPrintf ("**** EOF within comment/string %u\n", State); 441218590Sjkim break; 442218590Sjkim 443218590Sjkim default: 444250838Sjkim 445218590Sjkim break; 446218590Sjkim } 447218590Sjkim 448235945Sjkim /* Standalone EOF is OK */ 449235945Sjkim 450235945Sjkim if (i == 0) 451235945Sjkim { 452235945Sjkim return (ASL_EOF); 453235945Sjkim } 454235945Sjkim 455235945Sjkim /* 456235945Sjkim * Received an EOF in the middle of a line. Terminate the 457235945Sjkim * line with a newline. The next call to this function will 458235945Sjkim * return a standalone EOF. Thus, the upper parsing software 459235945Sjkim * never has to deal with an EOF within a valid line (or 460235945Sjkim * the last line does not get tossed on the floor.) 461235945Sjkim */ 462235945Sjkim c = '\n'; 463235945Sjkim State = DT_NORMAL_TEXT; 464209734Sjkim } 465209734Sjkim 466209734Sjkim switch (State) 467209734Sjkim { 468209734Sjkim case DT_NORMAL_TEXT: 469209734Sjkim 470209734Sjkim /* Normal text, insert char into line buffer */ 471209734Sjkim 472250838Sjkim Gbl_CurrentLineBuffer[i] = (char) c; 473209734Sjkim switch (c) 474209734Sjkim { 475209734Sjkim case '/': 476250838Sjkim 477209734Sjkim State = DT_START_COMMENT; 478209734Sjkim break; 479209734Sjkim 480209734Sjkim case '"': 481250838Sjkim 482209734Sjkim State = DT_START_QUOTED_STRING; 483220663Sjkim LineNotAllBlanks = TRUE; 484209734Sjkim i++; 485209734Sjkim break; 486209734Sjkim 487220663Sjkim case '\\': 488220663Sjkim /* 489220663Sjkim * The continuation char MUST be last char on this line. 490220663Sjkim * Otherwise, it will be assumed to be a valid ASL char. 491220663Sjkim */ 492220663Sjkim State = DT_MERGE_LINES; 493220663Sjkim break; 494220663Sjkim 495209734Sjkim case '\n': 496250838Sjkim 497209734Sjkim CurrentLineOffset = Gbl_NextLineOffset; 498209734Sjkim Gbl_NextLineOffset = (UINT32) ftell (Handle); 499209734Sjkim Gbl_CurrentLineNumber++; 500209734Sjkim 501220663Sjkim /* 502220663Sjkim * Exit if line is complete. Ignore empty lines (only \n) 503220663Sjkim * or lines that contain nothing but blanks. 504220663Sjkim */ 505220663Sjkim if ((i != 0) && LineNotAllBlanks) 506209734Sjkim { 507240716Sjkim if ((i + 1) >= Gbl_LineBufferSize) 508240716Sjkim { 509240716Sjkim UtExpandLineBuffers (); 510240716Sjkim } 511240716Sjkim 512220663Sjkim Gbl_CurrentLineBuffer[i+1] = 0; /* Terminate string */ 513209734Sjkim return (CurrentLineOffset); 514209734Sjkim } 515220663Sjkim 516220663Sjkim /* Toss this line and start a new one */ 517220663Sjkim 518220663Sjkim i = 0; 519220663Sjkim LineNotAllBlanks = FALSE; 520209734Sjkim break; 521209734Sjkim 522209734Sjkim default: 523250838Sjkim 524220663Sjkim if (c != ' ') 525220663Sjkim { 526220663Sjkim LineNotAllBlanks = TRUE; 527220663Sjkim } 528220663Sjkim 529209734Sjkim i++; 530209734Sjkim break; 531209734Sjkim } 532209734Sjkim break; 533209734Sjkim 534209734Sjkim case DT_START_QUOTED_STRING: 535209734Sjkim 536209734Sjkim /* Insert raw chars until end of quoted string */ 537209734Sjkim 538250838Sjkim Gbl_CurrentLineBuffer[i] = (char) c; 539209734Sjkim i++; 540209734Sjkim 541234623Sjkim switch (c) 542209734Sjkim { 543234623Sjkim case '"': 544250838Sjkim 545209734Sjkim State = DT_NORMAL_TEXT; 546234623Sjkim break; 547234623Sjkim 548234623Sjkim case '\\': 549250838Sjkim 550234623Sjkim State = DT_ESCAPE_SEQUENCE; 551234623Sjkim break; 552234623Sjkim 553234623Sjkim case '\n': 554250838Sjkim 555306536Sjkim if (!(Flags & DT_ALLOW_MULTILINE_QUOTES)) 556306536Sjkim { 557306536Sjkim AcpiOsPrintf ( 558306536Sjkim "ERROR at line %u: Unterminated quoted string\n", 559306536Sjkim Gbl_CurrentLineNumber++); 560306536Sjkim State = DT_NORMAL_TEXT; 561306536Sjkim } 562234623Sjkim break; 563234623Sjkim 564234623Sjkim default: /* Get next character */ 565250838Sjkim 566234623Sjkim break; 567209734Sjkim } 568209734Sjkim break; 569209734Sjkim 570234623Sjkim case DT_ESCAPE_SEQUENCE: 571234623Sjkim 572234623Sjkim /* Just copy the escaped character. TBD: sufficient for table compiler? */ 573234623Sjkim 574250838Sjkim Gbl_CurrentLineBuffer[i] = (char) c; 575234623Sjkim i++; 576234623Sjkim State = DT_START_QUOTED_STRING; 577234623Sjkim break; 578234623Sjkim 579209734Sjkim case DT_START_COMMENT: 580209734Sjkim 581209734Sjkim /* Open comment if this character is an asterisk or slash */ 582209734Sjkim 583209734Sjkim switch (c) 584209734Sjkim { 585209734Sjkim case '*': 586250838Sjkim 587209734Sjkim State = DT_SLASH_ASTERISK_COMMENT; 588209734Sjkim break; 589209734Sjkim 590209734Sjkim case '/': 591250838Sjkim 592209734Sjkim State = DT_SLASH_SLASH_COMMENT; 593209734Sjkim break; 594209734Sjkim 595209734Sjkim default: /* Not a comment */ 596250838Sjkim 597241973Sjkim i++; /* Save the preceding slash */ 598240716Sjkim if (i >= Gbl_LineBufferSize) 599240716Sjkim { 600240716Sjkim UtExpandLineBuffers (); 601240716Sjkim } 602240716Sjkim 603250838Sjkim Gbl_CurrentLineBuffer[i] = (char) c; 604209734Sjkim i++; 605209734Sjkim State = DT_NORMAL_TEXT; 606209734Sjkim break; 607209734Sjkim } 608209734Sjkim break; 609209734Sjkim 610209734Sjkim case DT_SLASH_ASTERISK_COMMENT: 611209734Sjkim 612209734Sjkim /* Ignore chars until an asterisk-slash is found */ 613209734Sjkim 614209734Sjkim switch (c) 615209734Sjkim { 616209734Sjkim case '\n': 617250838Sjkim 618209734Sjkim Gbl_NextLineOffset = (UINT32) ftell (Handle); 619209734Sjkim Gbl_CurrentLineNumber++; 620209734Sjkim break; 621209734Sjkim 622209734Sjkim case '*': 623250838Sjkim 624209734Sjkim State = DT_END_COMMENT; 625209734Sjkim break; 626209734Sjkim 627209734Sjkim default: 628250838Sjkim 629209734Sjkim break; 630209734Sjkim } 631209734Sjkim break; 632209734Sjkim 633209734Sjkim case DT_SLASH_SLASH_COMMENT: 634209734Sjkim 635209734Sjkim /* Ignore chars until end-of-line */ 636209734Sjkim 637209734Sjkim if (c == '\n') 638209734Sjkim { 639209734Sjkim /* We will exit via the NORMAL_TEXT path */ 640209734Sjkim 641209734Sjkim ungetc (c, Handle); 642209734Sjkim State = DT_NORMAL_TEXT; 643209734Sjkim } 644209734Sjkim break; 645209734Sjkim 646209734Sjkim case DT_END_COMMENT: 647209734Sjkim 648209734Sjkim /* End comment if this char is a slash */ 649209734Sjkim 650209734Sjkim switch (c) 651209734Sjkim { 652209734Sjkim case '/': 653250838Sjkim 654209734Sjkim State = DT_NORMAL_TEXT; 655209734Sjkim break; 656209734Sjkim 657218590Sjkim case '\n': 658250838Sjkim 659218590Sjkim CurrentLineOffset = Gbl_NextLineOffset; 660218590Sjkim Gbl_NextLineOffset = (UINT32) ftell (Handle); 661218590Sjkim Gbl_CurrentLineNumber++; 662218590Sjkim break; 663218590Sjkim 664218590Sjkim case '*': 665250838Sjkim 666218590Sjkim /* Consume all adjacent asterisks */ 667218590Sjkim break; 668218590Sjkim 669209734Sjkim default: 670250838Sjkim 671209734Sjkim State = DT_SLASH_ASTERISK_COMMENT; 672209734Sjkim break; 673209734Sjkim } 674209734Sjkim break; 675209734Sjkim 676220663Sjkim case DT_MERGE_LINES: 677220663Sjkim 678220663Sjkim if (c != '\n') 679220663Sjkim { 680220663Sjkim /* 681220663Sjkim * This is not a continuation backslash, it is a normal 682220663Sjkim * normal ASL backslash - for example: Scope(\_SB_) 683220663Sjkim */ 684220663Sjkim i++; /* Keep the backslash that is already in the buffer */ 685220663Sjkim 686220663Sjkim ungetc (c, Handle); 687220663Sjkim State = DT_NORMAL_TEXT; 688220663Sjkim } 689220663Sjkim else 690220663Sjkim { 691220663Sjkim /* 692220663Sjkim * This is a continuation line -- a backlash followed 693220663Sjkim * immediately by a newline. Insert a space between the 694220663Sjkim * lines (overwrite the backslash) 695220663Sjkim */ 696220663Sjkim Gbl_CurrentLineBuffer[i] = ' '; 697220663Sjkim i++; 698220663Sjkim 699220663Sjkim /* Ignore newline, this will merge the lines */ 700220663Sjkim 701220663Sjkim CurrentLineOffset = Gbl_NextLineOffset; 702220663Sjkim Gbl_NextLineOffset = (UINT32) ftell (Handle); 703220663Sjkim Gbl_CurrentLineNumber++; 704220663Sjkim State = DT_NORMAL_TEXT; 705220663Sjkim } 706220663Sjkim break; 707220663Sjkim 708209734Sjkim default: 709250838Sjkim 710209734Sjkim DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, "Unknown input state"); 711220663Sjkim return (ASL_EOF); 712209734Sjkim } 713209734Sjkim } 714209734Sjkim} 715209734Sjkim 716209734Sjkim 717209734Sjkim/****************************************************************************** 718209734Sjkim * 719208625Sjkim * FUNCTION: DtScanFile 720208625Sjkim * 721208625Sjkim * PARAMETERS: Handle - Open file handle for the source file 722208625Sjkim * 723208625Sjkim * RETURN: Pointer to start of the constructed parse tree. 724208625Sjkim * 725209734Sjkim * DESCRIPTION: Scan source file, link all field names and values 726208625Sjkim * to the global parse tree: Gbl_FieldList 727208625Sjkim * 728208625Sjkim *****************************************************************************/ 729208625Sjkim 730208625SjkimDT_FIELD * 731208625SjkimDtScanFile ( 732208625Sjkim FILE *Handle) 733208625Sjkim{ 734217365Sjkim ACPI_STATUS Status; 735209734Sjkim UINT32 Offset; 736208625Sjkim 737208625Sjkim 738209734Sjkim ACPI_FUNCTION_NAME (DtScanFile); 739209734Sjkim 740209734Sjkim 741208625Sjkim /* Get the file size */ 742208625Sjkim 743281075Sdim Gbl_InputByteCount = CmGetFileSize (Handle); 744281075Sdim if (Gbl_InputByteCount == ACPI_UINT32_MAX) 745281075Sdim { 746281075Sdim AslAbort (); 747281075Sdim } 748208625Sjkim 749209734Sjkim Gbl_CurrentLineNumber = 0; 750209734Sjkim Gbl_CurrentLineOffset = 0; 751209734Sjkim Gbl_NextLineOffset = 0; 752209734Sjkim 753208625Sjkim /* Scan line-by-line */ 754208625Sjkim 755306536Sjkim while ((Offset = DtGetNextLine (Handle, 0)) != ASL_EOF) 756208625Sjkim { 757209734Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Line %2.2u/%4.4X - %s", 758209734Sjkim Gbl_CurrentLineNumber, Offset, Gbl_CurrentLineBuffer)); 759208625Sjkim 760306536Sjkim Status = DtParseLine (Gbl_CurrentLineBuffer, 761306536Sjkim Gbl_CurrentLineNumber, Offset); 762217365Sjkim if (Status == AE_NOT_FOUND) 763217365Sjkim { 764217365Sjkim break; 765217365Sjkim } 766208625Sjkim } 767208625Sjkim 768220663Sjkim /* Dump the parse tree if debug enabled */ 769220663Sjkim 770245582Sjkim DtDumpFieldList (Gbl_FieldList); 771208625Sjkim return (Gbl_FieldList); 772208625Sjkim} 773208625Sjkim 774208625Sjkim 775208625Sjkim/* 776208625Sjkim * Output functions 777208625Sjkim */ 778208625Sjkim 779208625Sjkim/****************************************************************************** 780208625Sjkim * 781208625Sjkim * FUNCTION: DtWriteBinary 782208625Sjkim * 783208625Sjkim * PARAMETERS: DT_WALK_CALLBACK 784208625Sjkim * 785208625Sjkim * RETURN: Status 786208625Sjkim * 787208625Sjkim * DESCRIPTION: Write one subtable of a binary ACPI table 788208625Sjkim * 789208625Sjkim *****************************************************************************/ 790208625Sjkim 791208625Sjkimstatic void 792208625SjkimDtWriteBinary ( 793208625Sjkim DT_SUBTABLE *Subtable, 794208625Sjkim void *Context, 795208625Sjkim void *ReturnValue) 796208625Sjkim{ 797208625Sjkim 798208625Sjkim FlWriteFile (ASL_FILE_AML_OUTPUT, Subtable->Buffer, Subtable->Length); 799208625Sjkim} 800208625Sjkim 801208625Sjkim 802208625Sjkim/****************************************************************************** 803208625Sjkim * 804208625Sjkim * FUNCTION: DtOutputBinary 805208625Sjkim * 806208625Sjkim * PARAMETERS: 807208625Sjkim * 808208625Sjkim * RETURN: Status 809208625Sjkim * 810208625Sjkim * DESCRIPTION: Write entire binary ACPI table (result of compilation) 811208625Sjkim * 812208625Sjkim *****************************************************************************/ 813208625Sjkim 814208625Sjkimvoid 815208625SjkimDtOutputBinary ( 816208625Sjkim DT_SUBTABLE *RootTable) 817208625Sjkim{ 818208625Sjkim 819208625Sjkim if (!RootTable) 820208625Sjkim { 821208625Sjkim return; 822208625Sjkim } 823208625Sjkim 824208625Sjkim /* Walk the entire parse tree, emitting the binary data */ 825208625Sjkim 826208625Sjkim DtWalkTableTree (RootTable, DtWriteBinary, NULL, NULL); 827281075Sdim 828281075Sdim Gbl_TableLength = CmGetFileSize (Gbl_Files[ASL_FILE_AML_OUTPUT].Handle); 829281075Sdim if (Gbl_TableLength == ACPI_UINT32_MAX) 830281075Sdim { 831281075Sdim AslAbort (); 832281075Sdim } 833208625Sjkim} 834217365Sjkim 835217365Sjkim 836217365Sjkim/* 837217365Sjkim * Listing support 838217365Sjkim */ 839217365Sjkim 840217365Sjkim/****************************************************************************** 841217365Sjkim * 842217365Sjkim * FUNCTION: DtDumpBuffer 843217365Sjkim * 844217365Sjkim * PARAMETERS: FileID - Where to write buffer data 845217365Sjkim * Buffer - Buffer to dump 846218590Sjkim * Offset - Offset in current table 847217365Sjkim * Length - Buffer Length 848217365Sjkim * 849217365Sjkim * RETURN: None 850217365Sjkim * 851217365Sjkim * DESCRIPTION: Another copy of DumpBuffer routine (unfortunately). 852217365Sjkim * 853217365Sjkim * TBD: merge dump buffer routines 854217365Sjkim * 855217365Sjkim *****************************************************************************/ 856217365Sjkim 857217365Sjkimstatic void 858217365SjkimDtDumpBuffer ( 859217365Sjkim UINT32 FileId, 860217365Sjkim UINT8 *Buffer, 861218590Sjkim UINT32 Offset, 862217365Sjkim UINT32 Length) 863217365Sjkim{ 864217365Sjkim UINT32 i; 865217365Sjkim UINT32 j; 866217365Sjkim UINT8 BufChar; 867217365Sjkim 868217365Sjkim 869220663Sjkim FlPrintFile (FileId, "Output: [%3.3Xh %4.4d %3d] ", 870218590Sjkim Offset, Offset, Length); 871218590Sjkim 872217365Sjkim i = 0; 873217365Sjkim while (i < Length) 874217365Sjkim { 875218590Sjkim if (i >= 16) 876218590Sjkim { 877220663Sjkim FlPrintFile (FileId, "%24s", ""); 878218590Sjkim } 879218590Sjkim 880217365Sjkim /* Print 16 hex chars */ 881217365Sjkim 882217365Sjkim for (j = 0; j < 16;) 883217365Sjkim { 884217365Sjkim if (i + j >= Length) 885217365Sjkim { 886217365Sjkim /* Dump fill spaces */ 887217365Sjkim 888217365Sjkim FlPrintFile (FileId, " "); 889217365Sjkim j++; 890217365Sjkim continue; 891217365Sjkim } 892217365Sjkim 893217365Sjkim FlPrintFile (FileId, "%02X ", Buffer[i+j]); 894217365Sjkim j++; 895217365Sjkim } 896217365Sjkim 897217365Sjkim FlPrintFile (FileId, " "); 898217365Sjkim for (j = 0; j < 16; j++) 899217365Sjkim { 900217365Sjkim if (i + j >= Length) 901217365Sjkim { 902217365Sjkim FlPrintFile (FileId, "\n\n"); 903217365Sjkim return; 904217365Sjkim } 905217365Sjkim 906217365Sjkim BufChar = Buffer[(ACPI_SIZE) i + j]; 907306536Sjkim if (isprint (BufChar)) 908217365Sjkim { 909217365Sjkim FlPrintFile (FileId, "%c", BufChar); 910217365Sjkim } 911217365Sjkim else 912217365Sjkim { 913217365Sjkim FlPrintFile (FileId, "."); 914217365Sjkim } 915217365Sjkim } 916217365Sjkim 917217365Sjkim /* Done with that line. */ 918217365Sjkim 919217365Sjkim FlPrintFile (FileId, "\n"); 920217365Sjkim i += 16; 921217365Sjkim } 922217365Sjkim 923217365Sjkim FlPrintFile (FileId, "\n\n"); 924217365Sjkim} 925217365Sjkim 926217365Sjkim 927217365Sjkim/****************************************************************************** 928217365Sjkim * 929245582Sjkim * FUNCTION: DtDumpFieldList 930245582Sjkim * 931245582Sjkim * PARAMETERS: Field - Root field 932245582Sjkim * 933245582Sjkim * RETURN: None 934245582Sjkim * 935245582Sjkim * DESCRIPTION: Dump the entire field list 936245582Sjkim * 937245582Sjkim *****************************************************************************/ 938245582Sjkim 939245582Sjkimvoid 940245582SjkimDtDumpFieldList ( 941245582Sjkim DT_FIELD *Field) 942245582Sjkim{ 943245582Sjkim 944245582Sjkim if (!Gbl_DebugFlag || !Field) 945245582Sjkim { 946245582Sjkim return; 947245582Sjkim } 948245582Sjkim 949245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "\nField List:\n" 950245582Sjkim "LineNo ByteOff NameCol Column TableOff " 951281687Sjkim "Flags %32s : %s\n\n", "Name", "Value"); 952306536Sjkim 953245582Sjkim while (Field) 954245582Sjkim { 955245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 956281687Sjkim "%.08X %.08X %.08X %.08X %.08X %2.2X %32s : %s\n", 957245582Sjkim Field->Line, Field->ByteOffset, Field->NameColumn, 958245582Sjkim Field->Column, Field->TableOffset, Field->Flags, 959245582Sjkim Field->Name, Field->Value); 960245582Sjkim 961245582Sjkim Field = Field->Next; 962245582Sjkim } 963245582Sjkim 964245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, "\n\n"); 965245582Sjkim} 966245582Sjkim 967245582Sjkim 968245582Sjkim/****************************************************************************** 969245582Sjkim * 970245582Sjkim * FUNCTION: DtDumpSubtableInfo, DtDumpSubtableTree 971245582Sjkim * 972245582Sjkim * PARAMETERS: DT_WALK_CALLBACK 973245582Sjkim * 974245582Sjkim * RETURN: None 975245582Sjkim * 976245582Sjkim * DESCRIPTION: Info - dump a subtable tree entry with extra information. 977245582Sjkim * Tree - dump a subtable tree formatted by depth indentation. 978245582Sjkim * 979245582Sjkim *****************************************************************************/ 980245582Sjkim 981245582Sjkimstatic void 982245582SjkimDtDumpSubtableInfo ( 983245582Sjkim DT_SUBTABLE *Subtable, 984245582Sjkim void *Context, 985245582Sjkim void *ReturnValue) 986245582Sjkim{ 987245582Sjkim 988245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 989284460Sjkim "[%.04X] %24s %.08X %.08X %.08X %.08X %.08X %p %p %p\n", 990284460Sjkim Subtable->Depth, Subtable->Name, Subtable->Length, Subtable->TotalLength, 991245582Sjkim Subtable->SizeOfLengthField, Subtable->Flags, Subtable, 992245582Sjkim Subtable->Parent, Subtable->Child, Subtable->Peer); 993245582Sjkim} 994245582Sjkim 995245582Sjkimstatic void 996245582SjkimDtDumpSubtableTree ( 997245582Sjkim DT_SUBTABLE *Subtable, 998245582Sjkim void *Context, 999245582Sjkim void *ReturnValue) 1000245582Sjkim{ 1001245582Sjkim 1002245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 1003284460Sjkim "[%.04X] %24s %*s%08X (%.02X) - (%.02X)\n", 1004284460Sjkim Subtable->Depth, Subtable->Name, (4 * Subtable->Depth), " ", 1005245582Sjkim Subtable, Subtable->Length, Subtable->TotalLength); 1006245582Sjkim} 1007245582Sjkim 1008245582Sjkim 1009245582Sjkim/****************************************************************************** 1010245582Sjkim * 1011245582Sjkim * FUNCTION: DtDumpSubtableList 1012245582Sjkim * 1013245582Sjkim * PARAMETERS: None 1014245582Sjkim * 1015245582Sjkim * RETURN: None 1016245582Sjkim * 1017245582Sjkim * DESCRIPTION: Dump the raw list of subtables with information, and also 1018245582Sjkim * dump the subtable list in formatted tree format. Assists with 1019245582Sjkim * the development of new table code. 1020245582Sjkim * 1021245582Sjkim *****************************************************************************/ 1022245582Sjkim 1023245582Sjkimvoid 1024245582SjkimDtDumpSubtableList ( 1025245582Sjkim void) 1026245582Sjkim{ 1027245582Sjkim 1028245582Sjkim if (!Gbl_DebugFlag || !Gbl_RootTable) 1029245582Sjkim { 1030245582Sjkim return; 1031245582Sjkim } 1032245582Sjkim 1033245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 1034245582Sjkim "Subtable Info:\n" 1035284460Sjkim "Depth Name Length TotalLen LenSize Flags " 1036245582Sjkim "This Parent Child Peer\n\n"); 1037245582Sjkim DtWalkTableTree (Gbl_RootTable, DtDumpSubtableInfo, NULL, NULL); 1038245582Sjkim 1039245582Sjkim DbgPrint (ASL_DEBUG_OUTPUT, 1040284460Sjkim "\nSubtable Tree: (Depth, Name, Subtable, Length, TotalLength)\n\n"); 1041245582Sjkim DtWalkTableTree (Gbl_RootTable, DtDumpSubtableTree, NULL, NULL); 1042281075Sdim 1043281075Sdim DbgPrint (ASL_DEBUG_OUTPUT, "\n"); 1044245582Sjkim} 1045245582Sjkim 1046245582Sjkim 1047245582Sjkim/****************************************************************************** 1048245582Sjkim * 1049217365Sjkim * FUNCTION: DtWriteFieldToListing 1050217365Sjkim * 1051217365Sjkim * PARAMETERS: Buffer - Contains the compiled data 1052217365Sjkim * Field - Field node for the input line 1053217365Sjkim * Length - Length of the output data 1054217365Sjkim * 1055217365Sjkim * RETURN: None 1056217365Sjkim * 1057217365Sjkim * DESCRIPTION: Write one field to the listing file (if listing is enabled). 1058217365Sjkim * 1059217365Sjkim *****************************************************************************/ 1060217365Sjkim 1061217365Sjkimvoid 1062217365SjkimDtWriteFieldToListing ( 1063217365Sjkim UINT8 *Buffer, 1064217365Sjkim DT_FIELD *Field, 1065217365Sjkim UINT32 Length) 1066217365Sjkim{ 1067217365Sjkim UINT8 FileByte; 1068217365Sjkim 1069217365Sjkim 1070217365Sjkim if (!Gbl_ListingFlag || !Field) 1071217365Sjkim { 1072217365Sjkim return; 1073217365Sjkim } 1074217365Sjkim 1075217365Sjkim /* Dump the original source line */ 1076217365Sjkim 1077217365Sjkim FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Input: "); 1078217365Sjkim FlSeekFile (ASL_FILE_INPUT, Field->ByteOffset); 1079217365Sjkim 1080217365Sjkim while (FlReadFile (ASL_FILE_INPUT, &FileByte, 1) == AE_OK) 1081217365Sjkim { 1082217365Sjkim FlWriteFile (ASL_FILE_LISTING_OUTPUT, &FileByte, 1); 1083217365Sjkim if (FileByte == '\n') 1084217365Sjkim { 1085217365Sjkim break; 1086217365Sjkim } 1087217365Sjkim } 1088217365Sjkim 1089217365Sjkim /* Dump the line as parsed and represented internally */ 1090217365Sjkim 1091220663Sjkim FlPrintFile (ASL_FILE_LISTING_OUTPUT, "Parsed: %*s : %.64s", 1092217365Sjkim Field->Column-4, Field->Name, Field->Value); 1093217365Sjkim 1094220663Sjkim if (strlen (Field->Value) > 64) 1095220663Sjkim { 1096220663Sjkim FlPrintFile (ASL_FILE_LISTING_OUTPUT, "...Additional data, length 0x%X\n", 1097220663Sjkim strlen (Field->Value)); 1098220663Sjkim } 1099306536Sjkim 1100220663Sjkim FlPrintFile (ASL_FILE_LISTING_OUTPUT, "\n"); 1101220663Sjkim 1102217365Sjkim /* Dump the hex data that will be output for this field */ 1103217365Sjkim 1104218590Sjkim DtDumpBuffer (ASL_FILE_LISTING_OUTPUT, Buffer, Field->TableOffset, Length); 1105217365Sjkim} 1106217365Sjkim 1107217365Sjkim 1108217365Sjkim/****************************************************************************** 1109217365Sjkim * 1110217365Sjkim * FUNCTION: DtWriteTableToListing 1111217365Sjkim * 1112217365Sjkim * PARAMETERS: None 1113217365Sjkim * 1114217365Sjkim * RETURN: None 1115217365Sjkim * 1116217365Sjkim * DESCRIPTION: Write the entire compiled table to the listing file 1117217365Sjkim * in hex format 1118217365Sjkim * 1119217365Sjkim *****************************************************************************/ 1120217365Sjkim 1121217365Sjkimvoid 1122217365SjkimDtWriteTableToListing ( 1123217365Sjkim void) 1124217365Sjkim{ 1125217365Sjkim UINT8 *Buffer; 1126217365Sjkim 1127217365Sjkim 1128217365Sjkim if (!Gbl_ListingFlag) 1129217365Sjkim { 1130217365Sjkim return; 1131217365Sjkim } 1132217365Sjkim 1133217365Sjkim /* Read the entire table from the output file */ 1134217365Sjkim 1135217365Sjkim Buffer = UtLocalCalloc (Gbl_TableLength); 1136217365Sjkim FlSeekFile (ASL_FILE_AML_OUTPUT, 0); 1137217365Sjkim FlReadFile (ASL_FILE_AML_OUTPUT, Buffer, Gbl_TableLength); 1138217365Sjkim 1139217365Sjkim /* Dump the raw table data */ 1140217365Sjkim 1141217365Sjkim AcpiOsRedirectOutput (Gbl_Files[ASL_FILE_LISTING_OUTPUT].Handle); 1142217365Sjkim 1143217365Sjkim AcpiOsPrintf ("\n%s: Length %d (0x%X)\n\n", 1144217365Sjkim ACPI_RAW_TABLE_DATA_HEADER, Gbl_TableLength, Gbl_TableLength); 1145241973Sjkim AcpiUtDumpBuffer (Buffer, Gbl_TableLength, DB_BYTE_DISPLAY, 0); 1146217365Sjkim 1147217365Sjkim AcpiOsRedirectOutput (stdout); 1148252279Sjkim ACPI_FREE (Buffer); 1149217365Sjkim} 1150