Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: nsrepair - Repair for objects returned by predefined methods
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013 #include "acinterp.h"
0014 #include "acpredef.h"
0015 #include "amlresrc.h"
0016 
0017 #define _COMPONENT          ACPI_NAMESPACE
0018 ACPI_MODULE_NAME("nsrepair")
0019 
0020 /*******************************************************************************
0021  *
0022  * This module attempts to repair or convert objects returned by the
0023  * predefined methods to an object type that is expected, as per the ACPI
0024  * specification. The need for this code is dictated by the many machines that
0025  * return incorrect types for the standard predefined methods. Performing these
0026  * conversions here, in one place, eliminates the need for individual ACPI
0027  * device drivers to do the same. Note: Most of these conversions are different
0028  * than the internal object conversion routines used for implicit object
0029  * conversion.
0030  *
0031  * The following conversions can be performed as necessary:
0032  *
0033  * Integer -> String
0034  * Integer -> Buffer
0035  * String  -> Integer
0036  * String  -> Buffer
0037  * Buffer  -> Integer
0038  * Buffer  -> String
0039  * Buffer  -> Package of Integers
0040  * Package -> Package of one Package
0041  *
0042  * Additional conversions that are available:
0043  *  Convert a null return or zero return value to an end_tag descriptor
0044  *  Convert an ASCII string to a Unicode buffer
0045  *
0046  * An incorrect standalone object is wrapped with required outer package
0047  *
0048  * Additional possible repairs:
0049  * Required package elements that are NULL replaced by Integer/String/Buffer
0050  *
0051  ******************************************************************************/
0052 /* Local prototypes */
0053 static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
0054                                      acpi_namespace_node
0055                                      *node,
0056                                      u32
0057                                      return_btype,
0058                                      u32
0059                                      package_index);
0060 
0061 /*
0062  * Special but simple repairs for some names.
0063  *
0064  * 2nd argument: Unexpected types that can be repaired
0065  */
0066 static const struct acpi_simple_repair_info acpi_object_repair_info[] = {
0067     /* Resource descriptor conversions */
0068 
0069     {"_CRS",
0070      ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
0071      ACPI_RTYPE_NONE,
0072      ACPI_NOT_PACKAGE_ELEMENT,
0073      acpi_ns_convert_to_resource},
0074     {"_DMA",
0075      ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
0076      ACPI_RTYPE_NONE,
0077      ACPI_NOT_PACKAGE_ELEMENT,
0078      acpi_ns_convert_to_resource},
0079     {"_PRS",
0080      ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER |
0081      ACPI_RTYPE_NONE,
0082      ACPI_NOT_PACKAGE_ELEMENT,
0083      acpi_ns_convert_to_resource},
0084 
0085     /* Object reference conversions */
0086 
0087     {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS,
0088      acpi_ns_convert_to_reference},
0089 
0090     /* Unicode conversions */
0091 
0092     {"_MLS", ACPI_RTYPE_STRING, 1,
0093      acpi_ns_convert_to_unicode},
0094     {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER,
0095      ACPI_NOT_PACKAGE_ELEMENT,
0096      acpi_ns_convert_to_unicode},
0097     {{0, 0, 0, 0}, 0, 0, NULL}  /* Table terminator */
0098 };
0099 
0100 /*******************************************************************************
0101  *
0102  * FUNCTION:    acpi_ns_simple_repair
0103  *
0104  * PARAMETERS:  info                - Method execution information block
0105  *              expected_btypes     - Object types expected
0106  *              package_index       - Index of object within parent package (if
0107  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
0108  *                                    otherwise)
0109  *              return_object_ptr   - Pointer to the object returned from the
0110  *                                    evaluation of a method or object
0111  *
0112  * RETURN:      Status. AE_OK if repair was successful.
0113  *
0114  * DESCRIPTION: Attempt to repair/convert a return object of a type that was
0115  *              not expected.
0116  *
0117  ******************************************************************************/
0118 
0119 acpi_status
0120 acpi_ns_simple_repair(struct acpi_evaluate_info *info,
0121               u32 expected_btypes,
0122               u32 package_index,
0123               union acpi_operand_object **return_object_ptr)
0124 {
0125     union acpi_operand_object *return_object = *return_object_ptr;
0126     union acpi_operand_object *new_object = NULL;
0127     acpi_status status;
0128     const struct acpi_simple_repair_info *predefined;
0129 
0130     ACPI_FUNCTION_NAME(ns_simple_repair);
0131 
0132     /*
0133      * Special repairs for certain names that are in the repair table.
0134      * Check if this name is in the list of repairable names.
0135      */
0136     predefined = acpi_ns_match_simple_repair(info->node,
0137                          info->return_btype,
0138                          package_index);
0139     if (predefined) {
0140         if (!return_object) {
0141             ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
0142                           ACPI_WARN_ALWAYS,
0143                           "Missing expected return value"));
0144         }
0145 
0146         status = predefined->object_converter(info->node, return_object,
0147                               &new_object);
0148         if (ACPI_FAILURE(status)) {
0149 
0150             /* A fatal error occurred during a conversion */
0151 
0152             ACPI_EXCEPTION((AE_INFO, status,
0153                     "During return object analysis"));
0154             return (status);
0155         }
0156         if (new_object) {
0157             goto object_repaired;
0158         }
0159     }
0160 
0161     /*
0162      * Do not perform simple object repair unless the return type is not
0163      * expected.
0164      */
0165     if (info->return_btype & expected_btypes) {
0166         return (AE_OK);
0167     }
0168 
0169     /*
0170      * At this point, we know that the type of the returned object was not
0171      * one of the expected types for this predefined name. Attempt to
0172      * repair the object by converting it to one of the expected object
0173      * types for this predefined name.
0174      */
0175 
0176     /*
0177      * If there is no return value, check if we require a return value for
0178      * this predefined name. Either one return value is expected, or none,
0179      * for both methods and other objects.
0180      *
0181      * Try to fix if there was no return object. Warning if failed to fix.
0182      */
0183     if (!return_object) {
0184         if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) {
0185             if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
0186                 ACPI_WARN_PREDEFINED((AE_INFO,
0187                               info->full_pathname,
0188                               ACPI_WARN_ALWAYS,
0189                               "Found unexpected NULL package element"));
0190 
0191                 status =
0192                     acpi_ns_repair_null_element(info,
0193                                 expected_btypes,
0194                                 package_index,
0195                                 return_object_ptr);
0196                 if (ACPI_SUCCESS(status)) {
0197                     return (AE_OK); /* Repair was successful */
0198                 }
0199             } else {
0200                 ACPI_WARN_PREDEFINED((AE_INFO,
0201                               info->full_pathname,
0202                               ACPI_WARN_ALWAYS,
0203                               "Missing expected return value"));
0204             }
0205 
0206             return (AE_AML_NO_RETURN_VALUE);
0207         }
0208     }
0209 
0210     if (expected_btypes & ACPI_RTYPE_INTEGER) {
0211         status = acpi_ns_convert_to_integer(return_object, &new_object);
0212         if (ACPI_SUCCESS(status)) {
0213             goto object_repaired;
0214         }
0215     }
0216     if (expected_btypes & ACPI_RTYPE_STRING) {
0217         status = acpi_ns_convert_to_string(return_object, &new_object);
0218         if (ACPI_SUCCESS(status)) {
0219             goto object_repaired;
0220         }
0221     }
0222     if (expected_btypes & ACPI_RTYPE_BUFFER) {
0223         status = acpi_ns_convert_to_buffer(return_object, &new_object);
0224         if (ACPI_SUCCESS(status)) {
0225             goto object_repaired;
0226         }
0227     }
0228     if (expected_btypes & ACPI_RTYPE_PACKAGE) {
0229         /*
0230          * A package is expected. We will wrap the existing object with a
0231          * new package object. It is often the case that if a variable-length
0232          * package is required, but there is only a single object needed, the
0233          * BIOS will return that object instead of wrapping it with a Package
0234          * object. Note: after the wrapping, the package will be validated
0235          * for correct contents (expected object type or types).
0236          */
0237         status =
0238             acpi_ns_wrap_with_package(info, return_object, &new_object);
0239         if (ACPI_SUCCESS(status)) {
0240             /*
0241              * The original object just had its reference count
0242              * incremented for being inserted into the new package.
0243              */
0244             *return_object_ptr = new_object;    /* New Package object */
0245             info->return_flags |= ACPI_OBJECT_REPAIRED;
0246             return (AE_OK);
0247         }
0248     }
0249 
0250     /* We cannot repair this object */
0251 
0252     return (AE_AML_OPERAND_TYPE);
0253 
0254 object_repaired:
0255 
0256     /* Object was successfully repaired */
0257 
0258     if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
0259 
0260         /* Update reference count of new object */
0261 
0262         if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) {
0263             new_object->common.reference_count =
0264                 return_object->common.reference_count;
0265         }
0266 
0267         ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
0268                   "%s: Converted %s to expected %s at Package index %u\n",
0269                   info->full_pathname,
0270                   acpi_ut_get_object_type_name(return_object),
0271                   acpi_ut_get_object_type_name(new_object),
0272                   package_index));
0273     } else {
0274         ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
0275                   "%s: Converted %s to expected %s\n",
0276                   info->full_pathname,
0277                   acpi_ut_get_object_type_name(return_object),
0278                   acpi_ut_get_object_type_name(new_object)));
0279     }
0280 
0281     /* Delete old object, install the new return object */
0282 
0283     acpi_ut_remove_reference(return_object);
0284     *return_object_ptr = new_object;
0285     info->return_flags |= ACPI_OBJECT_REPAIRED;
0286     return (AE_OK);
0287 }
0288 
0289 /******************************************************************************
0290  *
0291  * FUNCTION:    acpi_ns_match_simple_repair
0292  *
0293  * PARAMETERS:  node                - Namespace node for the method/object
0294  *              return_btype        - Object type that was returned
0295  *              package_index       - Index of object within parent package (if
0296  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
0297  *                                    otherwise)
0298  *
0299  * RETURN:      Pointer to entry in repair table. NULL indicates not found.
0300  *
0301  * DESCRIPTION: Check an object name against the repairable object list.
0302  *
0303  *****************************************************************************/
0304 
0305 static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct
0306                                      acpi_namespace_node
0307                                      *node,
0308                                      u32
0309                                      return_btype,
0310                                      u32
0311                                      package_index)
0312 {
0313     const struct acpi_simple_repair_info *this_name;
0314 
0315     /* Search info table for a repairable predefined method/object name */
0316 
0317     this_name = acpi_object_repair_info;
0318     while (this_name->object_converter) {
0319         if (ACPI_COMPARE_NAMESEG(node->name.ascii, this_name->name)) {
0320 
0321             /* Check if we can actually repair this name/type combination */
0322 
0323             if ((return_btype & this_name->unexpected_btypes) &&
0324                 (this_name->package_index ==
0325                  ACPI_ALL_PACKAGE_ELEMENTS
0326                  || package_index == this_name->package_index)) {
0327                 return (this_name);
0328             }
0329 
0330             return (NULL);
0331         }
0332 
0333         this_name++;
0334     }
0335 
0336     return (NULL);      /* Name was not found in the repair table */
0337 }
0338 
0339 /*******************************************************************************
0340  *
0341  * FUNCTION:    acpi_ns_repair_null_element
0342  *
0343  * PARAMETERS:  info                - Method execution information block
0344  *              expected_btypes     - Object types expected
0345  *              package_index       - Index of object within parent package (if
0346  *                                    applicable - ACPI_NOT_PACKAGE_ELEMENT
0347  *                                    otherwise)
0348  *              return_object_ptr   - Pointer to the object returned from the
0349  *                                    evaluation of a method or object
0350  *
0351  * RETURN:      Status. AE_OK if repair was successful.
0352  *
0353  * DESCRIPTION: Attempt to repair a NULL element of a returned Package object.
0354  *
0355  ******************************************************************************/
0356 
0357 acpi_status
0358 acpi_ns_repair_null_element(struct acpi_evaluate_info *info,
0359                 u32 expected_btypes,
0360                 u32 package_index,
0361                 union acpi_operand_object **return_object_ptr)
0362 {
0363     union acpi_operand_object *return_object = *return_object_ptr;
0364     union acpi_operand_object *new_object;
0365 
0366     ACPI_FUNCTION_NAME(ns_repair_null_element);
0367 
0368     /* No repair needed if return object is non-NULL */
0369 
0370     if (return_object) {
0371         return (AE_OK);
0372     }
0373 
0374     /*
0375      * Attempt to repair a NULL element of a Package object. This applies to
0376      * predefined names that return a fixed-length package and each element
0377      * is required. It does not apply to variable-length packages where NULL
0378      * elements are allowed, especially at the end of the package.
0379      */
0380     if (expected_btypes & ACPI_RTYPE_INTEGER) {
0381 
0382         /* Need an integer - create a zero-value integer */
0383 
0384         new_object = acpi_ut_create_integer_object((u64)0);
0385     } else if (expected_btypes & ACPI_RTYPE_STRING) {
0386 
0387         /* Need a string - create a NULL string */
0388 
0389         new_object = acpi_ut_create_string_object(0);
0390     } else if (expected_btypes & ACPI_RTYPE_BUFFER) {
0391 
0392         /* Need a buffer - create a zero-length buffer */
0393 
0394         new_object = acpi_ut_create_buffer_object(0);
0395     } else {
0396         /* Error for all other expected types */
0397 
0398         return (AE_AML_OPERAND_TYPE);
0399     }
0400 
0401     if (!new_object) {
0402         return (AE_NO_MEMORY);
0403     }
0404 
0405     /* Set the reference count according to the parent Package object */
0406 
0407     new_object->common.reference_count =
0408         info->parent_package->common.reference_count;
0409 
0410     ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
0411               "%s: Converted NULL package element to expected %s at index %u\n",
0412               info->full_pathname,
0413               acpi_ut_get_object_type_name(new_object),
0414               package_index));
0415 
0416     *return_object_ptr = new_object;
0417     info->return_flags |= ACPI_OBJECT_REPAIRED;
0418     return (AE_OK);
0419 }
0420 
0421 /******************************************************************************
0422  *
0423  * FUNCTION:    acpi_ns_remove_null_elements
0424  *
0425  * PARAMETERS:  info                - Method execution information block
0426  *              package_type        - An acpi_return_package_types value
0427  *              obj_desc            - A Package object
0428  *
0429  * RETURN:      None.
0430  *
0431  * DESCRIPTION: Remove all NULL package elements from packages that contain
0432  *              a variable number of subpackages. For these types of
0433  *              packages, NULL elements can be safely removed.
0434  *
0435  *****************************************************************************/
0436 
0437 void
0438 acpi_ns_remove_null_elements(struct acpi_evaluate_info *info,
0439                  u8 package_type,
0440                  union acpi_operand_object *obj_desc)
0441 {
0442     union acpi_operand_object **source;
0443     union acpi_operand_object **dest;
0444     u32 count;
0445     u32 new_count;
0446     u32 i;
0447 
0448     ACPI_FUNCTION_NAME(ns_remove_null_elements);
0449 
0450     /*
0451      * We can safely remove all NULL elements from these package types:
0452      * PTYPE1_VAR packages contain a variable number of simple data types.
0453      * PTYPE2 packages contain a variable number of subpackages.
0454      */
0455     switch (package_type) {
0456     case ACPI_PTYPE1_VAR:
0457     case ACPI_PTYPE2:
0458     case ACPI_PTYPE2_COUNT:
0459     case ACPI_PTYPE2_PKG_COUNT:
0460     case ACPI_PTYPE2_FIXED:
0461     case ACPI_PTYPE2_MIN:
0462     case ACPI_PTYPE2_REV_FIXED:
0463     case ACPI_PTYPE2_FIX_VAR:
0464         break;
0465 
0466     default:
0467     case ACPI_PTYPE2_VAR_VAR:
0468     case ACPI_PTYPE1_FIXED:
0469     case ACPI_PTYPE1_OPTION:
0470         return;
0471     }
0472 
0473     count = obj_desc->package.count;
0474     new_count = count;
0475 
0476     source = obj_desc->package.elements;
0477     dest = source;
0478 
0479     /* Examine all elements of the package object, remove nulls */
0480 
0481     for (i = 0; i < count; i++) {
0482         if (!*source) {
0483             new_count--;
0484         } else {
0485             *dest = *source;
0486             dest++;
0487         }
0488 
0489         source++;
0490     }
0491 
0492     /* Update parent package if any null elements were removed */
0493 
0494     if (new_count < count) {
0495         ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
0496                   "%s: Found and removed %u NULL elements\n",
0497                   info->full_pathname, (count - new_count)));
0498 
0499         /* NULL terminate list and update the package count */
0500 
0501         *dest = NULL;
0502         obj_desc->package.count = new_count;
0503     }
0504 }
0505 
0506 /*******************************************************************************
0507  *
0508  * FUNCTION:    acpi_ns_wrap_with_package
0509  *
0510  * PARAMETERS:  info                - Method execution information block
0511  *              original_object     - Pointer to the object to repair.
0512  *              obj_desc_ptr        - The new package object is returned here
0513  *
0514  * RETURN:      Status, new object in *obj_desc_ptr
0515  *
0516  * DESCRIPTION: Repair a common problem with objects that are defined to
0517  *              return a variable-length Package of sub-objects. If there is
0518  *              only one sub-object, some BIOS code mistakenly simply declares
0519  *              the single object instead of a Package with one sub-object.
0520  *              This function attempts to repair this error by wrapping a
0521  *              Package object around the original object, creating the
0522  *              correct and expected Package with one sub-object.
0523  *
0524  *              Names that can be repaired in this manner include:
0525  *              _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS,
0526  *              _BCL, _DOD, _FIX, _Sx
0527  *
0528  ******************************************************************************/
0529 
0530 acpi_status
0531 acpi_ns_wrap_with_package(struct acpi_evaluate_info *info,
0532               union acpi_operand_object *original_object,
0533               union acpi_operand_object **obj_desc_ptr)
0534 {
0535     union acpi_operand_object *pkg_obj_desc;
0536 
0537     ACPI_FUNCTION_NAME(ns_wrap_with_package);
0538 
0539     /*
0540      * Create the new outer package and populate it. The new
0541      * package will have a single element, the lone sub-object.
0542      */
0543     pkg_obj_desc = acpi_ut_create_package_object(1);
0544     if (!pkg_obj_desc) {
0545         return (AE_NO_MEMORY);
0546     }
0547 
0548     pkg_obj_desc->package.elements[0] = original_object;
0549 
0550     ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
0551               "%s: Wrapped %s with expected Package object\n",
0552               info->full_pathname,
0553               acpi_ut_get_object_type_name(original_object)));
0554 
0555     /* Return the new object in the object pointer */
0556 
0557     *obj_desc_ptr = pkg_obj_desc;
0558     info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED;
0559     return (AE_OK);
0560 }