Home | History | Annotate | Line # | Download | only in executer
exnames.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: exnames - interpreter/scanner name load/execute
      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 __EXNAMES_C__
     45 
     46 #include "acpi.h"
     47 #include "accommon.h"
     48 #include "acinterp.h"
     49 #include "amlcode.h"
     50 
     51 #define _COMPONENT          ACPI_EXECUTER
     52         ACPI_MODULE_NAME    ("exnames")
     53 
     54 /* Local prototypes */
     55 
     56 static char *
     57 AcpiExAllocateNameString (
     58     UINT32                  PrefixCount,
     59     UINT32                  NumNameSegs);
     60 
     61 static ACPI_STATUS
     62 AcpiExNameSegment (
     63     UINT8                   **InAmlAddress,
     64     char                    *NameString);
     65 
     66 
     67 /*******************************************************************************
     68  *
     69  * FUNCTION:    AcpiExAllocateNameString
     70  *
     71  * PARAMETERS:  PrefixCount         - Count of parent levels. Special cases:
     72  *                                    (-1)==root,  0==none
     73  *              NumNameSegs         - count of 4-character name segments
     74  *
     75  * RETURN:      A pointer to the allocated string segment. This segment must
     76  *              be deleted by the caller.
     77  *
     78  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
     79  *              string is long enough, and set up prefix if any.
     80  *
     81  ******************************************************************************/
     82 
     83 static char *
     84 AcpiExAllocateNameString (
     85     UINT32                  PrefixCount,
     86     UINT32                  NumNameSegs)
     87 {
     88     char                    *TempPtr;
     89     char                    *NameString;
     90     UINT32                   SizeNeeded;
     91 
     92     ACPI_FUNCTION_TRACE (ExAllocateNameString);
     93 
     94 
     95     /*
     96      * Allow room for all \ and ^ prefixes, all segments and a MultiNamePrefix.
     97      * Also, one byte for the null terminator.
     98      * This may actually be somewhat longer than needed.
     99      */
    100     if (PrefixCount == ACPI_UINT32_MAX)
    101     {
    102         /* Special case for root */
    103 
    104         SizeNeeded = 1 + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
    105     }
    106     else
    107     {
    108         SizeNeeded = PrefixCount + (ACPI_NAME_SIZE * NumNameSegs) + 2 + 1;
    109     }
    110 
    111     /*
    112      * Allocate a buffer for the name.
    113      * This buffer must be deleted by the caller!
    114      */
    115     NameString = ACPI_ALLOCATE (SizeNeeded);
    116     if (!NameString)
    117     {
    118         ACPI_ERROR ((AE_INFO,
    119             "Could not allocate size %u", SizeNeeded));
    120         return_PTR (NULL);
    121     }
    122 
    123     TempPtr = NameString;
    124 
    125     /* Set up Root or Parent prefixes if needed */
    126 
    127     if (PrefixCount == ACPI_UINT32_MAX)
    128     {
    129         *TempPtr++ = AML_ROOT_PREFIX;
    130     }
    131     else
    132     {
    133         while (PrefixCount--)
    134         {
    135             *TempPtr++ = AML_PARENT_PREFIX;
    136         }
    137     }
    138 
    139 
    140     /* Set up Dual or Multi prefixes if needed */
    141 
    142     if (NumNameSegs > 2)
    143     {
    144         /* Set up multi prefixes   */
    145 
    146         *TempPtr++ = AML_MULTI_NAME_PREFIX_OP;
    147         *TempPtr++ = (char) NumNameSegs;
    148     }
    149     else if (2 == NumNameSegs)
    150     {
    151         /* Set up dual prefixes */
    152 
    153         *TempPtr++ = AML_DUAL_NAME_PREFIX;
    154     }
    155 
    156     /*
    157      * Terminate string following prefixes. AcpiExNameSegment() will
    158      * append the segment(s)
    159      */
    160     *TempPtr = 0;
    161 
    162     return_PTR (NameString);
    163 }
    164 
    165 /*******************************************************************************
    166  *
    167  * FUNCTION:    AcpiExNameSegment
    168  *
    169  * PARAMETERS:  InAmlAddress    - Pointer to the name in the AML code
    170  *              NameString      - Where to return the name. The name is appended
    171  *                                to any existing string to form a namepath
    172  *
    173  * RETURN:      Status
    174  *
    175  * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
    176  *
    177  ******************************************************************************/
    178 
    179 static ACPI_STATUS
    180 AcpiExNameSegment (
    181     UINT8                   **InAmlAddress,
    182     char                    *NameString)
    183 {
    184     char                    *AmlAddress = (void *) *InAmlAddress;
    185     ACPI_STATUS             Status = AE_OK;
    186     UINT32                  Index;
    187     char                    CharBuf[5];
    188 
    189 
    190     ACPI_FUNCTION_TRACE (ExNameSegment);
    191 
    192 
    193     /*
    194      * If first character is a digit, then we know that we aren't looking at a
    195      * valid name segment
    196      */
    197     CharBuf[0] = *AmlAddress;
    198 
    199     if ('0' <= CharBuf[0] && CharBuf[0] <= '9')
    200     {
    201         ACPI_ERROR ((AE_INFO, "Invalid leading digit: %c", CharBuf[0]));
    202         return_ACPI_STATUS (AE_CTRL_PENDING);
    203     }
    204 
    205     ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
    206 
    207     for (Index = 0;
    208         (Index < ACPI_NAME_SIZE) && (AcpiUtValidAcpiChar (*AmlAddress, 0));
    209         Index++)
    210     {
    211         CharBuf[Index] = *AmlAddress++;
    212         ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", CharBuf[Index]));
    213     }
    214 
    215 
    216     /* Valid name segment  */
    217 
    218     if (Index == 4)
    219     {
    220         /* Found 4 valid characters */
    221 
    222         CharBuf[4] = '\0';
    223 
    224         if (NameString)
    225         {
    226             ACPI_STRCAT (NameString, CharBuf);
    227             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
    228                 "Appended to - %s\n", NameString));
    229         }
    230         else
    231         {
    232             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
    233                 "No Name string - %s\n", CharBuf));
    234         }
    235     }
    236     else if (Index == 0)
    237     {
    238         /*
    239          * First character was not a valid name character,
    240          * so we are looking at something other than a name.
    241          */
    242         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    243             "Leading character is not alpha: %02Xh (not a name)\n",
    244             CharBuf[0]));
    245         Status = AE_CTRL_PENDING;
    246     }
    247     else
    248     {
    249         /*
    250          * Segment started with one or more valid characters, but fewer than
    251          * the required 4
    252          */
    253         Status = AE_AML_BAD_NAME;
    254         ACPI_ERROR ((AE_INFO,
    255             "Bad character 0x%02x in name, at %p",
    256             *AmlAddress, AmlAddress));
    257     }
    258 
    259     *InAmlAddress = ACPI_CAST_PTR (UINT8, AmlAddress);
    260     return_ACPI_STATUS (Status);
    261 }
    262 
    263 
    264 /*******************************************************************************
    265  *
    266  * FUNCTION:    AcpiExGetNameString
    267  *
    268  * PARAMETERS:  DataType            - Object type to be associated with this
    269  *                                    name
    270  *              InAmlAddress        - Pointer to the namestring in the AML code
    271  *              OutNameString       - Where the namestring is returned
    272  *              OutNameLength       - Length of the returned string
    273  *
    274  * RETURN:      Status, namestring and length
    275  *
    276  * DESCRIPTION: Extract a full namepath from the AML byte stream,
    277  *              including any prefixes.
    278  *
    279  ******************************************************************************/
    280 
    281 ACPI_STATUS
    282 AcpiExGetNameString (
    283     ACPI_OBJECT_TYPE        DataType,
    284     UINT8                   *InAmlAddress,
    285     char                    **OutNameString,
    286     UINT32                  *OutNameLength)
    287 {
    288     ACPI_STATUS             Status = AE_OK;
    289     UINT8                   *AmlAddress = InAmlAddress;
    290     char                    *NameString = NULL;
    291     UINT32                  NumSegments;
    292     UINT32                  PrefixCount = 0;
    293     BOOLEAN                 HasPrefix = FALSE;
    294 
    295 
    296     ACPI_FUNCTION_TRACE_PTR (ExGetNameString, AmlAddress);
    297 
    298 
    299     if (ACPI_TYPE_LOCAL_REGION_FIELD == DataType   ||
    300         ACPI_TYPE_LOCAL_BANK_FIELD == DataType     ||
    301         ACPI_TYPE_LOCAL_INDEX_FIELD == DataType)
    302     {
    303         /* Disallow prefixes for types associated with FieldUnit names */
    304 
    305         NameString = AcpiExAllocateNameString (0, 1);
    306         if (!NameString)
    307         {
    308             Status = AE_NO_MEMORY;
    309         }
    310         else
    311         {
    312             Status = AcpiExNameSegment (&AmlAddress, NameString);
    313         }
    314     }
    315     else
    316     {
    317         /*
    318          * DataType is not a field name.
    319          * Examine first character of name for root or parent prefix operators
    320          */
    321         switch (*AmlAddress)
    322         {
    323         case AML_ROOT_PREFIX:
    324 
    325             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "RootPrefix(\\) at %p\n",
    326                 AmlAddress));
    327 
    328             /*
    329              * Remember that we have a RootPrefix --
    330              * see comment in AcpiExAllocateNameString()
    331              */
    332             AmlAddress++;
    333             PrefixCount = ACPI_UINT32_MAX;
    334             HasPrefix = TRUE;
    335             break;
    336 
    337         case AML_PARENT_PREFIX:
    338 
    339             /* Increment past possibly multiple parent prefixes */
    340 
    341             do
    342             {
    343                 ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "ParentPrefix (^) at %p\n",
    344                     AmlAddress));
    345 
    346                 AmlAddress++;
    347                 PrefixCount++;
    348 
    349             } while (*AmlAddress == AML_PARENT_PREFIX);
    350 
    351             HasPrefix = TRUE;
    352             break;
    353 
    354         default:
    355 
    356             /* Not a prefix character */
    357 
    358             break;
    359         }
    360 
    361         /* Examine first character of name for name segment prefix operator */
    362 
    363         switch (*AmlAddress)
    364         {
    365         case AML_DUAL_NAME_PREFIX:
    366 
    367             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "DualNamePrefix at %p\n",
    368                 AmlAddress));
    369 
    370             AmlAddress++;
    371             NameString = AcpiExAllocateNameString (PrefixCount, 2);
    372             if (!NameString)
    373             {
    374                 Status = AE_NO_MEMORY;
    375                 break;
    376             }
    377 
    378             /* Indicate that we processed a prefix */
    379 
    380             HasPrefix = TRUE;
    381 
    382             Status = AcpiExNameSegment (&AmlAddress, NameString);
    383             if (ACPI_SUCCESS (Status))
    384             {
    385                 Status = AcpiExNameSegment (&AmlAddress, NameString);
    386             }
    387             break;
    388 
    389         case AML_MULTI_NAME_PREFIX_OP:
    390 
    391             ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "MultiNamePrefix at %p\n",
    392                 AmlAddress));
    393 
    394             /* Fetch count of segments remaining in name path */
    395 
    396             AmlAddress++;
    397             NumSegments = *AmlAddress;
    398 
    399             NameString = AcpiExAllocateNameString (PrefixCount, NumSegments);
    400             if (!NameString)
    401             {
    402                 Status = AE_NO_MEMORY;
    403                 break;
    404             }
    405 
    406             /* Indicate that we processed a prefix */
    407 
    408             AmlAddress++;
    409             HasPrefix = TRUE;
    410 
    411             while (NumSegments &&
    412                     (Status = AcpiExNameSegment (&AmlAddress, NameString)) ==
    413                         AE_OK)
    414             {
    415                 NumSegments--;
    416             }
    417 
    418             break;
    419 
    420         case 0:
    421 
    422             /* NullName valid as of 8-12-98 ASL/AML Grammar Update */
    423 
    424             if (PrefixCount == ACPI_UINT32_MAX)
    425             {
    426                 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    427                     "NameSeg is \"\\\" followed by NULL\n"));
    428             }
    429 
    430             /* Consume the NULL byte */
    431 
    432             AmlAddress++;
    433             NameString = AcpiExAllocateNameString (PrefixCount, 0);
    434             if (!NameString)
    435             {
    436                 Status = AE_NO_MEMORY;
    437                 break;
    438             }
    439 
    440             break;
    441 
    442         default:
    443 
    444             /* Name segment string */
    445 
    446             NameString = AcpiExAllocateNameString (PrefixCount, 1);
    447             if (!NameString)
    448             {
    449                 Status = AE_NO_MEMORY;
    450                 break;
    451             }
    452 
    453             Status = AcpiExNameSegment (&AmlAddress, NameString);
    454             break;
    455         }
    456     }
    457 
    458     if (AE_CTRL_PENDING == Status && HasPrefix)
    459     {
    460         /* Ran out of segments after processing a prefix */
    461 
    462         ACPI_ERROR ((AE_INFO,
    463             "Malformed Name at %p", NameString));
    464         Status = AE_AML_BAD_NAME;
    465     }
    466 
    467     if (ACPI_FAILURE (Status))
    468     {
    469         if (NameString)
    470         {
    471             ACPI_FREE (NameString);
    472         }
    473         return_ACPI_STATUS (Status);
    474     }
    475 
    476     *OutNameString = NameString;
    477     *OutNameLength = (UINT32) (AmlAddress - InAmlAddress);
    478 
    479     return_ACPI_STATUS (Status);
    480 }
    481