dtsubtable.c revision 250838
11590Srgrimes/****************************************************************************** 2252231Spfg * 31590Srgrimes * Module Name: dtsubtable.c - handling of subtables within ACPI tables 41590Srgrimes * 51590Srgrimes *****************************************************************************/ 61590Srgrimes 71590Srgrimes/* 81590Srgrimes * Copyright (C) 2000 - 2013, Intel Corp. 91590Srgrimes * All rights reserved. 101590Srgrimes * 111590Srgrimes * Redistribution and use in source and binary forms, with or without 121590Srgrimes * modification, are permitted provided that the following conditions 131590Srgrimes * are met: 141590Srgrimes * 1. Redistributions of source code must retain the above copyright 151590Srgrimes * notice, this list of conditions, and the following disclaimer, 161590Srgrimes * without modification. 171590Srgrimes * 2. Redistributions in binary form must reproduce at minimum a disclaimer 181590Srgrimes * substantially similar to the "NO WARRANTY" disclaimer below 191590Srgrimes * ("Disclaimer") and any redistribution must be conditioned upon 201590Srgrimes * including a substantially similar Disclaimer requirement for further 211590Srgrimes * binary redistribution. 221590Srgrimes * 3. Neither the names of the above-listed copyright holders nor the names 231590Srgrimes * of any contributors may be used to endorse or promote products derived 241590Srgrimes * from this software without specific prior written permission. 251590Srgrimes * 261590Srgrimes * Alternatively, this software may be distributed under the terms of the 271590Srgrimes * GNU General Public License ("GPL") version 2 as published by the Free 281590Srgrimes * Software Foundation. 291590Srgrimes * 301590Srgrimes * NO WARRANTY 311590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 321590Srgrimes * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 331590Srgrimes * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 341590Srgrimes * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3587766Smarkm * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3687766Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3787766Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 381590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3928066Scharnier * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 401590Srgrimes * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 411590Srgrimes * POSSIBILITY OF SUCH DAMAGES. 4287766Smarkm */ 431590Srgrimes 441590Srgrimes#define __DTSUBTABLE_C__ 4587766Smarkm 4628066Scharnier#include <contrib/dev/acpica/compiler/aslcompiler.h> 471590Srgrimes#include <contrib/dev/acpica/compiler/dtcompiler.h> 4898200Ssobomax 4998200Ssobomax#define _COMPONENT DT_COMPILER 5096175Sjmallett ACPI_MODULE_NAME ("dtsubtable") 5196175Sjmallett 521590Srgrimes 5328066Scharnier/****************************************************************************** 541590Srgrimes * 55200462Sdelphij * FUNCTION: DtCreateSubtable 56141563Sstefanf * 57132145Stjr * PARAMETERS: Buffer - Input buffer 5817522Sache * Length - Buffer length 591590Srgrimes * RetSubtable - Returned newly created subtable 60200462Sdelphij * 61252231Spfg * RETURN: None 621590Srgrimes * 631590Srgrimes * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO 641590Srgrimes * For example, FACS has 24 bytes reserved at the end 651590Srgrimes * and it's not listed at AcpiDmTableInfoFacs 661590Srgrimes * 671590Srgrimes *****************************************************************************/ 681590Srgrimes 691590Srgrimesvoid 701590SrgrimesDtCreateSubtable ( 711590Srgrimes UINT8 *Buffer, 721590Srgrimes UINT32 Length, 731590Srgrimes DT_SUBTABLE **RetSubtable) 741590Srgrimes{ 751590Srgrimes DT_SUBTABLE *Subtable; 761590Srgrimes 771590Srgrimes 781590Srgrimes Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE)); 791590Srgrimes 801590Srgrimes /* Create a new buffer for the subtable data */ 811590Srgrimes 821590Srgrimes Subtable->Buffer = UtLocalCalloc (Length); 831590Srgrimes ACPI_MEMCPY (Subtable->Buffer, Buffer, Length); 841590Srgrimes 851590Srgrimes Subtable->Length = Length; 861590Srgrimes Subtable->TotalLength = Length; 871590Srgrimes 881590Srgrimes *RetSubtable = Subtable; 891590Srgrimes} 901590Srgrimes 911590Srgrimes 921590Srgrimes/****************************************************************************** 931590Srgrimes * 941590Srgrimes * FUNCTION: DtInsertSubtable 951590Srgrimes * 961590Srgrimes * PARAMETERS: ParentTable - The Parent of the new subtable 971590Srgrimes * Subtable - The new subtable to insert 981590Srgrimes * 99122049Sdes * RETURN: None 100122049Sdes * 10199352Stjr * DESCRIPTION: Insert the new subtable to the parent table 1021590Srgrimes * 10358309Sgreen *****************************************************************************/ 10497238Stjr 1051590Srgrimesvoid 106168921SyarDtInsertSubtable ( 107168921Syar DT_SUBTABLE *ParentTable, 1081590Srgrimes DT_SUBTABLE *Subtable) 1091590Srgrimes{ 110168921Syar DT_SUBTABLE *ChildTable; 111168921Syar 1121590Srgrimes 11387766Smarkm Subtable->Peer = NULL; 114122049Sdes Subtable->Parent = ParentTable; 115122049Sdes Subtable->Depth = ParentTable->Depth + 1; 116122049Sdes 117173437Sdds /* Link the new entry into the child list */ 1181590Srgrimes 1191590Srgrimes if (!ParentTable->Child) 12092922Simp { 12192922Simp ParentTable->Child = Subtable; 12292922Simp } 1231590Srgrimes else 1241590Srgrimes { 125122044Sdes /* Walk to the end of the child list */ 1261590Srgrimes 1271590Srgrimes ChildTable = ParentTable->Child; 12860394Snsayer while (ChildTable->Peer) 1291590Srgrimes { 13017522Sache ChildTable = ChildTable->Peer; 13117522Sache } 1321590Srgrimes 13396175Sjmallett /* Add new subtable at the end of the child list */ 13496175Sjmallett 135268019Spfg ChildTable->Peer = Subtable; 1361590Srgrimes } 137205992Simp} 13858309Sgreen 13958309Sgreen 14058309Sgreen/****************************************************************************** 141168921Syar * 142168921Syar * FUNCTION: DtPushSubtable 143168921Syar * 144168921Syar * PARAMETERS: Subtable - Subtable to push 1451590Srgrimes * 1461590Srgrimes * RETURN: None 1471590Srgrimes * 1481590Srgrimes * DESCRIPTION: Push a subtable onto a subtable stack 1491590Srgrimes * 15080286Sobrien *****************************************************************************/ 15180286Sobrien 15260394Snsayervoid 15360394SnsayerDtPushSubtable ( 15460394Snsayer DT_SUBTABLE *Subtable) 1551590Srgrimes{ 1561590Srgrimes 1571590Srgrimes Subtable->StackTop = Gbl_SubtableStack; 1581590Srgrimes Gbl_SubtableStack = Subtable; 1591590Srgrimes} 16096175Sjmallett 16196175Sjmallett 162168921Syar/****************************************************************************** 16396175Sjmallett * 164146055Sglebius * FUNCTION: DtPopSubtable 165268019Spfg * 166268019Spfg * PARAMETERS: None 167146055Sglebius * 1681590Srgrimes * RETURN: None 1691590Srgrimes * 1701590Srgrimes * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack 171268019Spfg * 172268019Spfg *****************************************************************************/ 173268019Spfg 174268019Spfgvoid 1751590SrgrimesDtPopSubtable ( 1761590Srgrimes void) 17728066Scharnier{ 1781590Srgrimes DT_SUBTABLE *Subtable; 1791590Srgrimes 1801590Srgrimes 1811590Srgrimes Subtable = Gbl_SubtableStack; 1821590Srgrimes 1831590Srgrimes if (Subtable) 1841590Srgrimes { 1851590Srgrimes Gbl_SubtableStack = Subtable->StackTop; 1861590Srgrimes } 1871590Srgrimes} 1881590Srgrimes 1891590Srgrimes 1901590Srgrimes/****************************************************************************** 1911590Srgrimes * 1921590Srgrimes * FUNCTION: DtPeekSubtable 1931590Srgrimes * 1941590Srgrimes * PARAMETERS: None 1951590Srgrimes * 1961590Srgrimes * RETURN: The subtable on top of stack 1971590Srgrimes * 1981590Srgrimes * DESCRIPTION: Get the subtable on top of stack 19928066Scharnier * 20097238Stjr *****************************************************************************/ 2011590Srgrimes 2021590SrgrimesDT_SUBTABLE * 20328066ScharnierDtPeekSubtable ( 204122044Sdes void) 20528066Scharnier{ 206268019Spfg 207268325Spfg return (Gbl_SubtableStack); 208268325Spfg} 209268019Spfg 21028066Scharnier 21128066Scharnier/****************************************************************************** 21228066Scharnier * 2131590Srgrimes * FUNCTION: DtGetNextSubtable 2141590Srgrimes * 2151590Srgrimes * PARAMETERS: ParentTable - Parent table whose children we are 2161590Srgrimes * getting 2171590Srgrimes * ChildTable - Previous child that was found. 218122044Sdes * The NEXT child will be returned 2191590Srgrimes * 2201590Srgrimes * RETURN: Pointer to the NEXT child or NULL if none is found. 2211590Srgrimes * 2221590Srgrimes * DESCRIPTION: Return the next peer subtable within the tree. 2231590Srgrimes * 2241590Srgrimes *****************************************************************************/ 2251590Srgrimes 2261590SrgrimesDT_SUBTABLE * 2271590SrgrimesDtGetNextSubtable ( 2281590Srgrimes DT_SUBTABLE *ParentTable, 22941602Sarchie DT_SUBTABLE *ChildTable) 23041602Sarchie{ 23141602Sarchie ACPI_FUNCTION_ENTRY (); 2321590Srgrimes 23341602Sarchie 2341590Srgrimes if (!ChildTable) 2351590Srgrimes { 2361590Srgrimes /* It's really the parent's _scope_ that we want */ 2371590Srgrimes 23828066Scharnier return (ParentTable->Child); 2391590Srgrimes } 2401590Srgrimes 2411590Srgrimes /* Otherwise just return the next peer (NULL if at end-of-list) */ 2421590Srgrimes 243176126Sdwmalone return (ChildTable->Peer); 2441590Srgrimes} 2451590Srgrimes 2461590Srgrimes 2471590Srgrimes/****************************************************************************** 2481590Srgrimes * 2491590Srgrimes * FUNCTION: DtGetParentSubtable 2501590Srgrimes * 2511590Srgrimes * PARAMETERS: Subtable - Current subtable 2521590Srgrimes * 2531590Srgrimes * RETURN: Parent of the given subtable 2541590Srgrimes * 2551590Srgrimes * DESCRIPTION: Get the parent of the given subtable in the tree 2561590Srgrimes * 2571590Srgrimes *****************************************************************************/ 25841602Sarchie 25941602SarchieDT_SUBTABLE * 2601590SrgrimesDtGetParentSubtable ( 2611590Srgrimes DT_SUBTABLE *Subtable) 2621590Srgrimes{ 2631590Srgrimes 2641590Srgrimes if (!Subtable) 2651590Srgrimes { 2661590Srgrimes return (NULL); 2671590Srgrimes } 2681590Srgrimes 2691590Srgrimes return (Subtable->Parent); 2701590Srgrimes} 2711590Srgrimes 2721590Srgrimes 2731590Srgrimes/****************************************************************************** 27441602Sarchie * 27541602Sarchie * FUNCTION: DtGetSubtableLength 2761590Srgrimes * 2771590Srgrimes * PARAMETERS: Field - Current field list pointer 2781590Srgrimes * Info - Data table info 2791590Srgrimes * 2801590Srgrimes * RETURN: Subtable length 2811590Srgrimes * 2821590Srgrimes * DESCRIPTION: Get length of bytes needed to compile the subtable 2831590Srgrimes * 2841590Srgrimes *****************************************************************************/ 2851590Srgrimes 2861590SrgrimesUINT32 2871590SrgrimesDtGetSubtableLength ( 28841602Sarchie DT_FIELD *Field, 28941602Sarchie ACPI_DMTABLE_INFO *Info) 2901590Srgrimes{ 2911590Srgrimes UINT32 ByteLength = 0; 2921590Srgrimes UINT8 Step; 2931590Srgrimes UINT8 i; 2941590Srgrimes 2951590Srgrimes 2961590Srgrimes /* Walk entire Info table; Null name terminates */ 29741602Sarchie 29841602Sarchie for (; Info->Name; Info++) 2991590Srgrimes { 3001590Srgrimes if (Info->Opcode == ACPI_DMT_EXTRA_TEXT) 3011590Srgrimes { 3021590Srgrimes continue; 3031590Srgrimes } 3041590Srgrimes 3051590Srgrimes if (!Field) 30628066Scharnier { 3071590Srgrimes goto Error; 3081590Srgrimes } 3091590Srgrimes 3101590Srgrimes ByteLength += DtGetFieldLength (Field, Info); 3111590Srgrimes 3121590Srgrimes switch (Info->Opcode) 3131590Srgrimes { 314122044Sdes case ACPI_DMT_GAS: 3151590Srgrimes 316122049Sdes Step = 5; 317252231Spfg break; 318252231Spfg 319252231Spfg case ACPI_DMT_HESTNTFY: 32019829Swosch 32198200Ssobomax Step = 9; 3221590Srgrimes break; 323122049Sdes 32498200Ssobomax default: 32598200Ssobomax 32698200Ssobomax Step = 1; 327168921Syar break; 328122049Sdes } 32998200Ssobomax 330122049Sdes for (i = 0; i < Step; i++) 331122049Sdes { 33298200Ssobomax if (!Field) 33398200Ssobomax { 33498200Ssobomax goto Error; 33598200Ssobomax } 33698200Ssobomax 337122049Sdes Field = Field->Next; 338122049Sdes } 33998200Ssobomax } 34098200Ssobomax 34198200Ssobomax return (ByteLength); 342122049Sdes 34398294StjrError: 34498200Ssobomax if (!Field) 34598200Ssobomax { 346122049Sdes sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed", 347122049Sdes Info->Name); 348130039Sbrian DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer); 349217133Sjilles } 350217133Sjilles 351217133Sjilles return (ASL_EOF); 352217133Sjilles} 353217133Sjilles 354217133Sjilles 355217133Sjilles/****************************************************************************** 356217133Sjilles * 357130039Sbrian * FUNCTION: DtSetSubtableLength 358217133Sjilles * 359217133Sjilles * PARAMETERS: Subtable - Subtable 360130039Sbrian * 361130039Sbrian * RETURN: None 362130039Sbrian * 363122049Sdes * DESCRIPTION: Set length of the subtable into its length field 364130039Sbrian * 365130039Sbrian *****************************************************************************/ 366217133Sjilles 367217133Sjillesvoid 368217133SjillesDtSetSubtableLength ( 369217133Sjilles DT_SUBTABLE *Subtable) 370217133Sjilles{ 371130039Sbrian 372217133Sjilles if (!Subtable->LengthField) 373217133Sjilles { 374217133Sjilles return; 375217133Sjilles } 376217133Sjilles 377217133Sjilles ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength, 378130039Sbrian Subtable->SizeOfLengthField); 379130039Sbrian} 380122049Sdes