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