Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: nsconvert - Object conversions for objects returned by
  4.  *                          predefined methods
  5.  *
  6.  *****************************************************************************/
  7.  
  8. /*
  9.  * Copyright (C) 2000 - 2015, 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. #include <acpi/acpi.h>
  46. #include "accommon.h"
  47. #include "acnamesp.h"
  48. #include "acinterp.h"
  49. #include "acpredef.h"
  50. #include "amlresrc.h"
  51.  
  52. #define _COMPONENT          ACPI_NAMESPACE
  53. ACPI_MODULE_NAME("nsconvert")
  54.  
  55. /*******************************************************************************
  56.  *
  57.  * FUNCTION:    acpi_ns_convert_to_integer
  58.  *
  59.  * PARAMETERS:  original_object     - Object to be converted
  60.  *              return_object       - Where the new converted object is returned
  61.  *
  62.  * RETURN:      Status. AE_OK if conversion was successful.
  63.  *
  64.  * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
  65.  *
  66.  ******************************************************************************/
  67. acpi_status
  68. acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
  69.                            union acpi_operand_object **return_object)
  70. {
  71.         union acpi_operand_object *new_object;
  72.         acpi_status status;
  73.         u64 value = 0;
  74.         u32 i;
  75.  
  76.         switch (original_object->common.type) {
  77.         case ACPI_TYPE_STRING:
  78.  
  79.                 /* String-to-Integer conversion */
  80.  
  81.                 status = acpi_ut_strtoul64(original_object->string.pointer,
  82.                                            ACPI_ANY_BASE, &value);
  83.                 if (ACPI_FAILURE(status)) {
  84.                         return (status);
  85.                 }
  86.                 break;
  87.  
  88.         case ACPI_TYPE_BUFFER:
  89.  
  90.                 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
  91.  
  92.                 if (original_object->buffer.length > 8) {
  93.                         return (AE_AML_OPERAND_TYPE);
  94.                 }
  95.  
  96.                 /* Extract each buffer byte to create the integer */
  97.  
  98.                 for (i = 0; i < original_object->buffer.length; i++) {
  99.                         value |=
  100.                             ((u64)original_object->buffer.
  101.                              pointer[i] << (i * 8));
  102.                 }
  103.                 break;
  104.  
  105.         default:
  106.  
  107.                 return (AE_AML_OPERAND_TYPE);
  108.         }
  109.  
  110.         new_object = acpi_ut_create_integer_object(value);
  111.         if (!new_object) {
  112.                 return (AE_NO_MEMORY);
  113.         }
  114.  
  115.         *return_object = new_object;
  116.         return (AE_OK);
  117. }
  118.  
  119. /*******************************************************************************
  120.  *
  121.  * FUNCTION:    acpi_ns_convert_to_string
  122.  *
  123.  * PARAMETERS:  original_object     - Object to be converted
  124.  *              return_object       - Where the new converted object is returned
  125.  *
  126.  * RETURN:      Status. AE_OK if conversion was successful.
  127.  *
  128.  * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
  129.  *
  130.  ******************************************************************************/
  131.  
  132. acpi_status
  133. acpi_ns_convert_to_string(union acpi_operand_object *original_object,
  134.                           union acpi_operand_object **return_object)
  135. {
  136.         union acpi_operand_object *new_object;
  137.         acpi_size length;
  138.         acpi_status status;
  139.  
  140.         switch (original_object->common.type) {
  141.         case ACPI_TYPE_INTEGER:
  142.                 /*
  143.                  * Integer-to-String conversion. Commonly, convert
  144.                  * an integer of value 0 to a NULL string. The last element of
  145.                  * _BIF and _BIX packages occasionally need this fix.
  146.                  */
  147.                 if (original_object->integer.value == 0) {
  148.  
  149.                         /* Allocate a new NULL string object */
  150.  
  151.                         new_object = acpi_ut_create_string_object(0);
  152.                         if (!new_object) {
  153.                                 return (AE_NO_MEMORY);
  154.                         }
  155.                 } else {
  156.                         status =
  157.                             acpi_ex_convert_to_string(original_object,
  158.                                                       &new_object,
  159.                                                       ACPI_IMPLICIT_CONVERT_HEX);
  160.                         if (ACPI_FAILURE(status)) {
  161.                                 return (status);
  162.                         }
  163.                 }
  164.                 break;
  165.  
  166.         case ACPI_TYPE_BUFFER:
  167.                 /*
  168.                  * Buffer-to-String conversion. Use a to_string
  169.                  * conversion, no transform performed on the buffer data. The best
  170.                  * example of this is the _BIF method, where the string data from
  171.                  * the battery is often (incorrectly) returned as buffer object(s).
  172.                  */
  173.                 length = 0;
  174.                 while ((length < original_object->buffer.length) &&
  175.                        (original_object->buffer.pointer[length])) {
  176.                         length++;
  177.                 }
  178.  
  179.                 /* Allocate a new string object */
  180.  
  181.                 new_object = acpi_ut_create_string_object(length);
  182.                 if (!new_object) {
  183.                         return (AE_NO_MEMORY);
  184.                 }
  185.  
  186.                 /*
  187.                  * Copy the raw buffer data with no transform. String is already NULL
  188.                  * terminated at Length+1.
  189.                  */
  190.                 memcpy(new_object->string.pointer,
  191.                        original_object->buffer.pointer, length);
  192.                 break;
  193.  
  194.         default:
  195.  
  196.                 return (AE_AML_OPERAND_TYPE);
  197.         }
  198.  
  199.         *return_object = new_object;
  200.         return (AE_OK);
  201. }
  202.  
  203. /*******************************************************************************
  204.  *
  205.  * FUNCTION:    acpi_ns_convert_to_buffer
  206.  *
  207.  * PARAMETERS:  original_object     - Object to be converted
  208.  *              return_object       - Where the new converted object is returned
  209.  *
  210.  * RETURN:      Status. AE_OK if conversion was successful.
  211.  *
  212.  * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
  213.  *
  214.  ******************************************************************************/
  215.  
  216. acpi_status
  217. acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
  218.                           union acpi_operand_object **return_object)
  219. {
  220.         union acpi_operand_object *new_object;
  221.         acpi_status status;
  222.         union acpi_operand_object **elements;
  223.         u32 *dword_buffer;
  224.         u32 count;
  225.         u32 i;
  226.  
  227.         switch (original_object->common.type) {
  228.         case ACPI_TYPE_INTEGER:
  229.                 /*
  230.                  * Integer-to-Buffer conversion.
  231.                  * Convert the Integer to a packed-byte buffer. _MAT and other
  232.                  * objects need this sometimes, if a read has been performed on a
  233.                  * Field object that is less than or equal to the global integer
  234.                  * size (32 or 64 bits).
  235.                  */
  236.                 status =
  237.                     acpi_ex_convert_to_buffer(original_object, &new_object);
  238.                 if (ACPI_FAILURE(status)) {
  239.                         return (status);
  240.                 }
  241.                 break;
  242.  
  243.         case ACPI_TYPE_STRING:
  244.  
  245.                 /* String-to-Buffer conversion. Simple data copy */
  246.  
  247.                 new_object =
  248.                     acpi_ut_create_buffer_object(original_object->string.
  249.                                                  length);
  250.                 if (!new_object) {
  251.                         return (AE_NO_MEMORY);
  252.                 }
  253.  
  254.                 memcpy(new_object->buffer.pointer,
  255.                        original_object->string.pointer,
  256.                        original_object->string.length);
  257.                 break;
  258.  
  259.         case ACPI_TYPE_PACKAGE:
  260.                 /*
  261.                  * This case is often seen for predefined names that must return a
  262.                  * Buffer object with multiple DWORD integers within. For example,
  263.                  * _FDE and _GTM. The Package can be converted to a Buffer.
  264.                  */
  265.  
  266.                 /* All elements of the Package must be integers */
  267.  
  268.                 elements = original_object->package.elements;
  269.                 count = original_object->package.count;
  270.  
  271.                 for (i = 0; i < count; i++) {
  272.                         if ((!*elements) ||
  273.                             ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
  274.                                 return (AE_AML_OPERAND_TYPE);
  275.                         }
  276.                         elements++;
  277.                 }
  278.  
  279.                 /* Create the new buffer object to replace the Package */
  280.  
  281.                 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
  282.                 if (!new_object) {
  283.                         return (AE_NO_MEMORY);
  284.                 }
  285.  
  286.                 /* Copy the package elements (integers) to the buffer as DWORDs */
  287.  
  288.                 elements = original_object->package.elements;
  289.                 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
  290.  
  291.                 for (i = 0; i < count; i++) {
  292.                         *dword_buffer = (u32)(*elements)->integer.value;
  293.                         dword_buffer++;
  294.                         elements++;
  295.                 }
  296.                 break;
  297.  
  298.         default:
  299.  
  300.                 return (AE_AML_OPERAND_TYPE);
  301.         }
  302.  
  303.         *return_object = new_object;
  304.         return (AE_OK);
  305. }
  306.  
  307. /*******************************************************************************
  308.  *
  309.  * FUNCTION:    acpi_ns_convert_to_unicode
  310.  *
  311.  * PARAMETERS:  original_object     - ASCII String Object to be converted
  312.  *              return_object       - Where the new converted object is returned
  313.  *
  314.  * RETURN:      Status. AE_OK if conversion was successful.
  315.  *
  316.  * DESCRIPTION: Attempt to convert a String object to a Unicode string Buffer.
  317.  *
  318.  ******************************************************************************/
  319.  
  320. acpi_status
  321. acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
  322.                            union acpi_operand_object **return_object)
  323. {
  324.         union acpi_operand_object *new_object;
  325.         char *ascii_string;
  326.         u16 *unicode_buffer;
  327.         u32 unicode_length;
  328.         u32 i;
  329.  
  330.         if (!original_object) {
  331.                 return (AE_OK);
  332.         }
  333.  
  334.         /* If a Buffer was returned, it must be at least two bytes long */
  335.  
  336.         if (original_object->common.type == ACPI_TYPE_BUFFER) {
  337.                 if (original_object->buffer.length < 2) {
  338.                         return (AE_AML_OPERAND_VALUE);
  339.                 }
  340.  
  341.                 *return_object = NULL;
  342.                 return (AE_OK);
  343.         }
  344.  
  345.         /*
  346.          * The original object is an ASCII string. Convert this string to
  347.          * a unicode buffer.
  348.          */
  349.         ascii_string = original_object->string.pointer;
  350.         unicode_length = (original_object->string.length * 2) + 2;
  351.  
  352.         /* Create a new buffer object for the Unicode data */
  353.  
  354.         new_object = acpi_ut_create_buffer_object(unicode_length);
  355.         if (!new_object) {
  356.                 return (AE_NO_MEMORY);
  357.         }
  358.  
  359.         unicode_buffer = ACPI_CAST_PTR(u16, new_object->buffer.pointer);
  360.  
  361.         /* Convert ASCII to Unicode */
  362.  
  363.         for (i = 0; i < original_object->string.length; i++) {
  364.                 unicode_buffer[i] = (u16)ascii_string[i];
  365.         }
  366.  
  367.         *return_object = new_object;
  368.         return (AE_OK);
  369. }
  370.  
  371. /*******************************************************************************
  372.  *
  373.  * FUNCTION:    acpi_ns_convert_to_resource
  374.  *
  375.  * PARAMETERS:  original_object     - Object to be converted
  376.  *              return_object       - Where the new converted object is returned
  377.  *
  378.  * RETURN:      Status. AE_OK if conversion was successful
  379.  *
  380.  * DESCRIPTION: Attempt to convert a Integer object to a resource_template
  381.  *              Buffer.
  382.  *
  383.  ******************************************************************************/
  384.  
  385. acpi_status
  386. acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
  387.                             union acpi_operand_object **return_object)
  388. {
  389.         union acpi_operand_object *new_object;
  390.         u8 *buffer;
  391.  
  392.         /*
  393.          * We can fix the following cases for an expected resource template:
  394.          * 1. No return value (interpreter slack mode is disabled)
  395.          * 2. A "Return (Zero)" statement
  396.          * 3. A "Return empty buffer" statement
  397.          *
  398.          * We will return a buffer containing a single end_tag
  399.          * resource descriptor.
  400.          */
  401.         if (original_object) {
  402.                 switch (original_object->common.type) {
  403.                 case ACPI_TYPE_INTEGER:
  404.  
  405.                         /* We can only repair an Integer==0 */
  406.  
  407.                         if (original_object->integer.value) {
  408.                                 return (AE_AML_OPERAND_TYPE);
  409.                         }
  410.                         break;
  411.  
  412.                 case ACPI_TYPE_BUFFER:
  413.  
  414.                         if (original_object->buffer.length) {
  415.  
  416.                                 /* Additional checks can be added in the future */
  417.  
  418.                                 *return_object = NULL;
  419.                                 return (AE_OK);
  420.                         }
  421.                         break;
  422.  
  423.                 case ACPI_TYPE_STRING:
  424.                 default:
  425.  
  426.                         return (AE_AML_OPERAND_TYPE);
  427.                 }
  428.         }
  429.  
  430.         /* Create the new buffer object for the resource descriptor */
  431.  
  432.         new_object = acpi_ut_create_buffer_object(2);
  433.         if (!new_object) {
  434.                 return (AE_NO_MEMORY);
  435.         }
  436.  
  437.         buffer = ACPI_CAST_PTR(u8, new_object->buffer.pointer);
  438.  
  439.         /* Initialize the Buffer with a single end_tag descriptor */
  440.  
  441.         buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE);
  442.         buffer[1] = 0x00;
  443.  
  444.         *return_object = new_object;
  445.         return (AE_OK);
  446. }
  447.