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