Subversion Repositories Kolibri OS

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Module Name: nsrepair2 - Repair for objects returned by specific
  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.  
  49. #define _COMPONENT          ACPI_NAMESPACE
  50. ACPI_MODULE_NAME("nsrepair2")
  51.  
  52. /*
  53.  * Information structure and handler for ACPI predefined names that can
  54.  * be repaired on a per-name basis.
  55.  */
  56. typedef
  57. acpi_status(*acpi_repair_function) (struct acpi_evaluate_info * info,
  58.                                     union acpi_operand_object
  59.                                     **return_object_ptr);
  60.  
  61. typedef struct acpi_repair_info {
  62.         char name[ACPI_NAME_SIZE];
  63.         acpi_repair_function repair_function;
  64.  
  65. } acpi_repair_info;
  66.  
  67. /* Local prototypes */
  68.  
  69. static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
  70.                                                                    acpi_namespace_node
  71.                                                                    *node);
  72.  
  73. static acpi_status
  74. acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
  75.                    union acpi_operand_object **return_object_ptr);
  76.  
  77. static acpi_status
  78. acpi_ns_repair_CID(struct acpi_evaluate_info *info,
  79.                    union acpi_operand_object **return_object_ptr);
  80.  
  81. static acpi_status
  82. acpi_ns_repair_CST(struct acpi_evaluate_info *info,
  83.                    union acpi_operand_object **return_object_ptr);
  84.  
  85. static acpi_status
  86. acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
  87.                    union acpi_operand_object **return_object_ptr);
  88.  
  89. static acpi_status
  90. acpi_ns_repair_HID(struct acpi_evaluate_info *info,
  91.                    union acpi_operand_object **return_object_ptr);
  92.  
  93. static acpi_status
  94. acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
  95.                    union acpi_operand_object **return_object_ptr);
  96.  
  97. static acpi_status
  98. acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
  99.                    union acpi_operand_object **return_object_ptr);
  100.  
  101. static acpi_status
  102. acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
  103.                    union acpi_operand_object **return_object_ptr);
  104.  
  105. static acpi_status
  106. acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
  107.                           union acpi_operand_object *return_object,
  108.                           u32 start_index,
  109.                           u32 expected_count,
  110.                           u32 sort_index,
  111.                           u8 sort_direction, char *sort_key_name);
  112.  
  113. /* Values for sort_direction above */
  114.  
  115. #define ACPI_SORT_ASCENDING     0
  116. #define ACPI_SORT_DESCENDING    1
  117.  
  118. static void
  119. acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index);
  120.  
  121. static void
  122. acpi_ns_sort_list(union acpi_operand_object **elements,
  123.                   u32 count, u32 index, u8 sort_direction);
  124.  
  125. /*
  126.  * This table contains the names of the predefined methods for which we can
  127.  * perform more complex repairs.
  128.  *
  129.  * As necessary:
  130.  *
  131.  * _ALR: Sort the list ascending by ambient_illuminance
  132.  * _CID: Strings: uppercase all, remove any leading asterisk
  133.  * _CST: Sort the list ascending by C state type
  134.  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
  135.  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
  136.  * _HID: Strings: uppercase all, remove any leading asterisk
  137.  * _PRT: Fix reversed source_name and source_index
  138.  * _PSS: Sort the list descending by Power
  139.  * _TSS: Sort the list descending by Power
  140.  *
  141.  * Names that must be packages, but cannot be sorted:
  142.  *
  143.  * _BCL: Values are tied to the Package index where they appear, and cannot
  144.  * be moved or sorted. These index values are used for _BQC and _BCM.
  145.  * However, we can fix the case where a buffer is returned, by converting
  146.  * it to a Package of integers.
  147.  */
  148. static const struct acpi_repair_info acpi_ns_repairable_names[] = {
  149.         {"_ALR", acpi_ns_repair_ALR},
  150.         {"_CID", acpi_ns_repair_CID},
  151.         {"_CST", acpi_ns_repair_CST},
  152.         {"_FDE", acpi_ns_repair_FDE},
  153.         {"_GTM", acpi_ns_repair_FDE},   /* _GTM has same repair as _FDE */
  154.         {"_HID", acpi_ns_repair_HID},
  155.         {"_PRT", acpi_ns_repair_PRT},
  156.         {"_PSS", acpi_ns_repair_PSS},
  157.         {"_TSS", acpi_ns_repair_TSS},
  158.         {{0, 0, 0, 0}, NULL}    /* Table terminator */
  159. };
  160.  
  161. #define ACPI_FDE_FIELD_COUNT        5
  162. #define ACPI_FDE_BYTE_BUFFER_SIZE   5
  163. #define ACPI_FDE_DWORD_BUFFER_SIZE  (ACPI_FDE_FIELD_COUNT * sizeof (u32))
  164.  
  165. /******************************************************************************
  166.  *
  167.  * FUNCTION:    acpi_ns_complex_repairs
  168.  *
  169.  * PARAMETERS:  info                - Method execution information block
  170.  *              node                - Namespace node for the method/object
  171.  *              validate_status     - Original status of earlier validation
  172.  *              return_object_ptr   - Pointer to the object returned from the
  173.  *                                    evaluation of a method or object
  174.  *
  175.  * RETURN:      Status. AE_OK if repair was successful. If name is not
  176.  *              matched, validate_status is returned.
  177.  *
  178.  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
  179.  *              not expected.
  180.  *
  181.  *****************************************************************************/
  182.  
  183. acpi_status
  184. acpi_ns_complex_repairs(struct acpi_evaluate_info *info,
  185.                         struct acpi_namespace_node *node,
  186.                         acpi_status validate_status,
  187.                         union acpi_operand_object **return_object_ptr)
  188. {
  189.         const struct acpi_repair_info *predefined;
  190.         acpi_status status;
  191.  
  192.         /* Check if this name is in the list of repairable names */
  193.  
  194.         predefined = acpi_ns_match_complex_repair(node);
  195.         if (!predefined) {
  196.                 return (validate_status);
  197.         }
  198.  
  199.         status = predefined->repair_function(info, return_object_ptr);
  200.         return (status);
  201. }
  202.  
  203. /******************************************************************************
  204.  *
  205.  * FUNCTION:    acpi_ns_match_complex_repair
  206.  *
  207.  * PARAMETERS:  node                - Namespace node for the method/object
  208.  *
  209.  * RETURN:      Pointer to entry in repair table. NULL indicates not found.
  210.  *
  211.  * DESCRIPTION: Check an object name against the repairable object list.
  212.  *
  213.  *****************************************************************************/
  214.  
  215. static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct
  216.                                                                    acpi_namespace_node
  217.                                                                    *node)
  218. {
  219.         const struct acpi_repair_info *this_name;
  220.  
  221.         /* Search info table for a repairable predefined method/object name */
  222.  
  223.         this_name = acpi_ns_repairable_names;
  224.         while (this_name->repair_function) {
  225.                 if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
  226.                         return (this_name);
  227.                 }
  228.                 this_name++;
  229.         }
  230.  
  231.         return (NULL);          /* Not found */
  232. }
  233.  
  234. /******************************************************************************
  235.  *
  236.  * FUNCTION:    acpi_ns_repair_ALR
  237.  *
  238.  * PARAMETERS:  info                - Method execution information block
  239.  *              return_object_ptr   - Pointer to the object returned from the
  240.  *                                    evaluation of a method or object
  241.  *
  242.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  243.  *
  244.  * DESCRIPTION: Repair for the _ALR object. If necessary, sort the object list
  245.  *              ascending by the ambient illuminance values.
  246.  *
  247.  *****************************************************************************/
  248.  
  249. static acpi_status
  250. acpi_ns_repair_ALR(struct acpi_evaluate_info *info,
  251.                    union acpi_operand_object **return_object_ptr)
  252. {
  253.         union acpi_operand_object *return_object = *return_object_ptr;
  254.         acpi_status status;
  255.  
  256.         status = acpi_ns_check_sorted_list(info, return_object, 0, 2, 1,
  257.                                            ACPI_SORT_ASCENDING,
  258.                                            "AmbientIlluminance");
  259.  
  260.         return (status);
  261. }
  262.  
  263. /******************************************************************************
  264.  *
  265.  * FUNCTION:    acpi_ns_repair_FDE
  266.  *
  267.  * PARAMETERS:  info                - Method execution information block
  268.  *              return_object_ptr   - Pointer to the object returned from the
  269.  *                                    evaluation of a method or object
  270.  *
  271.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  272.  *
  273.  * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
  274.  *              value is a Buffer of 5 DWORDs. This function repairs a common
  275.  *              problem where the return value is a Buffer of BYTEs, not
  276.  *              DWORDs.
  277.  *
  278.  *****************************************************************************/
  279.  
  280. static acpi_status
  281. acpi_ns_repair_FDE(struct acpi_evaluate_info *info,
  282.                    union acpi_operand_object **return_object_ptr)
  283. {
  284.         union acpi_operand_object *return_object = *return_object_ptr;
  285.         union acpi_operand_object *buffer_object;
  286.         u8 *byte_buffer;
  287.         u32 *dword_buffer;
  288.         u32 i;
  289.  
  290.         ACPI_FUNCTION_NAME(ns_repair_FDE);
  291.  
  292.         switch (return_object->common.type) {
  293.         case ACPI_TYPE_BUFFER:
  294.  
  295.                 /* This is the expected type. Length should be (at least) 5 DWORDs */
  296.  
  297.                 if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) {
  298.                         return (AE_OK);
  299.                 }
  300.  
  301.                 /* We can only repair if we have exactly 5 BYTEs */
  302.  
  303.                 if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
  304.                         ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  305.                                               info->node_flags,
  306.                                               "Incorrect return buffer length %u, expected %u",
  307.                                               return_object->buffer.length,
  308.                                               ACPI_FDE_DWORD_BUFFER_SIZE));
  309.  
  310.                         return (AE_AML_OPERAND_TYPE);
  311.                 }
  312.  
  313.                 /* Create the new (larger) buffer object */
  314.  
  315.                 buffer_object =
  316.                     acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE);
  317.                 if (!buffer_object) {
  318.                         return (AE_NO_MEMORY);
  319.                 }
  320.  
  321.                 /* Expand each byte to a DWORD */
  322.  
  323.                 byte_buffer = return_object->buffer.pointer;
  324.                 dword_buffer =
  325.                     ACPI_CAST_PTR(u32, buffer_object->buffer.pointer);
  326.  
  327.                 for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
  328.                         *dword_buffer = (u32) *byte_buffer;
  329.                         dword_buffer++;
  330.                         byte_buffer++;
  331.                 }
  332.  
  333.                 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  334.                                   "%s Expanded Byte Buffer to expected DWord Buffer\n",
  335.                                   info->full_pathname));
  336.                 break;
  337.  
  338.         default:
  339.  
  340.                 return (AE_AML_OPERAND_TYPE);
  341.         }
  342.  
  343.         /* Delete the original return object, return the new buffer object */
  344.  
  345.         acpi_ut_remove_reference(return_object);
  346.         *return_object_ptr = buffer_object;
  347.  
  348.         info->return_flags |= ACPI_OBJECT_REPAIRED;
  349.         return (AE_OK);
  350. }
  351.  
  352. /******************************************************************************
  353.  *
  354.  * FUNCTION:    acpi_ns_repair_CID
  355.  *
  356.  * PARAMETERS:  info                - Method execution information block
  357.  *              return_object_ptr   - Pointer to the object returned from the
  358.  *                                    evaluation of a method or object
  359.  *
  360.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  361.  *
  362.  * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
  363.  *              letters are uppercase and that there is no leading asterisk.
  364.  *              If a Package, ensure same for all string elements.
  365.  *
  366.  *****************************************************************************/
  367.  
  368. static acpi_status
  369. acpi_ns_repair_CID(struct acpi_evaluate_info *info,
  370.                    union acpi_operand_object **return_object_ptr)
  371. {
  372.         acpi_status status;
  373.         union acpi_operand_object *return_object = *return_object_ptr;
  374.         union acpi_operand_object **element_ptr;
  375.         union acpi_operand_object *original_element;
  376.         u16 original_ref_count;
  377.         u32 i;
  378.  
  379.         /* Check for _CID as a simple string */
  380.  
  381.         if (return_object->common.type == ACPI_TYPE_STRING) {
  382.                 status = acpi_ns_repair_HID(info, return_object_ptr);
  383.                 return (status);
  384.         }
  385.  
  386.         /* Exit if not a Package */
  387.  
  388.         if (return_object->common.type != ACPI_TYPE_PACKAGE) {
  389.                 return (AE_OK);
  390.         }
  391.  
  392.         /* Examine each element of the _CID package */
  393.  
  394.         element_ptr = return_object->package.elements;
  395.         for (i = 0; i < return_object->package.count; i++) {
  396.                 original_element = *element_ptr;
  397.                 original_ref_count = original_element->common.reference_count;
  398.  
  399.                 status = acpi_ns_repair_HID(info, element_ptr);
  400.                 if (ACPI_FAILURE(status)) {
  401.                         return (status);
  402.                 }
  403.  
  404.                 /* Take care with reference counts */
  405.  
  406.                 if (original_element != *element_ptr) {
  407.  
  408.                         /* Element was replaced */
  409.  
  410.                         (*element_ptr)->common.reference_count =
  411.                             original_ref_count;
  412.  
  413.                         acpi_ut_remove_reference(original_element);
  414.                 }
  415.  
  416.                 element_ptr++;
  417.         }
  418.  
  419.         return (AE_OK);
  420. }
  421.  
  422. /******************************************************************************
  423.  *
  424.  * FUNCTION:    acpi_ns_repair_CST
  425.  *
  426.  * PARAMETERS:  info                - Method execution information block
  427.  *              return_object_ptr   - Pointer to the object returned from the
  428.  *                                    evaluation of a method or object
  429.  *
  430.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  431.  *
  432.  * DESCRIPTION: Repair for the _CST object:
  433.  *              1. Sort the list ascending by C state type
  434.  *              2. Ensure type cannot be zero
  435.  *              3. A subpackage count of zero means _CST is meaningless
  436.  *              4. Count must match the number of C state subpackages
  437.  *
  438.  *****************************************************************************/
  439.  
  440. static acpi_status
  441. acpi_ns_repair_CST(struct acpi_evaluate_info *info,
  442.                    union acpi_operand_object **return_object_ptr)
  443. {
  444.         union acpi_operand_object *return_object = *return_object_ptr;
  445.         union acpi_operand_object **outer_elements;
  446.         u32 outer_element_count;
  447.         union acpi_operand_object *obj_desc;
  448.         acpi_status status;
  449.         u8 removing;
  450.         u32 i;
  451.  
  452.         ACPI_FUNCTION_NAME(ns_repair_CST);
  453.  
  454.         /*
  455.          * Check if the C-state type values are proportional.
  456.          */
  457.         outer_element_count = return_object->package.count - 1;
  458.         i = 0;
  459.         while (i < outer_element_count) {
  460.                 outer_elements = &return_object->package.elements[i + 1];
  461.                 removing = FALSE;
  462.  
  463.                 if ((*outer_elements)->package.count == 0) {
  464.                         ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  465.                                               info->node_flags,
  466.                                               "SubPackage[%u] - removing entry due to zero count",
  467.                                               i));
  468.                         removing = TRUE;
  469.                         goto remove_element;
  470.                 }
  471.  
  472.                 obj_desc = (*outer_elements)->package.elements[1];      /* Index1 = Type */
  473.                 if ((u32)obj_desc->integer.value == 0) {
  474.                         ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  475.                                               info->node_flags,
  476.                                               "SubPackage[%u] - removing entry due to invalid Type(0)",
  477.                                               i));
  478.                         removing = TRUE;
  479.                 }
  480.  
  481. remove_element:
  482.                 if (removing) {
  483.                         acpi_ns_remove_element(return_object, i + 1);
  484.                         outer_element_count--;
  485.                 } else {
  486.                         i++;
  487.                 }
  488.         }
  489.  
  490.         /* Update top-level package count, Type "Integer" checked elsewhere */
  491.  
  492.         obj_desc = return_object->package.elements[0];
  493.         obj_desc->integer.value = outer_element_count;
  494.  
  495.         /*
  496.          * Entries (subpackages) in the _CST Package must be sorted by the
  497.          * C-state type, in ascending order.
  498.          */
  499.         status = acpi_ns_check_sorted_list(info, return_object, 1, 4, 1,
  500.                                            ACPI_SORT_ASCENDING, "C-State Type");
  501.         if (ACPI_FAILURE(status)) {
  502.                 return (status);
  503.         }
  504.  
  505.         return (AE_OK);
  506. }
  507.  
  508. /******************************************************************************
  509.  *
  510.  * FUNCTION:    acpi_ns_repair_HID
  511.  *
  512.  * PARAMETERS:  info                - Method execution information block
  513.  *              return_object_ptr   - Pointer to the object returned from the
  514.  *                                    evaluation of a method or object
  515.  *
  516.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  517.  *
  518.  * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
  519.  *              letters are uppercase and that there is no leading asterisk.
  520.  *
  521.  *****************************************************************************/
  522.  
  523. static acpi_status
  524. acpi_ns_repair_HID(struct acpi_evaluate_info *info,
  525.                    union acpi_operand_object **return_object_ptr)
  526. {
  527.         union acpi_operand_object *return_object = *return_object_ptr;
  528.         union acpi_operand_object *new_string;
  529.         char *source;
  530.         char *dest;
  531.  
  532.         ACPI_FUNCTION_NAME(ns_repair_HID);
  533.  
  534.         /* We only care about string _HID objects (not integers) */
  535.  
  536.         if (return_object->common.type != ACPI_TYPE_STRING) {
  537.                 return (AE_OK);
  538.         }
  539.  
  540.         if (return_object->string.length == 0) {
  541.                 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  542.                                       info->node_flags,
  543.                                       "Invalid zero-length _HID or _CID string"));
  544.  
  545.                 /* Return AE_OK anyway, let driver handle it */
  546.  
  547.                 info->return_flags |= ACPI_OBJECT_REPAIRED;
  548.                 return (AE_OK);
  549.         }
  550.  
  551.         /* It is simplest to always create a new string object */
  552.  
  553.         new_string = acpi_ut_create_string_object(return_object->string.length);
  554.         if (!new_string) {
  555.                 return (AE_NO_MEMORY);
  556.         }
  557.  
  558.         /*
  559.          * Remove a leading asterisk if present. For some unknown reason, there
  560.          * are many machines in the field that contains IDs like this.
  561.          *
  562.          * Examples: "*PNP0C03", "*ACPI0003"
  563.          */
  564.         source = return_object->string.pointer;
  565.         if (*source == '*') {
  566.                 source++;
  567.                 new_string->string.length--;
  568.  
  569.                 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  570.                                   "%s: Removed invalid leading asterisk\n",
  571.                                   info->full_pathname));
  572.         }
  573.  
  574.         /*
  575.          * Copy and uppercase the string. From the ACPI 5.0 specification:
  576.          *
  577.          * A valid PNP ID must be of the form "AAA####" where A is an uppercase
  578.          * letter and # is a hex digit. A valid ACPI ID must be of the form
  579.          * "NNNN####" where N is an uppercase letter or decimal digit, and
  580.          * # is a hex digit.
  581.          */
  582.         for (dest = new_string->string.pointer; *source; dest++, source++) {
  583.                 *dest = (char)toupper((int)*source);
  584.         }
  585.  
  586.         acpi_ut_remove_reference(return_object);
  587.         *return_object_ptr = new_string;
  588.         return (AE_OK);
  589. }
  590.  
  591. /******************************************************************************
  592.  *
  593.  * FUNCTION:    acpi_ns_repair_PRT
  594.  *
  595.  * PARAMETERS:  info                - Method execution information block
  596.  *              return_object_ptr   - Pointer to the object returned from the
  597.  *                                    evaluation of a method or object
  598.  *
  599.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  600.  *
  601.  * DESCRIPTION: Repair for the _PRT object. If necessary, fix reversed
  602.  *              source_name and source_index field, a common BIOS bug.
  603.  *
  604.  *****************************************************************************/
  605.  
  606. static acpi_status
  607. acpi_ns_repair_PRT(struct acpi_evaluate_info *info,
  608.                    union acpi_operand_object **return_object_ptr)
  609. {
  610.         union acpi_operand_object *package_object = *return_object_ptr;
  611.         union acpi_operand_object **top_object_list;
  612.         union acpi_operand_object **sub_object_list;
  613.         union acpi_operand_object *obj_desc;
  614.         union acpi_operand_object *sub_package;
  615.         u32 element_count;
  616.         u32 index;
  617.  
  618.         /* Each element in the _PRT package is a subpackage */
  619.  
  620.         top_object_list = package_object->package.elements;
  621.         element_count = package_object->package.count;
  622.  
  623.         /* Examine each subpackage */
  624.  
  625.         for (index = 0; index < element_count; index++, top_object_list++) {
  626.                 sub_package = *top_object_list;
  627.                 sub_object_list = sub_package->package.elements;
  628.  
  629.                 /* Check for minimum required element count */
  630.  
  631.                 if (sub_package->package.count < 4) {
  632.                         continue;
  633.                 }
  634.  
  635.                 /*
  636.                  * If the BIOS has erroneously reversed the _PRT source_name (index 2)
  637.                  * and the source_index (index 3), fix it. _PRT is important enough to
  638.                  * workaround this BIOS error. This also provides compatibility with
  639.                  * other ACPI implementations.
  640.                  */
  641.                 obj_desc = sub_object_list[3];
  642.                 if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
  643.                         sub_object_list[3] = sub_object_list[2];
  644.                         sub_object_list[2] = obj_desc;
  645.                         info->return_flags |= ACPI_OBJECT_REPAIRED;
  646.  
  647.                         ACPI_WARN_PREDEFINED((AE_INFO,
  648.                                               info->full_pathname,
  649.                                               info->node_flags,
  650.                                               "PRT[%X]: Fixed reversed SourceName and SourceIndex",
  651.                                               index));
  652.                 }
  653.         }
  654.  
  655.         return (AE_OK);
  656. }
  657.  
  658. /******************************************************************************
  659.  *
  660.  * FUNCTION:    acpi_ns_repair_PSS
  661.  *
  662.  * PARAMETERS:  info                - Method execution information block
  663.  *              return_object_ptr   - Pointer to the object returned from the
  664.  *                                    evaluation of a method or object
  665.  *
  666.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  667.  *
  668.  * DESCRIPTION: Repair for the _PSS object. If necessary, sort the object list
  669.  *              by the CPU frequencies. Check that the power dissipation values
  670.  *              are all proportional to CPU frequency (i.e., sorting by
  671.  *              frequency should be the same as sorting by power.)
  672.  *
  673.  *****************************************************************************/
  674.  
  675. static acpi_status
  676. acpi_ns_repair_PSS(struct acpi_evaluate_info *info,
  677.                    union acpi_operand_object **return_object_ptr)
  678. {
  679.         union acpi_operand_object *return_object = *return_object_ptr;
  680.         union acpi_operand_object **outer_elements;
  681.         u32 outer_element_count;
  682.         union acpi_operand_object **elements;
  683.         union acpi_operand_object *obj_desc;
  684.         u32 previous_value;
  685.         acpi_status status;
  686.         u32 i;
  687.  
  688.         /*
  689.          * Entries (subpackages) in the _PSS Package must be sorted by power
  690.          * dissipation, in descending order. If it appears that the list is
  691.          * incorrectly sorted, sort it. We sort by cpu_frequency, since this
  692.          * should be proportional to the power.
  693.          */
  694.         status = acpi_ns_check_sorted_list(info, return_object, 0, 6, 0,
  695.                                            ACPI_SORT_DESCENDING,
  696.                                            "CpuFrequency");
  697.         if (ACPI_FAILURE(status)) {
  698.                 return (status);
  699.         }
  700.  
  701.         /*
  702.          * We now know the list is correctly sorted by CPU frequency. Check if
  703.          * the power dissipation values are proportional.
  704.          */
  705.         previous_value = ACPI_UINT32_MAX;
  706.         outer_elements = return_object->package.elements;
  707.         outer_element_count = return_object->package.count;
  708.  
  709.         for (i = 0; i < outer_element_count; i++) {
  710.                 elements = (*outer_elements)->package.elements;
  711.                 obj_desc = elements[1]; /* Index1 = power_dissipation */
  712.  
  713.                 if ((u32) obj_desc->integer.value > previous_value) {
  714.                         ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
  715.                                               info->node_flags,
  716.                                               "SubPackage[%u,%u] - suspicious power dissipation values",
  717.                                               i - 1, i));
  718.                 }
  719.  
  720.                 previous_value = (u32) obj_desc->integer.value;
  721.                 outer_elements++;
  722.         }
  723.  
  724.         return (AE_OK);
  725. }
  726.  
  727. /******************************************************************************
  728.  *
  729.  * FUNCTION:    acpi_ns_repair_TSS
  730.  *
  731.  * PARAMETERS:  info                - Method execution information block
  732.  *              return_object_ptr   - Pointer to the object returned from the
  733.  *                                    evaluation of a method or object
  734.  *
  735.  * RETURN:      Status. AE_OK if object is OK or was repaired successfully
  736.  *
  737.  * DESCRIPTION: Repair for the _TSS object. If necessary, sort the object list
  738.  *              descending by the power dissipation values.
  739.  *
  740.  *****************************************************************************/
  741.  
  742. static acpi_status
  743. acpi_ns_repair_TSS(struct acpi_evaluate_info *info,
  744.                    union acpi_operand_object **return_object_ptr)
  745. {
  746.         union acpi_operand_object *return_object = *return_object_ptr;
  747.         acpi_status status;
  748.         struct acpi_namespace_node *node;
  749.  
  750.         /*
  751.          * We can only sort the _TSS return package if there is no _PSS in the
  752.          * same scope. This is because if _PSS is present, the ACPI specification
  753.          * dictates that the _TSS Power Dissipation field is to be ignored, and
  754.          * therefore some BIOSs leave garbage values in the _TSS Power field(s).
  755.          * In this case, it is best to just return the _TSS package as-is.
  756.          * (May, 2011)
  757.          */
  758.         status = acpi_ns_get_node(info->node, "^_PSS",
  759.                                   ACPI_NS_NO_UPSEARCH, &node);
  760.         if (ACPI_SUCCESS(status)) {
  761.                 return (AE_OK);
  762.         }
  763.  
  764.         status = acpi_ns_check_sorted_list(info, return_object, 0, 5, 1,
  765.                                            ACPI_SORT_DESCENDING,
  766.                                            "PowerDissipation");
  767.  
  768.         return (status);
  769. }
  770.  
  771. /******************************************************************************
  772.  *
  773.  * FUNCTION:    acpi_ns_check_sorted_list
  774.  *
  775.  * PARAMETERS:  info                - Method execution information block
  776.  *              return_object       - Pointer to the top-level returned object
  777.  *              start_index         - Index of the first subpackage
  778.  *              expected_count      - Minimum length of each subpackage
  779.  *              sort_index          - Subpackage entry to sort on
  780.  *              sort_direction      - Ascending or descending
  781.  *              sort_key_name       - Name of the sort_index field
  782.  *
  783.  * RETURN:      Status. AE_OK if the list is valid and is sorted correctly or
  784.  *              has been repaired by sorting the list.
  785.  *
  786.  * DESCRIPTION: Check if the package list is valid and sorted correctly by the
  787.  *              sort_index. If not, then sort the list.
  788.  *
  789.  *****************************************************************************/
  790.  
  791. static acpi_status
  792. acpi_ns_check_sorted_list(struct acpi_evaluate_info *info,
  793.                           union acpi_operand_object *return_object,
  794.                           u32 start_index,
  795.                           u32 expected_count,
  796.                           u32 sort_index,
  797.                           u8 sort_direction, char *sort_key_name)
  798. {
  799.         u32 outer_element_count;
  800.         union acpi_operand_object **outer_elements;
  801.         union acpi_operand_object **elements;
  802.         union acpi_operand_object *obj_desc;
  803.         u32 i;
  804.         u32 previous_value;
  805.  
  806.         ACPI_FUNCTION_NAME(ns_check_sorted_list);
  807.  
  808.         /* The top-level object must be a package */
  809.  
  810.         if (return_object->common.type != ACPI_TYPE_PACKAGE) {
  811.                 return (AE_AML_OPERAND_TYPE);
  812.         }
  813.  
  814.         /*
  815.          * NOTE: assumes list of subpackages contains no NULL elements.
  816.          * Any NULL elements should have been removed by earlier call
  817.          * to acpi_ns_remove_null_elements.
  818.          */
  819.         outer_element_count = return_object->package.count;
  820.         if (!outer_element_count || start_index >= outer_element_count) {
  821.                 return (AE_AML_PACKAGE_LIMIT);
  822.         }
  823.  
  824.         outer_elements = &return_object->package.elements[start_index];
  825.         outer_element_count -= start_index;
  826.  
  827.         previous_value = 0;
  828.         if (sort_direction == ACPI_SORT_DESCENDING) {
  829.                 previous_value = ACPI_UINT32_MAX;
  830.         }
  831.  
  832.         /* Examine each subpackage */
  833.  
  834.         for (i = 0; i < outer_element_count; i++) {
  835.  
  836.                 /* Each element of the top-level package must also be a package */
  837.  
  838.                 if ((*outer_elements)->common.type != ACPI_TYPE_PACKAGE) {
  839.                         return (AE_AML_OPERAND_TYPE);
  840.                 }
  841.  
  842.                 /* Each subpackage must have the minimum length */
  843.  
  844.                 if ((*outer_elements)->package.count < expected_count) {
  845.                         return (AE_AML_PACKAGE_LIMIT);
  846.                 }
  847.  
  848.                 elements = (*outer_elements)->package.elements;
  849.                 obj_desc = elements[sort_index];
  850.  
  851.                 if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
  852.                         return (AE_AML_OPERAND_TYPE);
  853.                 }
  854.  
  855.                 /*
  856.                  * The list must be sorted in the specified order. If we detect a
  857.                  * discrepancy, sort the entire list.
  858.                  */
  859.                 if (((sort_direction == ACPI_SORT_ASCENDING) &&
  860.                      (obj_desc->integer.value < previous_value)) ||
  861.                     ((sort_direction == ACPI_SORT_DESCENDING) &&
  862.                      (obj_desc->integer.value > previous_value))) {
  863.                         acpi_ns_sort_list(&return_object->package.
  864.                                           elements[start_index],
  865.                                           outer_element_count, sort_index,
  866.                                           sort_direction);
  867.  
  868.                         info->return_flags |= ACPI_OBJECT_REPAIRED;
  869.  
  870.                         ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
  871.                                           "%s: Repaired unsorted list - now sorted by %s\n",
  872.                                           info->full_pathname, sort_key_name));
  873.                         return (AE_OK);
  874.                 }
  875.  
  876.                 previous_value = (u32) obj_desc->integer.value;
  877.                 outer_elements++;
  878.         }
  879.  
  880.         return (AE_OK);
  881. }
  882.  
  883. /******************************************************************************
  884.  *
  885.  * FUNCTION:    acpi_ns_sort_list
  886.  *
  887.  * PARAMETERS:  elements            - Package object element list
  888.  *              count               - Element count for above
  889.  *              index               - Sort by which package element
  890.  *              sort_direction      - Ascending or Descending sort
  891.  *
  892.  * RETURN:      None
  893.  *
  894.  * DESCRIPTION: Sort the objects that are in a package element list.
  895.  *
  896.  * NOTE: Assumes that all NULL elements have been removed from the package,
  897.  *       and that all elements have been verified to be of type Integer.
  898.  *
  899.  *****************************************************************************/
  900.  
  901. static void
  902. acpi_ns_sort_list(union acpi_operand_object **elements,
  903.                   u32 count, u32 index, u8 sort_direction)
  904. {
  905.         union acpi_operand_object *obj_desc1;
  906.         union acpi_operand_object *obj_desc2;
  907.         union acpi_operand_object *temp_obj;
  908.         u32 i;
  909.         u32 j;
  910.  
  911.         /* Simple bubble sort */
  912.  
  913.         for (i = 1; i < count; i++) {
  914.                 for (j = (count - 1); j >= i; j--) {
  915.                         obj_desc1 = elements[j - 1]->package.elements[index];
  916.                         obj_desc2 = elements[j]->package.elements[index];
  917.  
  918.                         if (((sort_direction == ACPI_SORT_ASCENDING) &&
  919.                              (obj_desc1->integer.value >
  920.                               obj_desc2->integer.value))
  921.                             || ((sort_direction == ACPI_SORT_DESCENDING)
  922.                                 && (obj_desc1->integer.value <
  923.                                     obj_desc2->integer.value))) {
  924.                                 temp_obj = elements[j - 1];
  925.                                 elements[j - 1] = elements[j];
  926.                                 elements[j] = temp_obj;
  927.                         }
  928.                 }
  929.         }
  930. }
  931.  
  932. /******************************************************************************
  933.  *
  934.  * FUNCTION:    acpi_ns_remove_element
  935.  *
  936.  * PARAMETERS:  obj_desc            - Package object element list
  937.  *              index               - Index of element to remove
  938.  *
  939.  * RETURN:      None
  940.  *
  941.  * DESCRIPTION: Remove the requested element of a package and delete it.
  942.  *
  943.  *****************************************************************************/
  944.  
  945. static void
  946. acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index)
  947. {
  948.         union acpi_operand_object **source;
  949.         union acpi_operand_object **dest;
  950.         u32 count;
  951.         u32 new_count;
  952.         u32 i;
  953.  
  954.         ACPI_FUNCTION_NAME(ns_remove_element);
  955.  
  956.         count = obj_desc->package.count;
  957.         new_count = count - 1;
  958.  
  959.         source = obj_desc->package.elements;
  960.         dest = source;
  961.  
  962.         /* Examine all elements of the package object, remove matched index */
  963.  
  964.         for (i = 0; i < count; i++) {
  965.                 if (i == index) {
  966.                         acpi_ut_remove_reference(*source);      /* Remove one ref for being in pkg */
  967.                         acpi_ut_remove_reference(*source);
  968.                 } else {
  969.                         *dest = *source;
  970.                         dest++;
  971.                 }
  972.                 source++;
  973.         }
  974.  
  975.         /* NULL terminate list and update the package count */
  976.  
  977.         *dest = NULL;
  978.         obj_desc->package.count = new_count;
  979. }
  980.