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