Home | History | Annotate | Line # | Download | only in compiler
dtsubtable.c revision 1.1.1.3.12.1
      1 /******************************************************************************
      2  *
      3  * Module Name: dtsubtable.c - handling of subtables within ACPI tables
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2013, 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 
     77 
     78     Subtable = UtLocalCalloc (sizeof (DT_SUBTABLE));
     79 
     80     /* Create a new buffer for the subtable data */
     81 
     82     Subtable->Buffer = UtLocalCalloc (Length);
     83     ACPI_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         default:
    325 
    326             Step = 1;
    327             break;
    328         }
    329 
    330         for (i = 0; i < Step; i++)
    331         {
    332             if (!Field)
    333             {
    334                 goto Error;
    335             }
    336 
    337             Field = Field->Next;
    338         }
    339     }
    340 
    341     return (ByteLength);
    342 
    343 Error:
    344     if (!Field)
    345     {
    346         snprintf (MsgBuffer, sizeof(MsgBuffer), "Found NULL field - Field name \"%s\" needed",
    347             Info->Name);
    348         DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
    349     }
    350 
    351     return (ASL_EOF);
    352 }
    353 
    354 
    355 /******************************************************************************
    356  *
    357  * FUNCTION:    DtSetSubtableLength
    358  *
    359  * PARAMETERS:  Subtable            - Subtable
    360  *
    361  * RETURN:      None
    362  *
    363  * DESCRIPTION: Set length of the subtable into its length field
    364  *
    365  *****************************************************************************/
    366 
    367 void
    368 DtSetSubtableLength (
    369     DT_SUBTABLE             *Subtable)
    370 {
    371 
    372     if (!Subtable->LengthField)
    373     {
    374         return;
    375     }
    376 
    377     ACPI_MEMCPY (Subtable->LengthField, &Subtable->TotalLength,
    378         Subtable->SizeOfLengthField);
    379 }
    380