Home | History | Annotate | Line # | Download | only in compiler
dtsubtable.c revision 1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: dtsubtable.c - handling of subtables within ACPI tables
      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 __DTSUBTABLE_C__
     45 
     46 #include "aslcompiler.h"
     47 #include "dtcompiler.h"
     48 
     49 #define _COMPONENT          DT_COMPILER
     50         ACPI_MODULE_NAME    ("dtsubtable")
     51 
     52 
     53 /******************************************************************************
     54  *
     55  * FUNCTION:    DtCreateSubtable
     56  *
     57  * PARAMETERS:  Buffer              - Input buffer
     58  *              Length              - Buffer length
     59  *              RetSubtable         - Returned newly created subtable
     60  *
     61  * RETURN:      None
     62  *
     63  * DESCRIPTION: Create a subtable that is not listed with ACPI_DMTABLE_INFO
     64  *              For example, FACS has 24 bytes reserved at the end
     65  *              and it's not listed at AcpiDmTableInfoFacs
     66  *
     67  *****************************************************************************/
     68 
     69 void
     70 DtCreateSubtable (
     71     UINT8                   *Buffer,
     72     UINT32                  Length,
     73     DT_SUBTABLE             **RetSubtable)
     74 {
     75     DT_SUBTABLE             *Subtable;
     76     char                    *String;
     77 
     78 
     79     Subtable = UtSubtableCacheCalloc ();
     80 
     81     /* Create a new buffer for the subtable data */
     82 
     83     String = UtStringCacheCalloc (Length);
     84     Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
     85     ACPI_MEMCPY (Subtable->Buffer, Buffer, Length);
     86 
     87     Subtable->Length = Length;
     88     Subtable->TotalLength = Length;
     89 
     90     *RetSubtable = Subtable;
     91 }
     92 
     93 
     94 /******************************************************************************
     95  *
     96  * FUNCTION:    DtInsertSubtable
     97  *
     98  * PARAMETERS:  ParentTable         - The Parent of the new subtable
     99  *              Subtable            - The new subtable to insert
    100  *
    101  * RETURN:      None
    102  *
    103  * DESCRIPTION: Insert the new subtable to the parent table
    104  *
    105  *****************************************************************************/
    106 
    107 void
    108 DtInsertSubtable (
    109     DT_SUBTABLE             *ParentTable,
    110     DT_SUBTABLE             *Subtable)
    111 {
    112     DT_SUBTABLE             *ChildTable;
    113 
    114 
    115     Subtable->Peer = NULL;
    116     Subtable->Parent = ParentTable;
    117     Subtable->Depth = ParentTable->Depth + 1;
    118 
    119     /* Link the new entry into the child list */
    120 
    121     if (!ParentTable->Child)
    122     {
    123         ParentTable->Child = Subtable;
    124     }
    125     else
    126     {
    127         /* Walk to the end of the child list */
    128 
    129         ChildTable = ParentTable->Child;
    130         while (ChildTable->Peer)
    131         {
    132             ChildTable = ChildTable->Peer;
    133         }
    134 
    135         /* Add new subtable at the end of the child list */
    136 
    137         ChildTable->Peer = Subtable;
    138     }
    139 }
    140 
    141 
    142 /******************************************************************************
    143  *
    144  * FUNCTION:    DtPushSubtable
    145  *
    146  * PARAMETERS:  Subtable            - Subtable to push
    147  *
    148  * RETURN:      None
    149  *
    150  * DESCRIPTION: Push a subtable onto a subtable stack
    151  *
    152  *****************************************************************************/
    153 
    154 void
    155 DtPushSubtable (
    156     DT_SUBTABLE             *Subtable)
    157 {
    158 
    159     Subtable->StackTop = Gbl_SubtableStack;
    160     Gbl_SubtableStack = Subtable;
    161 }
    162 
    163 
    164 /******************************************************************************
    165  *
    166  * FUNCTION:    DtPopSubtable
    167  *
    168  * PARAMETERS:  None
    169  *
    170  * RETURN:      None
    171  *
    172  * DESCRIPTION: Pop a subtable from a subtable stack. Uses global SubtableStack
    173  *
    174  *****************************************************************************/
    175 
    176 void
    177 DtPopSubtable (
    178     void)
    179 {
    180     DT_SUBTABLE             *Subtable;
    181 
    182 
    183     Subtable = Gbl_SubtableStack;
    184 
    185     if (Subtable)
    186     {
    187         Gbl_SubtableStack = Subtable->StackTop;
    188     }
    189 }
    190 
    191 
    192 /******************************************************************************
    193  *
    194  * FUNCTION:    DtPeekSubtable
    195  *
    196  * PARAMETERS:  None
    197  *
    198  * RETURN:      The subtable on top of stack
    199  *
    200  * DESCRIPTION: Get the subtable on top of stack
    201  *
    202  *****************************************************************************/
    203 
    204 DT_SUBTABLE *
    205 DtPeekSubtable (
    206     void)
    207 {
    208 
    209     return (Gbl_SubtableStack);
    210 }
    211 
    212 
    213 /******************************************************************************
    214  *
    215  * FUNCTION:    DtGetNextSubtable
    216  *
    217  * PARAMETERS:  ParentTable         - Parent table whose children we are
    218  *                                    getting
    219  *              ChildTable          - Previous child that was found.
    220  *                                    The NEXT child will be returned
    221  *
    222  * RETURN:      Pointer to the NEXT child or NULL if none is found.
    223  *
    224  * DESCRIPTION: Return the next peer subtable within the tree.
    225  *
    226  *****************************************************************************/
    227 
    228 DT_SUBTABLE *
    229 DtGetNextSubtable (
    230     DT_SUBTABLE             *ParentTable,
    231     DT_SUBTABLE             *ChildTable)
    232 {
    233     ACPI_FUNCTION_ENTRY ();
    234 
    235 
    236     if (!ChildTable)
    237     {
    238         /* It's really the parent's _scope_ that we want */
    239 
    240         return (ParentTable->Child);
    241     }
    242 
    243     /* Otherwise just return the next peer (NULL if at end-of-list) */
    244 
    245     return (ChildTable->Peer);
    246 }
    247 
    248 
    249 /******************************************************************************
    250  *
    251  * FUNCTION:    DtGetParentSubtable
    252  *
    253  * PARAMETERS:  Subtable            - Current subtable
    254  *
    255  * RETURN:      Parent of the given subtable
    256  *
    257  * DESCRIPTION: Get the parent of the given subtable in the tree
    258  *
    259  *****************************************************************************/
    260 
    261 DT_SUBTABLE *
    262 DtGetParentSubtable (
    263     DT_SUBTABLE             *Subtable)
    264 {
    265 
    266     if (!Subtable)
    267     {
    268         return (NULL);
    269     }
    270 
    271     return (Subtable->Parent);
    272 }
    273 
    274 
    275 /******************************************************************************
    276  *
    277  * FUNCTION:    DtGetSubtableLength
    278  *
    279  * PARAMETERS:  Field               - Current field list pointer
    280  *              Info                - Data table info
    281  *
    282  * RETURN:      Subtable length
    283  *
    284  * DESCRIPTION: Get length of bytes needed to compile the subtable
    285  *
    286  *****************************************************************************/
    287 
    288 UINT32
    289 DtGetSubtableLength (
    290     DT_FIELD                *Field,
    291     ACPI_DMTABLE_INFO       *Info)
    292 {
    293     UINT32                  ByteLength = 0;
    294     UINT8                   Step;
    295     UINT8                   i;
    296 
    297 
    298     /* Walk entire Info table; Null name terminates */
    299 
    300     for (; Info->Name; Info++)
    301     {
    302         if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
    303         {
    304             continue;
    305         }
    306 
    307         if (!Field)
    308         {
    309             goto Error;
    310         }
    311 
    312         ByteLength += DtGetFieldLength (Field, Info);
    313 
    314         switch (Info->Opcode)
    315         {
    316         case ACPI_DMT_GAS:
    317 
    318             Step = 5;
    319             break;
    320 
    321         case ACPI_DMT_HESTNTFY:
    322 
    323             Step = 9;
    324             break;
    325 
    326         default:
    327 
    328             Step = 1;
    329             break;
    330         }
    331 
    332         for (i = 0; i < Step; i++)
    333         {
    334             if (!Field)
    335             {
    336                 goto Error;
    337             }
    338 
    339             Field = Field->Next;
    340         }
    341     }
    342 
    343     return (ByteLength);
    344 
    345 Error:
    346     if (!Field)
    347     {
    348         snprintf (MsgBuffer, sizeof(MsgBuffer), "Found NULL field - Field name \"%s\" needed",
    349             Info->Name);
    350         DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    351     }
    352 
    353     return (ASL_EOF);
    354 }
    355 
    356 
    357 /******************************************************************************
    358  *
    359  * FUNCTION:    DtSetSubtableLength
    360  *
    361  * PARAMETERS:  Subtable            - Subtable
    362  *
    363  * RETURN:      None
    364  *
    365  * DESCRIPTION: Set length of the subtable into its length field
    366  *
    367  *****************************************************************************/
    368 
    369 void
    370 DtSetSubtableLength (
    371     DT_SUBTABLE             *Subtable)
    372 {
    373 
    374     if (!Subtable->LengthField)
    375     {
    376         return;
    377     }
    378 
    379     ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
    380         Subtable->SizeOfLengthField);
    381 }
    382