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