Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: exnames - interpreter/scanner name load/execute
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acinterp.h"
0013 #include "amlcode.h"
0014 
0015 #define _COMPONENT          ACPI_EXECUTER
0016 ACPI_MODULE_NAME("exnames")
0017 
0018 /* Local prototypes */
0019 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
0020 
0021 static acpi_status acpi_ex_name_segment(u8 **in_aml_address, char *name_string);
0022 
0023 /*******************************************************************************
0024  *
0025  * FUNCTION:    acpi_ex_allocate_name_string
0026  *
0027  * PARAMETERS:  prefix_count        - Count of parent levels. Special cases:
0028  *                                    (-1)==root,  0==none
0029  *              num_name_segs       - count of 4-character name segments
0030  *
0031  * RETURN:      A pointer to the allocated string segment. This segment must
0032  *              be deleted by the caller.
0033  *
0034  * DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
0035  *              string is long enough, and set up prefix if any.
0036  *
0037  ******************************************************************************/
0038 
0039 static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
0040 {
0041     char *temp_ptr;
0042     char *name_string;
0043     u32 size_needed;
0044 
0045     ACPI_FUNCTION_TRACE(ex_allocate_name_string);
0046 
0047     /*
0048      * Allow room for all \ and ^ prefixes, all segments and a multi_name_prefix.
0049      * Also, one byte for the null terminator.
0050      * This may actually be somewhat longer than needed.
0051      */
0052     if (prefix_count == ACPI_UINT32_MAX) {
0053 
0054         /* Special case for root */
0055 
0056         size_needed = 1 + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
0057     } else {
0058         size_needed =
0059             prefix_count + (ACPI_NAMESEG_SIZE * num_name_segs) + 2 + 1;
0060     }
0061 
0062     /*
0063      * Allocate a buffer for the name.
0064      * This buffer must be deleted by the caller!
0065      */
0066     name_string = ACPI_ALLOCATE(size_needed);
0067     if (!name_string) {
0068         ACPI_ERROR((AE_INFO,
0069                 "Could not allocate size %u", size_needed));
0070         return_PTR(NULL);
0071     }
0072 
0073     temp_ptr = name_string;
0074 
0075     /* Set up Root or Parent prefixes if needed */
0076 
0077     if (prefix_count == ACPI_UINT32_MAX) {
0078         *temp_ptr++ = AML_ROOT_PREFIX;
0079     } else {
0080         while (prefix_count--) {
0081             *temp_ptr++ = AML_PARENT_PREFIX;
0082         }
0083     }
0084 
0085     /* Set up Dual or Multi prefixes if needed */
0086 
0087     if (num_name_segs > 2) {
0088 
0089         /* Set up multi prefixes   */
0090 
0091         *temp_ptr++ = AML_MULTI_NAME_PREFIX;
0092         *temp_ptr++ = (char)num_name_segs;
0093     } else if (2 == num_name_segs) {
0094 
0095         /* Set up dual prefixes */
0096 
0097         *temp_ptr++ = AML_DUAL_NAME_PREFIX;
0098     }
0099 
0100     /*
0101      * Terminate string following prefixes. acpi_ex_name_segment() will
0102      * append the segment(s)
0103      */
0104     *temp_ptr = 0;
0105 
0106     return_PTR(name_string);
0107 }
0108 
0109 /*******************************************************************************
0110  *
0111  * FUNCTION:    acpi_ex_name_segment
0112  *
0113  * PARAMETERS:  in_aml_address  - Pointer to the name in the AML code
0114  *              name_string     - Where to return the name. The name is appended
0115  *                                to any existing string to form a namepath
0116  *
0117  * RETURN:      Status
0118  *
0119  * DESCRIPTION: Extract an ACPI name (4 bytes) from the AML byte stream
0120  *
0121  ******************************************************************************/
0122 
0123 static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string)
0124 {
0125     char *aml_address = (void *)*in_aml_address;
0126     acpi_status status = AE_OK;
0127     u32 index;
0128     char char_buf[5];
0129 
0130     ACPI_FUNCTION_TRACE(ex_name_segment);
0131 
0132     /*
0133      * If first character is a digit, then we know that we aren't looking
0134      * at a valid name segment
0135      */
0136     char_buf[0] = *aml_address;
0137 
0138     if ('0' <= char_buf[0] && char_buf[0] <= '9') {
0139         ACPI_ERROR((AE_INFO, "Invalid leading digit: %c", char_buf[0]));
0140         return_ACPI_STATUS(AE_CTRL_PENDING);
0141     }
0142 
0143     for (index = 0;
0144          (index < ACPI_NAMESEG_SIZE)
0145          && (acpi_ut_valid_name_char(*aml_address, 0)); index++) {
0146         char_buf[index] = *aml_address++;
0147     }
0148 
0149     /* Valid name segment  */
0150 
0151     if (index == 4) {
0152 
0153         /* Found 4 valid characters */
0154 
0155         char_buf[4] = '\0';
0156 
0157         if (name_string) {
0158             ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
0159                       "Appending NameSeg %s\n", char_buf));
0160             strcat(name_string, char_buf);
0161         } else {
0162             ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
0163                       "No Name string - %s\n", char_buf));
0164         }
0165     } else if (index == 0) {
0166         /*
0167          * First character was not a valid name character,
0168          * so we are looking at something other than a name.
0169          */
0170         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
0171                   "Leading character is not alpha: %02Xh (not a name)\n",
0172                   char_buf[0]));
0173         status = AE_CTRL_PENDING;
0174     } else {
0175         /*
0176          * Segment started with one or more valid characters, but fewer than
0177          * the required 4
0178          */
0179         status = AE_AML_BAD_NAME;
0180         ACPI_ERROR((AE_INFO,
0181                 "Bad character 0x%02x in name, at %p",
0182                 *aml_address, aml_address));
0183     }
0184 
0185     *in_aml_address = ACPI_CAST_PTR(u8, aml_address);
0186     return_ACPI_STATUS(status);
0187 }
0188 
0189 /*******************************************************************************
0190  *
0191  * FUNCTION:    acpi_ex_get_name_string
0192  *
0193  * PARAMETERS:  data_type           - Object type to be associated with this
0194  *                                    name
0195  *              in_aml_address      - Pointer to the namestring in the AML code
0196  *              out_name_string     - Where the namestring is returned
0197  *              out_name_length     - Length of the returned string
0198  *
0199  * RETURN:      Status, namestring and length
0200  *
0201  * DESCRIPTION: Extract a full namepath from the AML byte stream,
0202  *              including any prefixes.
0203  *
0204  ******************************************************************************/
0205 
0206 acpi_status
0207 acpi_ex_get_name_string(acpi_object_type data_type,
0208             u8 * in_aml_address,
0209             char **out_name_string, u32 * out_name_length)
0210 {
0211     acpi_status status = AE_OK;
0212     u8 *aml_address = in_aml_address;
0213     char *name_string = NULL;
0214     u32 num_segments;
0215     u32 prefix_count = 0;
0216     u8 has_prefix = FALSE;
0217 
0218     ACPI_FUNCTION_TRACE_PTR(ex_get_name_string, aml_address);
0219 
0220     if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
0221         ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
0222         ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
0223 
0224         /* Disallow prefixes for types associated with field_unit names */
0225 
0226         name_string = acpi_ex_allocate_name_string(0, 1);
0227         if (!name_string) {
0228             status = AE_NO_MEMORY;
0229         } else {
0230             status =
0231                 acpi_ex_name_segment(&aml_address, name_string);
0232         }
0233     } else {
0234         /*
0235          * data_type is not a field name.
0236          * Examine first character of name for root or parent prefix operators
0237          */
0238         switch (*aml_address) {
0239         case AML_ROOT_PREFIX:
0240 
0241             ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0242                       "RootPrefix(\\) at %p\n",
0243                       aml_address));
0244 
0245             /*
0246              * Remember that we have a root_prefix --
0247              * see comment in acpi_ex_allocate_name_string()
0248              */
0249             aml_address++;
0250             prefix_count = ACPI_UINT32_MAX;
0251             has_prefix = TRUE;
0252             break;
0253 
0254         case AML_PARENT_PREFIX:
0255 
0256             /* Increment past possibly multiple parent prefixes */
0257 
0258             do {
0259                 ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0260                           "ParentPrefix (^) at %p\n",
0261                           aml_address));
0262 
0263                 aml_address++;
0264                 prefix_count++;
0265 
0266             } while (*aml_address == AML_PARENT_PREFIX);
0267 
0268             has_prefix = TRUE;
0269             break;
0270 
0271         default:
0272 
0273             /* Not a prefix character */
0274 
0275             break;
0276         }
0277 
0278         /* Examine first character of name for name segment prefix operator */
0279 
0280         switch (*aml_address) {
0281         case AML_DUAL_NAME_PREFIX:
0282 
0283             ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0284                       "DualNamePrefix at %p\n",
0285                       aml_address));
0286 
0287             aml_address++;
0288             name_string =
0289                 acpi_ex_allocate_name_string(prefix_count, 2);
0290             if (!name_string) {
0291                 status = AE_NO_MEMORY;
0292                 break;
0293             }
0294 
0295             /* Indicate that we processed a prefix */
0296 
0297             has_prefix = TRUE;
0298 
0299             status =
0300                 acpi_ex_name_segment(&aml_address, name_string);
0301             if (ACPI_SUCCESS(status)) {
0302                 status =
0303                     acpi_ex_name_segment(&aml_address,
0304                              name_string);
0305             }
0306             break;
0307 
0308         case AML_MULTI_NAME_PREFIX:
0309 
0310             ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
0311                       "MultiNamePrefix at %p\n",
0312                       aml_address));
0313 
0314             /* Fetch count of segments remaining in name path */
0315 
0316             aml_address++;
0317             num_segments = *aml_address;
0318 
0319             name_string =
0320                 acpi_ex_allocate_name_string(prefix_count,
0321                              num_segments);
0322             if (!name_string) {
0323                 status = AE_NO_MEMORY;
0324                 break;
0325             }
0326 
0327             /* Indicate that we processed a prefix */
0328 
0329             aml_address++;
0330             has_prefix = TRUE;
0331 
0332             while (num_segments &&
0333                    (status =
0334                 acpi_ex_name_segment(&aml_address,
0335                              name_string)) == AE_OK) {
0336                 num_segments--;
0337             }
0338 
0339             break;
0340 
0341         case 0:
0342 
0343             /* null_name valid as of 8-12-98 ASL/AML Grammar Update */
0344 
0345             if (prefix_count == ACPI_UINT32_MAX) {
0346                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0347                           "NameSeg is \"\\\" followed by NULL\n"));
0348             }
0349 
0350             /* Consume the NULL byte */
0351 
0352             aml_address++;
0353             name_string =
0354                 acpi_ex_allocate_name_string(prefix_count, 0);
0355             if (!name_string) {
0356                 status = AE_NO_MEMORY;
0357                 break;
0358             }
0359 
0360             break;
0361 
0362         default:
0363 
0364             /* Name segment string */
0365 
0366             name_string =
0367                 acpi_ex_allocate_name_string(prefix_count, 1);
0368             if (!name_string) {
0369                 status = AE_NO_MEMORY;
0370                 break;
0371             }
0372 
0373             status =
0374                 acpi_ex_name_segment(&aml_address, name_string);
0375             break;
0376         }
0377     }
0378 
0379     if (AE_CTRL_PENDING == status && has_prefix) {
0380 
0381         /* Ran out of segments after processing a prefix */
0382 
0383         ACPI_ERROR((AE_INFO, "Malformed Name at %p", name_string));
0384         status = AE_AML_BAD_NAME;
0385     }
0386 
0387     if (ACPI_FAILURE(status)) {
0388         if (name_string) {
0389             ACPI_FREE(name_string);
0390         }
0391         return_ACPI_STATUS(status);
0392     }
0393 
0394     *out_name_string = name_string;
0395     *out_name_length = (u32) (aml_address - in_aml_address);
0396 
0397     return_ACPI_STATUS(status);
0398 }