1 /****************************************************************************** 2 * 3 * Module Name: nsrepair - Repair for objects returned by predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "acnamesp.h" 47 #include "acinterp.h" 48 #include "acpredef.h" 49 #include "amlresrc.h" 50 51 #define _COMPONENT ACPI_NAMESPACE 52 ACPI_MODULE_NAME ("nsrepair") 53 54 55 /******************************************************************************* 56 * 57 * This module attempts to repair or convert objects returned by the 58 * predefined methods to an object type that is expected, as per the ACPI 59 * specification. The need for this code is dictated by the many machines that 60 * return incorrect types for the standard predefined methods. Performing these 61 * conversions here, in one place, eliminates the need for individual ACPI 62 * device drivers to do the same. Note: Most of these conversions are different 63 * than the internal object conversion routines used for implicit object 64 * conversion. 65 * 66 * The following conversions can be performed as necessary: 67 * 68 * Integer -> String 69 * Integer -> Buffer 70 * String -> Integer 71 * String -> Buffer 72 * Buffer -> Integer 73 * Buffer -> String 74 * Buffer -> Package of Integers 75 * Package -> Package of one Package 76 * 77 * Additional conversions that are available: 78 * Convert a null return or zero return value to an EndTag descriptor 79 * Convert an ASCII string to a Unicode buffer 80 * 81 * An incorrect standalone object is wrapped with required outer package 82 * 83 * Additional possible repairs: 84 * Required package elements that are NULL replaced by Integer/String/Buffer 85 * 86 ******************************************************************************/ 87 88 89 /* Local prototypes */ 90 91 static const ACPI_SIMPLE_REPAIR_INFO * 92 AcpiNsMatchSimpleRepair ( 93 ACPI_NAMESPACE_NODE *Node, 94 UINT32 ReturnBtype, 95 UINT32 PackageIndex); 96 97 98 /* 99 * Special but simple repairs for some names. 100 * 101 * 2nd argument: Unexpected types that can be repaired 102 */ 103 static const ACPI_SIMPLE_REPAIR_INFO AcpiObjectRepairInfo[] = 104 { 105 /* Resource descriptor conversions */ 106 107 { "_CRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, 108 ACPI_NOT_PACKAGE_ELEMENT, 109 AcpiNsConvertToResource }, 110 { "_DMA", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, 111 ACPI_NOT_PACKAGE_ELEMENT, 112 AcpiNsConvertToResource }, 113 { "_PRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, 114 ACPI_NOT_PACKAGE_ELEMENT, 115 AcpiNsConvertToResource }, 116 117 /* Object reference conversions */ 118 119 { "_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS, 120 AcpiNsConvertToReference }, 121 122 /* Unicode conversions */ 123 124 { "_MLS", ACPI_RTYPE_STRING, 1, 125 AcpiNsConvertToUnicode }, 126 { "_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 127 ACPI_NOT_PACKAGE_ELEMENT, 128 AcpiNsConvertToUnicode }, 129 { {0,0,0,0}, 0, 0, NULL } /* Table terminator */ 130 }; 131 132 133 /******************************************************************************* 134 * 135 * FUNCTION: AcpiNsSimpleRepair 136 * 137 * PARAMETERS: Info - Method execution information block 138 * ExpectedBtypes - Object types expected 139 * PackageIndex - Index of object within parent package (if 140 * applicable - ACPI_NOT_PACKAGE_ELEMENT 141 * otherwise) 142 * ReturnObjectPtr - Pointer to the object returned from the 143 * evaluation of a method or object 144 * 145 * RETURN: Status. AE_OK if repair was successful. 146 * 147 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 148 * not expected. 149 * 150 ******************************************************************************/ 151 152 ACPI_STATUS 153 AcpiNsSimpleRepair ( 154 ACPI_EVALUATE_INFO *Info, 155 UINT32 ExpectedBtypes, 156 UINT32 PackageIndex, 157 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 158 { 159 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 160 ACPI_OPERAND_OBJECT *NewObject = NULL; 161 ACPI_STATUS Status; 162 const ACPI_SIMPLE_REPAIR_INFO *Predefined; 163 164 165 ACPI_FUNCTION_NAME (NsSimpleRepair); 166 167 168 /* 169 * Special repairs for certain names that are in the repair table. 170 * Check if this name is in the list of repairable names. 171 */ 172 Predefined = AcpiNsMatchSimpleRepair (Info->Node, 173 Info->ReturnBtype, PackageIndex); 174 if (Predefined) 175 { 176 if (!ReturnObject) 177 { 178 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 179 ACPI_WARN_ALWAYS, "Missing expected return value")); 180 } 181 182 Status = Predefined->ObjectConverter (Info->Node, ReturnObject, 183 &NewObject); 184 if (ACPI_FAILURE (Status)) 185 { 186 /* A fatal error occurred during a conversion */ 187 188 ACPI_EXCEPTION ((AE_INFO, Status, 189 "During return object analysis")); 190 return (Status); 191 } 192 if (NewObject) 193 { 194 goto ObjectRepaired; 195 } 196 } 197 198 /* 199 * Do not perform simple object repair unless the return type is not 200 * expected. 201 */ 202 if (Info->ReturnBtype & ExpectedBtypes) 203 { 204 return (AE_OK); 205 } 206 207 /* 208 * At this point, we know that the type of the returned object was not 209 * one of the expected types for this predefined name. Attempt to 210 * repair the object by converting it to one of the expected object 211 * types for this predefined name. 212 */ 213 214 /* 215 * If there is no return value, check if we require a return value for 216 * this predefined name. Either one return value is expected, or none, 217 * for both methods and other objects. 218 * 219 * Try to fix if there was no return object. Warning if failed to fix. 220 */ 221 if (!ReturnObject) 222 { 223 if (ExpectedBtypes && (!(ExpectedBtypes & ACPI_RTYPE_NONE))) 224 { 225 if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) 226 { 227 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 228 ACPI_WARN_ALWAYS, "Found unexpected NULL package element")); 229 230 Status = AcpiNsRepairNullElement (Info, ExpectedBtypes, 231 PackageIndex, ReturnObjectPtr); 232 if (ACPI_SUCCESS (Status)) 233 { 234 return (AE_OK); /* Repair was successful */ 235 } 236 } 237 else 238 { 239 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 240 ACPI_WARN_ALWAYS, "Missing expected return value")); 241 } 242 243 return (AE_AML_NO_RETURN_VALUE); 244 } 245 } 246 247 if (ExpectedBtypes & ACPI_RTYPE_INTEGER) 248 { 249 Status = AcpiNsConvertToInteger (ReturnObject, &NewObject); 250 if (ACPI_SUCCESS (Status)) 251 { 252 goto ObjectRepaired; 253 } 254 } 255 if (ExpectedBtypes & ACPI_RTYPE_STRING) 256 { 257 Status = AcpiNsConvertToString (ReturnObject, &NewObject); 258 if (ACPI_SUCCESS (Status)) 259 { 260 goto ObjectRepaired; 261 } 262 } 263 if (ExpectedBtypes & ACPI_RTYPE_BUFFER) 264 { 265 Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject); 266 if (ACPI_SUCCESS (Status)) 267 { 268 goto ObjectRepaired; 269 } 270 } 271 if (ExpectedBtypes & ACPI_RTYPE_PACKAGE) 272 { 273 /* 274 * A package is expected. We will wrap the existing object with a 275 * new package object. It is often the case that if a variable-length 276 * package is required, but there is only a single object needed, the 277 * BIOS will return that object instead of wrapping it with a Package 278 * object. Note: after the wrapping, the package will be validated 279 * for correct contents (expected object type or types). 280 */ 281 Status = AcpiNsWrapWithPackage (Info, ReturnObject, &NewObject); 282 if (ACPI_SUCCESS (Status)) 283 { 284 /* 285 * The original object just had its reference count 286 * incremented for being inserted into the new package. 287 */ 288 *ReturnObjectPtr = NewObject; /* New Package object */ 289 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 290 return (AE_OK); 291 } 292 } 293 294 /* We cannot repair this object */ 295 296 return (AE_AML_OPERAND_TYPE); 297 298 299 ObjectRepaired: 300 301 /* Object was successfully repaired */ 302 303 if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) 304 { 305 /* 306 * The original object is a package element. We need to 307 * decrement the reference count of the original object, 308 * for removing it from the package. 309 * 310 * However, if the original object was just wrapped with a 311 * package object as part of the repair, we don't need to 312 * change the reference count. 313 */ 314 if (!(Info->ReturnFlags & ACPI_OBJECT_WRAPPED)) 315 { 316 NewObject->Common.ReferenceCount = 317 ReturnObject->Common.ReferenceCount; 318 319 if (ReturnObject->Common.ReferenceCount > 1) 320 { 321 ReturnObject->Common.ReferenceCount--; 322 } 323 } 324 325 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 326 "%s: Converted %s to expected %s at Package index %u\n", 327 Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), 328 AcpiUtGetObjectTypeName (NewObject), PackageIndex)); 329 } 330 else 331 { 332 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 333 "%s: Converted %s to expected %s\n", 334 Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), 335 AcpiUtGetObjectTypeName (NewObject))); 336 } 337 338 /* Delete old object, install the new return object */ 339 340 AcpiUtRemoveReference (ReturnObject); 341 *ReturnObjectPtr = NewObject; 342 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 343 return (AE_OK); 344 } 345 346 347 /****************************************************************************** 348 * 349 * FUNCTION: AcpiNsMatchSimpleRepair 350 * 351 * PARAMETERS: Node - Namespace node for the method/object 352 * ReturnBtype - Object type that was returned 353 * PackageIndex - Index of object within parent package (if 354 * applicable - ACPI_NOT_PACKAGE_ELEMENT 355 * otherwise) 356 * 357 * RETURN: Pointer to entry in repair table. NULL indicates not found. 358 * 359 * DESCRIPTION: Check an object name against the repairable object list. 360 * 361 *****************************************************************************/ 362 363 static const ACPI_SIMPLE_REPAIR_INFO * 364 AcpiNsMatchSimpleRepair ( 365 ACPI_NAMESPACE_NODE *Node, 366 UINT32 ReturnBtype, 367 UINT32 PackageIndex) 368 { 369 const ACPI_SIMPLE_REPAIR_INFO *ThisName; 370 371 372 /* Search info table for a repairable predefined method/object name */ 373 374 ThisName = AcpiObjectRepairInfo; 375 while (ThisName->ObjectConverter) 376 { 377 if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) 378 { 379 /* Check if we can actually repair this name/type combination */ 380 381 if ((ReturnBtype & ThisName->UnexpectedBtypes) && 382 (ThisName->PackageIndex == ACPI_ALL_PACKAGE_ELEMENTS || 383 PackageIndex == ThisName->PackageIndex)) 384 { 385 return (ThisName); 386 } 387 388 return (NULL); 389 } 390 391 ThisName++; 392 } 393 394 return (NULL); /* Name was not found in the repair table */ 395 } 396 397 398 /******************************************************************************* 399 * 400 * FUNCTION: AcpiNsRepairNullElement 401 * 402 * PARAMETERS: Info - Method execution information block 403 * ExpectedBtypes - Object types expected 404 * PackageIndex - Index of object within parent package (if 405 * applicable - ACPI_NOT_PACKAGE_ELEMENT 406 * otherwise) 407 * ReturnObjectPtr - Pointer to the object returned from the 408 * evaluation of a method or object 409 * 410 * RETURN: Status. AE_OK if repair was successful. 411 * 412 * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 413 * 414 ******************************************************************************/ 415 416 ACPI_STATUS 417 AcpiNsRepairNullElement ( 418 ACPI_EVALUATE_INFO *Info, 419 UINT32 ExpectedBtypes, 420 UINT32 PackageIndex, 421 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 422 { 423 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 424 ACPI_OPERAND_OBJECT *NewObject; 425 426 427 ACPI_FUNCTION_NAME (NsRepairNullElement); 428 429 430 /* No repair needed if return object is non-NULL */ 431 432 if (ReturnObject) 433 { 434 return (AE_OK); 435 } 436 437 /* 438 * Attempt to repair a NULL element of a Package object. This applies to 439 * predefined names that return a fixed-length package and each element 440 * is required. It does not apply to variable-length packages where NULL 441 * elements are allowed, especially at the end of the package. 442 */ 443 if (ExpectedBtypes & ACPI_RTYPE_INTEGER) 444 { 445 /* Need an Integer - create a zero-value integer */ 446 447 NewObject = AcpiUtCreateIntegerObject ((UINT64) 0); 448 } 449 else if (ExpectedBtypes & ACPI_RTYPE_STRING) 450 { 451 /* Need a String - create a NULL string */ 452 453 NewObject = AcpiUtCreateStringObject (0); 454 } 455 else if (ExpectedBtypes & ACPI_RTYPE_BUFFER) 456 { 457 /* Need a Buffer - create a zero-length buffer */ 458 459 NewObject = AcpiUtCreateBufferObject (0); 460 } 461 else 462 { 463 /* Error for all other expected types */ 464 465 return (AE_AML_OPERAND_TYPE); 466 } 467 468 if (!NewObject) 469 { 470 return (AE_NO_MEMORY); 471 } 472 473 /* Set the reference count according to the parent Package object */ 474 475 NewObject->Common.ReferenceCount = 476 Info->ParentPackage->Common.ReferenceCount; 477 478 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 479 "%s: Converted NULL package element to expected %s at index %u\n", 480 Info->FullPathname, AcpiUtGetObjectTypeName (NewObject), 481 PackageIndex)); 482 483 *ReturnObjectPtr = NewObject; 484 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 485 return (AE_OK); 486 } 487 488 489 /****************************************************************************** 490 * 491 * FUNCTION: AcpiNsRemoveNullElements 492 * 493 * PARAMETERS: Info - Method execution information block 494 * PackageType - An AcpiReturnPackageTypes value 495 * ObjDesc - A Package object 496 * 497 * RETURN: None. 498 * 499 * DESCRIPTION: Remove all NULL package elements from packages that contain 500 * a variable number of subpackages. For these types of 501 * packages, NULL elements can be safely removed. 502 * 503 *****************************************************************************/ 504 505 void 506 AcpiNsRemoveNullElements ( 507 ACPI_EVALUATE_INFO *Info, 508 UINT8 PackageType, 509 ACPI_OPERAND_OBJECT *ObjDesc) 510 { 511 ACPI_OPERAND_OBJECT **Source; 512 ACPI_OPERAND_OBJECT **Dest; 513 UINT32 Count; 514 UINT32 NewCount; 515 UINT32 i; 516 517 518 ACPI_FUNCTION_NAME (NsRemoveNullElements); 519 520 521 /* 522 * We can safely remove all NULL elements from these package types: 523 * PTYPE1_VAR packages contain a variable number of simple data types. 524 * PTYPE2 packages contain a variable number of subpackages. 525 */ 526 switch (PackageType) 527 { 528 case ACPI_PTYPE1_VAR: 529 case ACPI_PTYPE2: 530 case ACPI_PTYPE2_COUNT: 531 case ACPI_PTYPE2_PKG_COUNT: 532 case ACPI_PTYPE2_FIXED: 533 case ACPI_PTYPE2_MIN: 534 case ACPI_PTYPE2_REV_FIXED: 535 case ACPI_PTYPE2_FIX_VAR: 536 break; 537 538 default: 539 case ACPI_PTYPE2_VAR_VAR: 540 case ACPI_PTYPE1_FIXED: 541 case ACPI_PTYPE1_OPTION: 542 return; 543 } 544 545 Count = ObjDesc->Package.Count; 546 NewCount = Count; 547 548 Source = ObjDesc->Package.Elements; 549 Dest = Source; 550 551 /* Examine all elements of the package object, remove nulls */ 552 553 for (i = 0; i < Count; i++) 554 { 555 if (!*Source) 556 { 557 NewCount--; 558 } 559 else 560 { 561 *Dest = *Source; 562 Dest++; 563 } 564 565 Source++; 566 } 567 568 /* Update parent package if any null elements were removed */ 569 570 if (NewCount < Count) 571 { 572 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 573 "%s: Found and removed %u NULL elements\n", 574 Info->FullPathname, (Count - NewCount))); 575 576 /* NULL terminate list and update the package count */ 577 578 *Dest = NULL; 579 ObjDesc->Package.Count = NewCount; 580 } 581 } 582 583 584 /******************************************************************************* 585 * 586 * FUNCTION: AcpiNsWrapWithPackage 587 * 588 * PARAMETERS: Info - Method execution information block 589 * OriginalObject - Pointer to the object to repair. 590 * ObjDescPtr - The new package object is returned here 591 * 592 * RETURN: Status, new object in *ObjDescPtr 593 * 594 * DESCRIPTION: Repair a common problem with objects that are defined to 595 * return a variable-length Package of sub-objects. If there is 596 * only one sub-object, some BIOS code mistakenly simply declares 597 * the single object instead of a Package with one sub-object. 598 * This function attempts to repair this error by wrapping a 599 * Package object around the original object, creating the 600 * correct and expected Package with one sub-object. 601 * 602 * Names that can be repaired in this manner include: 603 * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 604 * _BCL, _DOD, _FIX, _Sx 605 * 606 ******************************************************************************/ 607 608 ACPI_STATUS 609 AcpiNsWrapWithPackage ( 610 ACPI_EVALUATE_INFO *Info, 611 ACPI_OPERAND_OBJECT *OriginalObject, 612 ACPI_OPERAND_OBJECT **ObjDescPtr) 613 { 614 ACPI_OPERAND_OBJECT *PkgObjDesc; 615 616 617 ACPI_FUNCTION_NAME (NsWrapWithPackage); 618 619 620 /* 621 * Create the new outer package and populate it. The new 622 * package will have a single element, the lone sub-object. 623 */ 624 PkgObjDesc = AcpiUtCreatePackageObject (1); 625 if (!PkgObjDesc) 626 { 627 return (AE_NO_MEMORY); 628 } 629 630 PkgObjDesc->Package.Elements[0] = OriginalObject; 631 632 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 633 "%s: Wrapped %s with expected Package object\n", 634 Info->FullPathname, AcpiUtGetObjectTypeName (OriginalObject))); 635 636 /* Return the new object in the object pointer */ 637 638 *ObjDescPtr = PkgObjDesc; 639 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 640 return (AE_OK); 641 } 642