1 /****************************************************************************** 2 * 3 * Module Name: nsrepair - Repair for objects returned by predefined methods 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 /* Unicode conversions */ 118 119 { "_MLS", ACPI_RTYPE_STRING, 1, 120 AcpiNsConvertToUnicode }, 121 { "_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 122 ACPI_NOT_PACKAGE_ELEMENT, 123 AcpiNsConvertToUnicode }, 124 { {0,0,0,0}, 0, 0, NULL } /* Table terminator */ 125 }; 126 127 128 /******************************************************************************* 129 * 130 * FUNCTION: AcpiNsSimpleRepair 131 * 132 * PARAMETERS: Info - Method execution information block 133 * ExpectedBtypes - Object types expected 134 * PackageIndex - Index of object within parent package (if 135 * applicable - ACPI_NOT_PACKAGE_ELEMENT 136 * otherwise) 137 * ReturnObjectPtr - Pointer to the object returned from the 138 * evaluation of a method or object 139 * 140 * RETURN: Status. AE_OK if repair was successful. 141 * 142 * DESCRIPTION: Attempt to repair/convert a return object of a type that was 143 * not expected. 144 * 145 ******************************************************************************/ 146 147 ACPI_STATUS 148 AcpiNsSimpleRepair ( 149 ACPI_EVALUATE_INFO *Info, 150 UINT32 ExpectedBtypes, 151 UINT32 PackageIndex, 152 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 153 { 154 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 155 ACPI_OPERAND_OBJECT *NewObject = NULL; 156 ACPI_STATUS Status; 157 const ACPI_SIMPLE_REPAIR_INFO *Predefined; 158 159 160 ACPI_FUNCTION_NAME (NsSimpleRepair); 161 162 163 /* 164 * Special repairs for certain names that are in the repair table. 165 * Check if this name is in the list of repairable names. 166 */ 167 Predefined = AcpiNsMatchSimpleRepair (Info->Node, 168 Info->ReturnBtype, PackageIndex); 169 if (Predefined) 170 { 171 if (!ReturnObject) 172 { 173 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 174 ACPI_WARN_ALWAYS, "Missing expected return value")); 175 } 176 177 Status = Predefined->ObjectConverter (ReturnObject, &NewObject); 178 if (ACPI_FAILURE (Status)) 179 { 180 /* A fatal error occurred during a conversion */ 181 182 ACPI_EXCEPTION ((AE_INFO, Status, 183 "During return object analysis")); 184 return (Status); 185 } 186 if (NewObject) 187 { 188 goto ObjectRepaired; 189 } 190 } 191 192 /* 193 * Do not perform simple object repair unless the return type is not 194 * expected. 195 */ 196 if (Info->ReturnBtype & ExpectedBtypes) 197 { 198 return (AE_OK); 199 } 200 201 /* 202 * At this point, we know that the type of the returned object was not 203 * one of the expected types for this predefined name. Attempt to 204 * repair the object by converting it to one of the expected object 205 * types for this predefined name. 206 */ 207 208 /* 209 * If there is no return value, check if we require a return value for 210 * this predefined name. Either one return value is expected, or none, 211 * for both methods and other objects. 212 * 213 * Try to fix if there was no return object. Warning if failed to fix. 214 */ 215 if (!ReturnObject) 216 { 217 if (ExpectedBtypes && (!(ExpectedBtypes & ACPI_RTYPE_NONE))) 218 { 219 if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) 220 { 221 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 222 ACPI_WARN_ALWAYS, "Found unexpected NULL package element")); 223 224 Status = AcpiNsRepairNullElement (Info, ExpectedBtypes, 225 PackageIndex, ReturnObjectPtr); 226 if (ACPI_SUCCESS (Status)) 227 { 228 return (AE_OK); /* Repair was successful */ 229 } 230 } 231 else 232 { 233 ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, 234 ACPI_WARN_ALWAYS, "Missing expected return value")); 235 } 236 237 return (AE_AML_NO_RETURN_VALUE); 238 } 239 } 240 241 if (ExpectedBtypes & ACPI_RTYPE_INTEGER) 242 { 243 Status = AcpiNsConvertToInteger (ReturnObject, &NewObject); 244 if (ACPI_SUCCESS (Status)) 245 { 246 goto ObjectRepaired; 247 } 248 } 249 if (ExpectedBtypes & ACPI_RTYPE_STRING) 250 { 251 Status = AcpiNsConvertToString (ReturnObject, &NewObject); 252 if (ACPI_SUCCESS (Status)) 253 { 254 goto ObjectRepaired; 255 } 256 } 257 if (ExpectedBtypes & ACPI_RTYPE_BUFFER) 258 { 259 Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject); 260 if (ACPI_SUCCESS (Status)) 261 { 262 goto ObjectRepaired; 263 } 264 } 265 if (ExpectedBtypes & ACPI_RTYPE_PACKAGE) 266 { 267 /* 268 * A package is expected. We will wrap the existing object with a 269 * new package object. It is often the case that if a variable-length 270 * package is required, but there is only a single object needed, the 271 * BIOS will return that object instead of wrapping it with a Package 272 * object. Note: after the wrapping, the package will be validated 273 * for correct contents (expected object type or types). 274 */ 275 Status = AcpiNsWrapWithPackage (Info, ReturnObject, &NewObject); 276 if (ACPI_SUCCESS (Status)) 277 { 278 /* 279 * The original object just had its reference count 280 * incremented for being inserted into the new package. 281 */ 282 *ReturnObjectPtr = NewObject; /* New Package object */ 283 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 284 return (AE_OK); 285 } 286 } 287 288 /* We cannot repair this object */ 289 290 return (AE_AML_OPERAND_TYPE); 291 292 293 ObjectRepaired: 294 295 /* Object was successfully repaired */ 296 297 if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) 298 { 299 /* 300 * The original object is a package element. We need to 301 * decrement the reference count of the original object, 302 * for removing it from the package. 303 * 304 * However, if the original object was just wrapped with a 305 * package object as part of the repair, we don't need to 306 * change the reference count. 307 */ 308 if (!(Info->ReturnFlags & ACPI_OBJECT_WRAPPED)) 309 { 310 NewObject->Common.ReferenceCount = 311 ReturnObject->Common.ReferenceCount; 312 313 if (ReturnObject->Common.ReferenceCount > 1) 314 { 315 ReturnObject->Common.ReferenceCount--; 316 } 317 } 318 319 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 320 "%s: Converted %s to expected %s at Package index %u\n", 321 Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), 322 AcpiUtGetObjectTypeName (NewObject), PackageIndex)); 323 } 324 else 325 { 326 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 327 "%s: Converted %s to expected %s\n", 328 Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), 329 AcpiUtGetObjectTypeName (NewObject))); 330 } 331 332 /* Delete old object, install the new return object */ 333 334 AcpiUtRemoveReference (ReturnObject); 335 *ReturnObjectPtr = NewObject; 336 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 337 return (AE_OK); 338 } 339 340 341 /****************************************************************************** 342 * 343 * FUNCTION: AcpiNsMatchSimpleRepair 344 * 345 * PARAMETERS: Node - Namespace node for the method/object 346 * ReturnBtype - Object type that was returned 347 * PackageIndex - Index of object within parent package (if 348 * applicable - ACPI_NOT_PACKAGE_ELEMENT 349 * otherwise) 350 * 351 * RETURN: Pointer to entry in repair table. NULL indicates not found. 352 * 353 * DESCRIPTION: Check an object name against the repairable object list. 354 * 355 *****************************************************************************/ 356 357 static const ACPI_SIMPLE_REPAIR_INFO * 358 AcpiNsMatchSimpleRepair ( 359 ACPI_NAMESPACE_NODE *Node, 360 UINT32 ReturnBtype, 361 UINT32 PackageIndex) 362 { 363 const ACPI_SIMPLE_REPAIR_INFO *ThisName; 364 365 366 /* Search info table for a repairable predefined method/object name */ 367 368 ThisName = AcpiObjectRepairInfo; 369 while (ThisName->ObjectConverter) 370 { 371 if (ACPI_COMPARE_NAME (Node->Name.Ascii, ThisName->Name)) 372 { 373 /* Check if we can actually repair this name/type combination */ 374 375 if ((ReturnBtype & ThisName->UnexpectedBtypes) && 376 (PackageIndex == ThisName->PackageIndex)) 377 { 378 return (ThisName); 379 } 380 381 return (NULL); 382 } 383 384 ThisName++; 385 } 386 387 return (NULL); /* Name was not found in the repair table */ 388 } 389 390 391 /******************************************************************************* 392 * 393 * FUNCTION: AcpiNsRepairNullElement 394 * 395 * PARAMETERS: Info - Method execution information block 396 * ExpectedBtypes - Object types expected 397 * PackageIndex - Index of object within parent package (if 398 * applicable - ACPI_NOT_PACKAGE_ELEMENT 399 * otherwise) 400 * ReturnObjectPtr - Pointer to the object returned from the 401 * evaluation of a method or object 402 * 403 * RETURN: Status. AE_OK if repair was successful. 404 * 405 * DESCRIPTION: Attempt to repair a NULL element of a returned Package object. 406 * 407 ******************************************************************************/ 408 409 ACPI_STATUS 410 AcpiNsRepairNullElement ( 411 ACPI_EVALUATE_INFO *Info, 412 UINT32 ExpectedBtypes, 413 UINT32 PackageIndex, 414 ACPI_OPERAND_OBJECT **ReturnObjectPtr) 415 { 416 ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; 417 ACPI_OPERAND_OBJECT *NewObject; 418 419 420 ACPI_FUNCTION_NAME (NsRepairNullElement); 421 422 423 /* No repair needed if return object is non-NULL */ 424 425 if (ReturnObject) 426 { 427 return (AE_OK); 428 } 429 430 /* 431 * Attempt to repair a NULL element of a Package object. This applies to 432 * predefined names that return a fixed-length package and each element 433 * is required. It does not apply to variable-length packages where NULL 434 * elements are allowed, especially at the end of the package. 435 */ 436 if (ExpectedBtypes & ACPI_RTYPE_INTEGER) 437 { 438 /* Need an Integer - create a zero-value integer */ 439 440 NewObject = AcpiUtCreateIntegerObject ((UINT64) 0); 441 } 442 else if (ExpectedBtypes & ACPI_RTYPE_STRING) 443 { 444 /* Need a String - create a NULL string */ 445 446 NewObject = AcpiUtCreateStringObject (0); 447 } 448 else if (ExpectedBtypes & ACPI_RTYPE_BUFFER) 449 { 450 /* Need a Buffer - create a zero-length buffer */ 451 452 NewObject = AcpiUtCreateBufferObject (0); 453 } 454 else 455 { 456 /* Error for all other expected types */ 457 458 return (AE_AML_OPERAND_TYPE); 459 } 460 461 if (!NewObject) 462 { 463 return (AE_NO_MEMORY); 464 } 465 466 /* Set the reference count according to the parent Package object */ 467 468 NewObject->Common.ReferenceCount = 469 Info->ParentPackage->Common.ReferenceCount; 470 471 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 472 "%s: Converted NULL package element to expected %s at index %u\n", 473 Info->FullPathname, AcpiUtGetObjectTypeName (NewObject), 474 PackageIndex)); 475 476 *ReturnObjectPtr = NewObject; 477 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; 478 return (AE_OK); 479 } 480 481 482 /****************************************************************************** 483 * 484 * FUNCTION: AcpiNsRemoveNullElements 485 * 486 * PARAMETERS: Info - Method execution information block 487 * PackageType - An AcpiReturnPackageTypes value 488 * ObjDesc - A Package object 489 * 490 * RETURN: None. 491 * 492 * DESCRIPTION: Remove all NULL package elements from packages that contain 493 * a variable number of subpackages. For these types of 494 * packages, NULL elements can be safely removed. 495 * 496 *****************************************************************************/ 497 498 void 499 AcpiNsRemoveNullElements ( 500 ACPI_EVALUATE_INFO *Info, 501 UINT8 PackageType, 502 ACPI_OPERAND_OBJECT *ObjDesc) 503 { 504 ACPI_OPERAND_OBJECT **Source; 505 ACPI_OPERAND_OBJECT **Dest; 506 UINT32 Count; 507 UINT32 NewCount; 508 UINT32 i; 509 510 511 ACPI_FUNCTION_NAME (NsRemoveNullElements); 512 513 514 /* 515 * We can safely remove all NULL elements from these package types: 516 * PTYPE1_VAR packages contain a variable number of simple data types. 517 * PTYPE2 packages contain a variable number of subpackages. 518 */ 519 switch (PackageType) 520 { 521 case ACPI_PTYPE1_VAR: 522 case ACPI_PTYPE2: 523 case ACPI_PTYPE2_COUNT: 524 case ACPI_PTYPE2_PKG_COUNT: 525 case ACPI_PTYPE2_FIXED: 526 case ACPI_PTYPE2_MIN: 527 case ACPI_PTYPE2_REV_FIXED: 528 case ACPI_PTYPE2_FIX_VAR: 529 break; 530 531 default: 532 case ACPI_PTYPE2_VAR_VAR: 533 case ACPI_PTYPE1_FIXED: 534 case ACPI_PTYPE1_OPTION: 535 return; 536 } 537 538 Count = ObjDesc->Package.Count; 539 NewCount = Count; 540 541 Source = ObjDesc->Package.Elements; 542 Dest = Source; 543 544 /* Examine all elements of the package object, remove nulls */ 545 546 for (i = 0; i < Count; i++) 547 { 548 if (!*Source) 549 { 550 NewCount--; 551 } 552 else 553 { 554 *Dest = *Source; 555 Dest++; 556 } 557 558 Source++; 559 } 560 561 /* Update parent package if any null elements were removed */ 562 563 if (NewCount < Count) 564 { 565 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 566 "%s: Found and removed %u NULL elements\n", 567 Info->FullPathname, (Count - NewCount))); 568 569 /* NULL terminate list and update the package count */ 570 571 *Dest = NULL; 572 ObjDesc->Package.Count = NewCount; 573 } 574 } 575 576 577 /******************************************************************************* 578 * 579 * FUNCTION: AcpiNsWrapWithPackage 580 * 581 * PARAMETERS: Info - Method execution information block 582 * OriginalObject - Pointer to the object to repair. 583 * ObjDescPtr - The new package object is returned here 584 * 585 * RETURN: Status, new object in *ObjDescPtr 586 * 587 * DESCRIPTION: Repair a common problem with objects that are defined to 588 * return a variable-length Package of sub-objects. If there is 589 * only one sub-object, some BIOS code mistakenly simply declares 590 * the single object instead of a Package with one sub-object. 591 * This function attempts to repair this error by wrapping a 592 * Package object around the original object, creating the 593 * correct and expected Package with one sub-object. 594 * 595 * Names that can be repaired in this manner include: 596 * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, 597 * _BCL, _DOD, _FIX, _Sx 598 * 599 ******************************************************************************/ 600 601 ACPI_STATUS 602 AcpiNsWrapWithPackage ( 603 ACPI_EVALUATE_INFO *Info, 604 ACPI_OPERAND_OBJECT *OriginalObject, 605 ACPI_OPERAND_OBJECT **ObjDescPtr) 606 { 607 ACPI_OPERAND_OBJECT *PkgObjDesc; 608 609 610 ACPI_FUNCTION_NAME (NsWrapWithPackage); 611 612 613 /* 614 * Create the new outer package and populate it. The new 615 * package will have a single element, the lone sub-object. 616 */ 617 PkgObjDesc = AcpiUtCreatePackageObject (1); 618 if (!PkgObjDesc) 619 { 620 return (AE_NO_MEMORY); 621 } 622 623 PkgObjDesc->Package.Elements[0] = OriginalObject; 624 625 ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, 626 "%s: Wrapped %s with expected Package object\n", 627 Info->FullPathname, AcpiUtGetObjectTypeName (OriginalObject))); 628 629 /* Return the new object in the object pointer */ 630 631 *ObjDescPtr = PkgObjDesc; 632 Info->ReturnFlags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; 633 return (AE_OK); 634 } 635