1 /******************************************************************************
   2  *
   3  * Module Name: exnames - interpreter/scanner name load/execute
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 }