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