Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: exnames - interpreter/scanner name load/execute
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, 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
  50. ACPI_MODULE_NAME("exnames")
  51.  
  52. /* Local prototypes */
  53. static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs);
  54.  
  55. static 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.  
  73. static 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.  
  157. static 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.                         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.  
  243. acpi_status
  244. acpi_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.