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