nsrepair.c (17407B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/****************************************************************************** 3 * 4 * Module Name: nsrepair - Repair for objects returned by predefined methods 5 * 6 * Copyright (C) 2000 - 2022, Intel Corp. 7 * 8 *****************************************************************************/ 9 10#include <acpi/acpi.h> 11#include "accommon.h" 12#include "acnamesp.h" 13#include "acinterp.h" 14#include "acpredef.h" 15#include "amlresrc.h" 16 17#define _COMPONENT ACPI_NAMESPACE 18ACPI_MODULE_NAME("nsrepair") 19 20/******************************************************************************* 21 * 22 * This module attempts to repair or convert objects returned by the 23 * predefined methods to an object type that is expected, as per the ACPI 24 * specification. The need for this code is dictated by the many machines that 25 * return incorrect types for the standard predefined methods. Performing these 26 * conversions here, in one place, eliminates the need for individual ACPI 27 * device drivers to do the same. Note: Most of these conversions are different 28 * than the internal object conversion routines used for implicit object 29 * conversion. 30 * 31 * The following conversions can be performed as necessary: 32 * 33 * Integer -> String 34 * Integer -> Buffer 35 * String -> Integer 36 * String -> Buffer 37 * Buffer -> Integer 38 * Buffer -> String 39 * Buffer -> Package of Integers 40 * Package -> Package of one Package 41 * 42 * Additional conversions that are available: 43 * Convert a null return or zero return value to an end_tag descriptor 44 * Convert an ASCII string to a Unicode buffer 45 * 46 * An incorrect standalone object is wrapped with required outer package 47 * 48 * Additional possible repairs: 49 * Required package elements that are NULL replaced by Integer/String/Buffer 50 * 51 ******************************************************************************/ 52/* Local prototypes */ 53static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 54 acpi_namespace_node 55 *node, 56 u32 57 return_btype, 58 u32 59 package_index); 60 61/* 62 * Special but simple repairs for some names. 63 * 64 * 2nd argument: Unexpected types that can be repaired 65 */ 66static const struct acpi_simple_repair_info acpi_object_repair_info[] = { 67 /* Resource descriptor conversions */ 68 69 {"_CRS", 70 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 71 ACPI_RTYPE_NONE, 72 ACPI_NOT_PACKAGE_ELEMENT, 73 acpi_ns_convert_to_resource}, 74 {"_DMA", 75 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 76 ACPI_RTYPE_NONE, 77 ACPI_NOT_PACKAGE_ELEMENT, 78 acpi_ns_convert_to_resource}, 79 {"_PRS", 80 ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | 81 ACPI_RTYPE_NONE, 82 ACPI_NOT_PACKAGE_ELEMENT, 83 acpi_ns_convert_to_resource}, 84 85 /* Object reference conversions */ 86 87 {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS, 88 acpi_ns_convert_to_reference}, 89 90 /* Unicode conversions */ 91 92 {"_MLS", ACPI_RTYPE_STRING, 1, 93 acpi_ns_convert_to_unicode}, 94 {"_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 95 ACPI_NOT_PACKAGE_ELEMENT, 96 acpi_ns_convert_to_unicode}, 97 {{0, 0, 0, 0}, 0, 0, NULL} /* Table terminator */ 98}; 99 100/******************************************************************************* 101 * 102 * FUNCTION: acpi_ns_simple_repair 103 * 104 * PARAMETERS: info - Method execution information block 105 * expected_btypes - Object types expected 106 * package_index - Index of object within parent package (if 107 * applicable - ACPI_NOT_PACKAGE_ELEMENT 108 * otherwise) 109 * return_object_ptr - Pointer to the object returned from the 110 * evaluation of a method or object 111 * 112 * RETURN: Status. AE_OK if repair was successful. 113 * 114 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 115 * not expected. 116 * 117 ******************************************************************************/ 118 119acpi_status 120acpi_ns_simple_repair(struct acpi_evaluate_info *info, 121 u32 expected_btypes, 122 u32 package_index, 123 union acpi_operand_object **return_object_ptr) 124{ 125 union acpi_operand_object *return_object = *return_object_ptr; 126 union acpi_operand_object *new_object = NULL; 127 acpi_status status; 128 const struct acpi_simple_repair_info *predefined; 129 130 ACPI_FUNCTION_NAME(ns_simple_repair); 131 132 /* 133 * Special repairs for certain names that are in the repair table. 134 * Check if this name is in the list of repairable names. 135 */ 136 predefined = acpi_ns_match_simple_repair(info->node, 137 info->return_btype, 138 package_index); 139 if (predefined) { 140 if (!return_object) { 141 ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, 142 ACPI_WARN_ALWAYS, 143 "Missing expected return value")); 144 } 145 146 status = predefined->object_converter(info->node, return_object, 147 &new_object); 148 if (ACPI_FAILURE(status)) { 149 150 /* A fatal error occurred during a conversion */ 151 152 ACPI_EXCEPTION((AE_INFO, status, 153 "During return object analysis")); 154 return (status); 155 } 156 if (new_object) { 157 goto object_repaired; 158 } 159 } 160 161 /* 162 * Do not perform simple object repair unless the return type is not 163 * expected. 164 */ 165 if (info->return_btype & expected_btypes) { 166 return (AE_OK); 167 } 168 169 /* 170 * At this point, we know that the type of the returned object was not 171 * one of the expected types for this predefined name. Attempt to 172 * repair the object by converting it to one of the expected object 173 * types for this predefined name. 174 */ 175 176 /* 177 * If there is no return value, check if we require a return value for 178 * this predefined name. Either one return value is expected, or none, 179 * for both methods and other objects. 180 * 181 * Try to fix if there was no return object. Warning if failed to fix. 182 */ 183 if (!return_object) { 184 if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { 185 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 186 ACPI_WARN_PREDEFINED((AE_INFO, 187 info->full_pathname, 188 ACPI_WARN_ALWAYS, 189 "Found unexpected NULL package element")); 190 191 status = 192 acpi_ns_repair_null_element(info, 193 expected_btypes, 194 package_index, 195 return_object_ptr); 196 if (ACPI_SUCCESS(status)) { 197 return (AE_OK); /* Repair was successful */ 198 } 199 } else { 200 ACPI_WARN_PREDEFINED((AE_INFO, 201 info->full_pathname, 202 ACPI_WARN_ALWAYS, 203 "Missing expected return value")); 204 } 205 206 return (AE_AML_NO_RETURN_VALUE); 207 } 208 } 209 210 if (expected_btypes & ACPI_RTYPE_INTEGER) { 211 status = acpi_ns_convert_to_integer(return_object, &new_object); 212 if (ACPI_SUCCESS(status)) { 213 goto object_repaired; 214 } 215 } 216 if (expected_btypes & ACPI_RTYPE_STRING) { 217 status = acpi_ns_convert_to_string(return_object, &new_object); 218 if (ACPI_SUCCESS(status)) { 219 goto object_repaired; 220 } 221 } 222 if (expected_btypes & ACPI_RTYPE_BUFFER) { 223 status = acpi_ns_convert_to_buffer(return_object, &new_object); 224 if (ACPI_SUCCESS(status)) { 225 goto object_repaired; 226 } 227 } 228 if (expected_btypes & ACPI_RTYPE_PACKAGE) { 229 /* 230 * A package is expected. We will wrap the existing object with a 231 * new package object. It is often the case that if a variable-length 232 * package is required, but there is only a single object needed, the 233 * BIOS will return that object instead of wrapping it with a Package 234 * object. Note: after the wrapping, the package will be validated 235 * for correct contents (expected object type or types). 236 */ 237 status = 238 acpi_ns_wrap_with_package(info, return_object, &new_object); 239 if (ACPI_SUCCESS(status)) { 240 /* 241 * The original object just had its reference count 242 * incremented for being inserted into the new package. 243 */ 244 *return_object_ptr = new_object; /* New Package object */ 245 info->return_flags |= ACPI_OBJECT_REPAIRED; 246 return (AE_OK); 247 } 248 } 249 250 /* We cannot repair this object */ 251 252 return (AE_AML_OPERAND_TYPE); 253 254object_repaired: 255 256 /* Object was successfully repaired */ 257 258 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 259 260 /* Update reference count of new object */ 261 262 if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { 263 new_object->common.reference_count = 264 return_object->common.reference_count; 265 } 266 267 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 268 "%s: Converted %s to expected %s at Package index %u\n", 269 info->full_pathname, 270 acpi_ut_get_object_type_name(return_object), 271 acpi_ut_get_object_type_name(new_object), 272 package_index)); 273 } else { 274 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 275 "%s: Converted %s to expected %s\n", 276 info->full_pathname, 277 acpi_ut_get_object_type_name(return_object), 278 acpi_ut_get_object_type_name(new_object))); 279 } 280 281 /* Delete old object, install the new return object */ 282 283 acpi_ut_remove_reference(return_object); 284 *return_object_ptr = new_object; 285 info->return_flags |= ACPI_OBJECT_REPAIRED; 286 return (AE_OK); 287} 288 289/****************************************************************************** 290 * 291 * FUNCTION: acpi_ns_match_simple_repair 292 * 293 * PARAMETERS: node - Namespace node for the method/object 294 * return_btype - Object type that was returned 295 * package_index - Index of object within parent package (if 296 * applicable - ACPI_NOT_PACKAGE_ELEMENT 297 * otherwise) 298 * 299 * RETURN: Pointer to entry in repair table. NULL indicates not found. 300 * 301 * DESCRIPTION: Check an object name against the repairable object list. 302 * 303 *****************************************************************************/ 304 305static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct 306 acpi_namespace_node 307 *node, 308 u32 309 return_btype, 310 u32 311 package_index) 312{ 313 const struct acpi_simple_repair_info *this_name; 314 315 /* Search info table for a repairable predefined method/object name */ 316 317 this_name = acpi_object_repair_info; 318 while (this_name->object_converter) { 319 if (ACPI_COMPARE_NAMESEG(node->name.ascii, this_name->name)) { 320 321 /* Check if we can actually repair this name/type combination */ 322 323 if ((return_btype & this_name->unexpected_btypes) && 324 (this_name->package_index == 325 ACPI_ALL_PACKAGE_ELEMENTS 326 || package_index == this_name->package_index)) { 327 return (this_name); 328 } 329 330 return (NULL); 331 } 332 333 this_name++; 334 } 335 336 return (NULL); /* Name was not found in the repair table */ 337} 338 339/******************************************************************************* 340 * 341 * FUNCTION: acpi_ns_repair_null_element 342 * 343 * PARAMETERS: info - Method execution information block 344 * expected_btypes - Object types expected 345 * package_index - Index of object within parent package (if 346 * applicable - ACPI_NOT_PACKAGE_ELEMENT 347 * otherwise) 348 * return_object_ptr - Pointer to the object returned from the 349 * evaluation of a method or object 350 * 351 * RETURN: Status. AE_OK if repair was successful. 352 * 353 * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 354 * 355 ******************************************************************************/ 356 357acpi_status 358acpi_ns_repair_null_element(struct acpi_evaluate_info *info, 359 u32 expected_btypes, 360 u32 package_index, 361 union acpi_operand_object **return_object_ptr) 362{ 363 union acpi_operand_object *return_object = *return_object_ptr; 364 union acpi_operand_object *new_object; 365 366 ACPI_FUNCTION_NAME(ns_repair_null_element); 367 368 /* No repair needed if return object is non-NULL */ 369 370 if (return_object) { 371 return (AE_OK); 372 } 373 374 /* 375 * Attempt to repair a NULL element of a Package object. This applies to 376 * predefined names that return a fixed-length package and each element 377 * is required. It does not apply to variable-length packages where NULL 378 * elements are allowed, especially at the end of the package. 379 */ 380 if (expected_btypes & ACPI_RTYPE_INTEGER) { 381 382 /* Need an integer - create a zero-value integer */ 383 384 new_object = acpi_ut_create_integer_object((u64)0); 385 } else if (expected_btypes & ACPI_RTYPE_STRING) { 386 387 /* Need a string - create a NULL string */ 388 389 new_object = acpi_ut_create_string_object(0); 390 } else if (expected_btypes & ACPI_RTYPE_BUFFER) { 391 392 /* Need a buffer - create a zero-length buffer */ 393 394 new_object = acpi_ut_create_buffer_object(0); 395 } else { 396 /* Error for all other expected types */ 397 398 return (AE_AML_OPERAND_TYPE); 399 } 400 401 if (!new_object) { 402 return (AE_NO_MEMORY); 403 } 404 405 /* Set the reference count according to the parent Package object */ 406 407 new_object->common.reference_count = 408 info->parent_package->common.reference_count; 409 410 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 411 "%s: Converted NULL package element to expected %s at index %u\n", 412 info->full_pathname, 413 acpi_ut_get_object_type_name(new_object), 414 package_index)); 415 416 *return_object_ptr = new_object; 417 info->return_flags |= ACPI_OBJECT_REPAIRED; 418 return (AE_OK); 419} 420 421/****************************************************************************** 422 * 423 * FUNCTION: acpi_ns_remove_null_elements 424 * 425 * PARAMETERS: info - Method execution information block 426 * package_type - An acpi_return_package_types value 427 * obj_desc - A Package object 428 * 429 * RETURN: None. 430 * 431 * DESCRIPTION: Remove all NULL package elements from packages that contain 432 * a variable number of subpackages. For these types of 433 * packages, NULL elements can be safely removed. 434 * 435 *****************************************************************************/ 436 437void 438acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, 439 u8 package_type, 440 union acpi_operand_object *obj_desc) 441{ 442 union acpi_operand_object **source; 443 union acpi_operand_object **dest; 444 u32 count; 445 u32 new_count; 446 u32 i; 447 448 ACPI_FUNCTION_NAME(ns_remove_null_elements); 449 450 /* 451 * We can safely remove all NULL elements from these package types: 452 * PTYPE1_VAR packages contain a variable number of simple data types. 453 * PTYPE2 packages contain a variable number of subpackages. 454 */ 455 switch (package_type) { 456 case ACPI_PTYPE1_VAR: 457 case ACPI_PTYPE2: 458 case ACPI_PTYPE2_COUNT: 459 case ACPI_PTYPE2_PKG_COUNT: 460 case ACPI_PTYPE2_FIXED: 461 case ACPI_PTYPE2_MIN: 462 case ACPI_PTYPE2_REV_FIXED: 463 case ACPI_PTYPE2_FIX_VAR: 464 break; 465 466 default: 467 case ACPI_PTYPE2_VAR_VAR: 468 case ACPI_PTYPE1_FIXED: 469 case ACPI_PTYPE1_OPTION: 470 return; 471 } 472 473 count = obj_desc->package.count; 474 new_count = count; 475 476 source = obj_desc->package.elements; 477 dest = source; 478 479 /* Examine all elements of the package object, remove nulls */ 480 481 for (i = 0; i < count; i++) { 482 if (!*source) { 483 new_count--; 484 } else { 485 *dest = *source; 486 dest++; 487 } 488 489 source++; 490 } 491 492 /* Update parent package if any null elements were removed */ 493 494 if (new_count < count) { 495 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 496 "%s: Found and removed %u NULL elements\n", 497 info->full_pathname, (count - new_count))); 498 499 /* NULL terminate list and update the package count */ 500 501 *dest = NULL; 502 obj_desc->package.count = new_count; 503 } 504} 505 506/******************************************************************************* 507 * 508 * FUNCTION: acpi_ns_wrap_with_package 509 * 510 * PARAMETERS: info - Method execution information block 511 * original_object - Pointer to the object to repair. 512 * obj_desc_ptr - The new package object is returned here 513 * 514 * RETURN: Status, new object in *obj_desc_ptr 515 * 516 * DESCRIPTION: Repair a common problem with objects that are defined to 517 * return a variable-length Package of sub-objects. If there is 518 * only one sub-object, some BIOS code mistakenly simply declares 519 * the single object instead of a Package with one sub-object. 520 * This function attempts to repair this error by wrapping a 521 * Package object around the original object, creating the 522 * correct and expected Package with one sub-object. 523 * 524 * Names that can be repaired in this manner include: 525 * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 526 * _BCL, _DOD, _FIX, _Sx 527 * 528 ******************************************************************************/ 529 530acpi_status 531acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, 532 union acpi_operand_object *original_object, 533 union acpi_operand_object **obj_desc_ptr) 534{ 535 union acpi_operand_object *pkg_obj_desc; 536 537 ACPI_FUNCTION_NAME(ns_wrap_with_package); 538 539 /* 540 * Create the new outer package and populate it. The new 541 * package will have a single element, the lone sub-object. 542 */ 543 pkg_obj_desc = acpi_ut_create_package_object(1); 544 if (!pkg_obj_desc) { 545 return (AE_NO_MEMORY); 546 } 547 548 pkg_obj_desc->package.elements[0] = original_object; 549 550 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 551 "%s: Wrapped %s with expected Package object\n", 552 info->full_pathname, 553 acpi_ut_get_object_type_name(original_object))); 554 555 /* Return the new object in the object pointer */ 556 557 *obj_desc_ptr = pkg_obj_desc; 558 info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 559 return (AE_OK); 560}