diff options
Diffstat (limited to 'namespace')
-rw-r--r-- | namespace/nsaccess.c | 2 | ||||
-rw-r--r-- | namespace/nsdump.c | 2 | ||||
-rw-r--r-- | namespace/nseval.c | 20 | ||||
-rw-r--r-- | namespace/nsnames.c | 2 | ||||
-rw-r--r-- | namespace/nspredef.c | 93 | ||||
-rw-r--r-- | namespace/nsrepair.c | 478 | ||||
-rw-r--r-- | namespace/nsrepair2.c | 209 | ||||
-rw-r--r-- | namespace/nsutils.c | 63 | ||||
-rw-r--r-- | namespace/nsxfeval.c | 10 | ||||
-rw-r--r-- | namespace/nsxfname.c | 10 | ||||
-rw-r--r-- | namespace/nsxfobj.c | 12 |
11 files changed, 659 insertions, 242 deletions
diff --git a/namespace/nsaccess.c b/namespace/nsaccess.c index 172b26d3abcd..2bc7d8d71182 100644 --- a/namespace/nsaccess.c +++ b/namespace/nsaccess.c @@ -251,7 +251,7 @@ AcpiNsRootInitialize ( /* Mark this as a very SPECIAL method */ ObjDesc->Method.MethodFlags = AML_METHOD_INTERNAL_ONLY; - ObjDesc->Method.Implementation = AcpiUtOsiImplementation; + ObjDesc->Method.Extra.Implementation = AcpiUtOsiImplementation; #endif break; diff --git a/namespace/nsdump.c b/namespace/nsdump.c index 96510564ee4a..d799f7c64ce9 100644 --- a/namespace/nsdump.c +++ b/namespace/nsdump.c @@ -286,7 +286,7 @@ AcpiNsDumpOneObject ( return (AE_OK); } - ThisNode = AcpiNsMapHandleToNode (ObjHandle); + ThisNode = AcpiNsValidateHandle (ObjHandle); if (!ThisNode) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n", diff --git a/namespace/nseval.c b/namespace/nseval.c index e5d4cf327e53..07af96ed93dc 100644 --- a/namespace/nseval.c +++ b/namespace/nseval.c @@ -477,6 +477,19 @@ AcpiNsExecModuleCode ( MethodObj->Method.NextObject); Type = AcpiNsGetType (ParentNode); + /* + * Get the region handler and save it in the method object. We may need + * this if an operation region declaration causes a _REG method to be run. + * + * We can't do this in AcpiPsLinkModuleCode because + * AcpiGbl_RootNode->Object is NULL at PASS1. + */ + if ((Type == ACPI_TYPE_DEVICE) && ParentNode->Object) + { + MethodObj->Method.Extra.Handler = + ParentNode->Object->Device.Handler; + } + /* Must clear NextObject (AcpiNsAttachObject needs the field) */ MethodObj->Method.NextObject = NULL; @@ -513,6 +526,13 @@ AcpiNsExecModuleCode ( ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Executed module-level code at %p\n", MethodObj->Method.AmlStart)); + /* Delete a possible implicit return value (in slack mode) */ + + if (Info->ReturnObject) + { + AcpiUtRemoveReference (Info->ReturnObject); + } + /* Detach the temporary method object */ AcpiNsDetachObject (ParentNode); diff --git a/namespace/nsnames.c b/namespace/nsnames.c index 0dd148fa7ca1..c00a4457b2a8 100644 --- a/namespace/nsnames.c +++ b/namespace/nsnames.c @@ -337,7 +337,7 @@ AcpiNsHandleToPathname ( ACPI_FUNCTION_TRACE_PTR (NsHandleToPathname, TargetHandle); - Node = AcpiNsMapHandleToNode (TargetHandle); + Node = AcpiNsValidateHandle (TargetHandle); if (!Node) { return_ACPI_STATUS (AE_BAD_PARAMETER); diff --git a/namespace/nspredef.c b/namespace/nspredef.c index ae4e17d43826..d979c43e93f9 100644 --- a/namespace/nspredef.c +++ b/namespace/nspredef.c @@ -313,31 +313,40 @@ AcpiNsCheckPredefinedNames ( Data->Pathname = Pathname; /* - * Check that the type of the return object is what is expected for - * this predefined name + * Check that the type of the main return object is what is expected + * for this predefined name */ Status = AcpiNsCheckObjectType (Data, ReturnObjectPtr, Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); if (ACPI_FAILURE (Status)) { - goto CheckValidationStatus; + goto Exit; } - /* For returned Package objects, check the type of all sub-objects */ - - if (ReturnObject->Common.Type == ACPI_TYPE_PACKAGE) + /* + * For returned Package objects, check the type of all sub-objects. + * Note: Package may have been newly created by call above. + */ + if ((*ReturnObjectPtr)->Common.Type == ACPI_TYPE_PACKAGE) { Status = AcpiNsCheckPackage (Data, ReturnObjectPtr); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } } /* - * Perform additional, more complicated repairs on a per-name - * basis. + * The return object was OK, or it was successfully repaired above. + * Now make some additional checks such as verifying that package + * objects are sorted correctly (if required) or buffer objects have + * the correct data width (bytes vs. dwords). These repairs are + * performed on a per-name basis, i.e., the code is specific to + * particular predefined names. */ Status = AcpiNsComplexRepairs (Data, Node, Status, ReturnObjectPtr); - -CheckValidationStatus: +Exit: /* * If the object validation failed or if we successfully repaired one * or more objects, mark the parent node to suppress further warning @@ -349,7 +358,6 @@ CheckValidationStatus: } ACPI_FREE (Data); - Cleanup: ACPI_FREE (Pathname); return (Status); @@ -544,6 +552,12 @@ AcpiNsCheckPackage ( "%s Validating return Package of Type %X, Count %X\n", Data->Pathname, Package->RetInfo.Type, ReturnObject->Package.Count)); + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + AcpiNsRemoveNullElements (Data, Package->RetInfo.Type, ReturnObject); + /* Extract package count and elements array */ Elements = ReturnObject->Package.Elements; @@ -582,9 +596,10 @@ AcpiNsCheckPackage ( } else if (Count > ExpectedCount) { - ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Return Package is larger than needed - " - "found %u, expected %u", Count, ExpectedCount)); + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + Data->Pathname, Count, ExpectedCount)); } /* Validate all elements of the returned package */ @@ -800,56 +815,20 @@ AcpiNsCheckPackageList ( ACPI_OPERAND_OBJECT *SubPackage; ACPI_OPERAND_OBJECT **SubElements; ACPI_STATUS Status; - BOOLEAN NonTrailingNull = FALSE; UINT32 ExpectedCount; UINT32 i; UINT32 j; - /* Validate each sub-Package in the parent Package */ - + /* + * Validate each sub-Package in the parent Package + * + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to AcpiNsRemoveNullElements. + */ for (i = 0; i < Count; i++) { - /* - * Handling for NULL package elements. For now, we will simply allow - * a parent package with trailing NULL elements. This can happen if - * the package was defined to be longer than the initializer list. - * This is legal as per the ACPI specification. It is often used - * to allow for dynamic initialization of a Package. - * - * A future enhancement may be to simply truncate the package to - * remove the trailing NULL elements. - */ - if (!(*Elements)) - { - if (!NonTrailingNull) - { - /* Ensure the remaining elements are all NULL */ - - for (j = 1; j < (Count - i + 1); j++) - { - if (Elements[j]) - { - NonTrailingNull = TRUE; - } - } - - if (!NonTrailingNull) - { - /* Ignore the trailing NULL elements */ - - return (AE_OK); - } - } - - /* There are trailing non-null elements, issue warning */ - - ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Found NULL element at package index %u", i)); - Elements++; - continue; - } - SubPackage = *Elements; SubElements = SubPackage->Package.Elements; diff --git a/namespace/nsrepair.c b/namespace/nsrepair.c index 3e3a23125d91..5c402df36b56 100644 --- a/namespace/nsrepair.c +++ b/namespace/nsrepair.c @@ -119,7 +119,6 @@ #include "accommon.h" #include "acnamesp.h" #include "acinterp.h" -#include "acpredef.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME ("nsrepair") @@ -127,6 +126,54 @@ /******************************************************************************* * + * This module attempts to repair or convert objects returned by the + * predefined methods to an object type that is expected, as per the ACPI + * specification. The need for this code is dictated by the many machines that + * return incorrect types for the standard predefined methods. Performing these + * conversions here, in one place, eliminates the need for individual ACPI + * device drivers to do the same. Note: Most of these conversions are different + * than the internal object conversion routines used for implicit object + * conversion. + * + * The following conversions can be performed as necessary: + * + * Integer -> String + * Integer -> Buffer + * String -> Integer + * String -> Buffer + * Buffer -> Integer + * Buffer -> String + * Buffer -> Package of Integers + * Package -> Package of one Package + * + ******************************************************************************/ + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +static ACPI_STATUS +AcpiNsConvertToPackage ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + + +/******************************************************************************* + * * FUNCTION: AcpiNsRepairObject * * PARAMETERS: Data - Pointer to validation data structure @@ -153,35 +200,230 @@ AcpiNsRepairObject ( { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_OPERAND_OBJECT *NewObject; - ACPI_SIZE Length; ACPI_STATUS Status; + ACPI_FUNCTION_NAME (NsRepairObject); + + /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to - * repair the object. Only a limited number of repairs are possible. + * repair the object by converting it to one of the expected object + * types for this predefined name. + */ + if (ExpectedBtypes & ACPI_RTYPE_INTEGER) + { + Status = AcpiNsConvertToInteger (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_STRING) + { + Status = AcpiNsConvertToString (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_BUFFER) + { + Status = AcpiNsConvertToBuffer (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + if (ExpectedBtypes & ACPI_RTYPE_PACKAGE) + { + Status = AcpiNsConvertToPackage (ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + goto ObjectRepaired; + } + } + + /* We cannot repair this object */ + + return (AE_AML_OPERAND_TYPE); + + +ObjectRepaired: + + /* Object was successfully repaired */ + + /* + * If the original object is a package element, we need to: + * 1. Set the reference count of the new object to match the + * reference count of the old object. + * 2. Decrement the reference count of the original object. */ - switch (ReturnObject->Common.Type) + if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) + { + NewObject->Common.ReferenceCount = + ReturnObject->Common.ReferenceCount; + + if (ReturnObject->Common.ReferenceCount > 1) + { + ReturnObject->Common.ReferenceCount--; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s at index %u\n", + Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject), PackageIndex)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s\n", + Data->Pathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject))); + } + + /* Delete old object, install the new return object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = NewObject; + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToInteger + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + UINT64 Value = 0; + UINT32 i; + + + switch (OriginalObject->Common.Type) { + case ACPI_TYPE_STRING: + + /* String-to-Integer conversion */ + + Status = AcpiUtStrtoul64 (OriginalObject->String.Pointer, + ACPI_ANY_BASE, &Value); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + case ACPI_TYPE_BUFFER: - /* Does the method/object legally return a string? */ + /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */ - if (!(ExpectedBtypes & ACPI_RTYPE_STRING)) + if (OriginalObject->Buffer.Length > 8) { return (AE_AML_OPERAND_TYPE); } + /* Extract each buffer byte to create the integer */ + + for (i = 0; i < OriginalObject->Buffer.Length; i++) + { + Value |= ((UINT64) OriginalObject->Buffer.Pointer[i] << (i * 8)); + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + NewObject = AcpiUtCreateIntegerObject (Value); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToString + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_SIZE Length; + ACPI_STATUS Status; + + + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + /* + * Integer-to-String conversion. Commonly, convert + * an integer of value 0 to a NULL string. The last element of + * _BIF and _BIX packages occasionally need this fix. + */ + if (OriginalObject->Integer.Value == 0) + { + /* Allocate a new NULL string object */ + + NewObject = AcpiUtCreateStringObject (0); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + } + else + { + Status = AcpiExConvertToString (OriginalObject, &NewObject, + ACPI_IMPLICIT_CONVERT_HEX); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + break; + + case ACPI_TYPE_BUFFER: /* - * Have a Buffer, expected a String, convert. Use a ToString + * Buffer-to-String conversion. Use a ToString * conversion, no transform performed on the buffer data. The best * example of this is the _BIF method, where the string data from * the battery is often (incorrectly) returned as buffer object(s). */ Length = 0; - while ((Length < ReturnObject->Buffer.Length) && - (ReturnObject->Buffer.Pointer[Length])) + while ((Length < OriginalObject->Buffer.Length) && + (OriginalObject->Buffer.Pointer[Length])) { Length++; } @@ -199,101 +441,188 @@ AcpiNsRepairObject ( * terminated at Length+1. */ ACPI_MEMCPY (NewObject->String.Pointer, - ReturnObject->Buffer.Pointer, Length); + OriginalObject->Buffer.Pointer, Length); break; + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToBuffer + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT **Elements; + UINT32 *DwordBuffer; + UINT32 Count; + UINT32 i; + + switch (OriginalObject->Common.Type) + { case ACPI_TYPE_INTEGER: + /* + * Integer-to-Buffer conversion. + * Convert the Integer to a packed-byte buffer. _MAT and other + * objects need this sometimes, if a read has been performed on a + * Field object that is less than or equal to the global integer + * size (32 or 64 bits). + */ + Status = AcpiExConvertToBuffer (OriginalObject, &NewObject); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_STRING: - /* 1) Does the method/object legally return a buffer? */ + /* String-to-Buffer conversion. Simple data copy */ - if (ExpectedBtypes & ACPI_RTYPE_BUFFER) + NewObject = AcpiUtCreateBufferObject (OriginalObject->String.Length); + if (!NewObject) { - /* - * Convert the Integer to a packed-byte buffer. _MAT needs - * this sometimes, if a read has been performed on a Field - * object that is less than or equal to the global integer - * size (32 or 64 bits). - */ - Status = AcpiExConvertToBuffer (ReturnObject, &NewObject); - if (ACPI_FAILURE (Status)) - { - return (Status); - } + return (AE_NO_MEMORY); } - /* 2) Does the method/object legally return a string? */ + ACPI_MEMCPY (NewObject->Buffer.Pointer, + OriginalObject->String.Pointer, OriginalObject->String.Length); + break; + + case ACPI_TYPE_PACKAGE: + /* + * This case is often seen for predefined names that must return a + * Buffer object with multiple DWORD integers within. For example, + * _FDE and _GTM. The Package can be converted to a Buffer. + */ + + /* All elements of the Package must be integers */ + + Elements = OriginalObject->Package.Elements; + Count = OriginalObject->Package.Count; - else if (ExpectedBtypes & ACPI_RTYPE_STRING) + for (i = 0; i < Count; i++) { - /* - * The only supported Integer-to-String conversion is to convert - * an integer of value 0 to a NULL string. The last element of - * _BIF and _BIX packages occasionally need this fix. - */ - if (ReturnObject->Integer.Value != 0) + if ((!*Elements) || + ((*Elements)->Common.Type != ACPI_TYPE_INTEGER)) { return (AE_AML_OPERAND_TYPE); } + Elements++; + } - /* Allocate a new NULL string object */ + /* Create the new buffer object to replace the Package */ - NewObject = AcpiUtCreateStringObject (0); - if (!NewObject) - { - return (AE_NO_MEMORY); - } - } - else + NewObject = AcpiUtCreateBufferObject (ACPI_MUL_4 (Count)); + if (!NewObject) { - return (AE_AML_OPERAND_TYPE); + return (AE_NO_MEMORY); } - break; + /* Copy the package elements (integers) to the buffer as DWORDs */ - default: + Elements = OriginalObject->Package.Elements; + DwordBuffer = ACPI_CAST_PTR (UINT32, NewObject->Buffer.Pointer); - /* We cannot repair this object */ + for (i = 0; i < Count; i++) + { + *DwordBuffer = (UINT32) (*Elements)->Integer.Value; + DwordBuffer++; + Elements++; + } + break; + default: return (AE_AML_OPERAND_TYPE); } - /* Object was successfully repaired */ + *ReturnObject = NewObject; + return (AE_OK); +} - /* - * If the original object is a package element, we need to: - * 1. Set the reference count of the new object to match the - * reference count of the old object. - * 2. Decrement the reference count of the original object. - */ - if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToPackage + * + * PARAMETERS: OriginalObject - Object to be converted + * ReturnObject - Where the new converted object is returned + * + * RETURN: Status. AE_OK if conversion was successful. + * + * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of + * the buffer is converted to a single integer package element. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsConvertToPackage ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + ACPI_OPERAND_OBJECT **Elements; + UINT32 Length; + UINT8 *Buffer; + + + switch (OriginalObject->Common.Type) { - NewObject->Common.ReferenceCount = - ReturnObject->Common.ReferenceCount; + case ACPI_TYPE_BUFFER: - if (ReturnObject->Common.ReferenceCount > 1) + /* Buffer-to-Package conversion */ + + Length = OriginalObject->Buffer.Length; + NewObject = AcpiUtCreatePackageObject (Length); + if (!NewObject) { - ReturnObject->Common.ReferenceCount--; + return (AE_NO_MEMORY); } - ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Converted %s to expected %s at index %u", - AcpiUtGetObjectTypeName (ReturnObject), - AcpiUtGetObjectTypeName (NewObject), PackageIndex)); - } - else - { - ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Converted %s to expected %s", - AcpiUtGetObjectTypeName (ReturnObject), - AcpiUtGetObjectTypeName (NewObject))); - } + /* Convert each buffer byte to an integer package element */ - /* Delete old object, install the new return object */ + Elements = NewObject->Package.Elements; + Buffer = OriginalObject->Buffer.Pointer; - AcpiUtRemoveReference (ReturnObject); - *ReturnObjectPtr = NewObject; - Data->Flags |= ACPI_OBJECT_REPAIRED; + while (Length--) + { + *Elements = AcpiUtCreateIntegerObject ((UINT64) *Buffer); + if (!*Elements) + { + AcpiUtRemoveReference (NewObject); + return (AE_NO_MEMORY); + } + Elements++; + Buffer++; + } + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + *ReturnObject = NewObject; return (AE_OK); } @@ -330,6 +659,9 @@ AcpiNsRepairPackageList ( ACPI_OPERAND_OBJECT *PkgObjDesc; + ACPI_FUNCTION_NAME (NsRepairPackageList); + + /* * Create the new outer package and populate it. The new package will * have a single element, the lone subpackage. @@ -347,8 +679,8 @@ AcpiNsRepairPackageList ( *ObjDescPtr = PkgObjDesc; Data->Flags |= ACPI_OBJECT_REPAIRED; - ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Repaired Incorrectly formed Package")); + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Repaired incorrectly formed Package\n", Data->Pathname)); return (AE_OK); } diff --git a/namespace/nsrepair2.c b/namespace/nsrepair2.c index d248906182b8..c08028452b4c 100644 --- a/namespace/nsrepair2.c +++ b/namespace/nsrepair2.c @@ -119,6 +119,7 @@ #include "acpi.h" #include "accommon.h" #include "acnamesp.h" +#include "acpredef.h" #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME ("nsrepair2") @@ -153,6 +154,11 @@ AcpiNsRepair_ALR ( ACPI_OPERAND_OBJECT **ReturnObjectPtr); static ACPI_STATUS +AcpiNsRepair_FDE ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS AcpiNsRepair_PSS ( ACPI_PREDEFINED_DATA *Data, ACPI_OPERAND_OBJECT **ReturnObjectPtr); @@ -172,10 +178,6 @@ AcpiNsCheckSortedList ( char *SortKeyName); static ACPI_STATUS -AcpiNsRemoveNullElements ( - ACPI_OPERAND_OBJECT *Package); - -static ACPI_STATUS AcpiNsSortList ( ACPI_OPERAND_OBJECT **Elements, UINT32 Count, @@ -192,19 +194,30 @@ AcpiNsSortList ( * This table contains the names of the predefined methods for which we can * perform more complex repairs. * - * _ALR: Sort the list ascending by AmbientIlluminance if necessary - * _PSS: Sort the list descending by Power if necessary - * _TSS: Sort the list descending by Power if necessary + * As necessary: + * + * _ALR: Sort the list ascending by AmbientIlluminance + * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs + * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs + * _PSS: Sort the list descending by Power + * _TSS: Sort the list descending by Power */ static const ACPI_REPAIR_INFO AcpiNsRepairableNames[] = { {"_ALR", AcpiNsRepair_ALR}, + {"_FDE", AcpiNsRepair_FDE}, + {"_GTM", AcpiNsRepair_FDE}, /* _GTM has same repair as _FDE */ {"_PSS", AcpiNsRepair_PSS}, {"_TSS", AcpiNsRepair_TSS}, - {{0,0,0,0}, NULL} /* Table terminator */ + {{0,0,0,0}, NULL} /* Table terminator */ }; +#define ACPI_FDE_FIELD_COUNT 5 +#define ACPI_FDE_BYTE_BUFFER_SIZE 5 +#define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (UINT32)) + + /****************************************************************************** * * FUNCTION: AcpiNsComplexRepairs @@ -215,7 +228,7 @@ static const ACPI_REPAIR_INFO AcpiNsRepairableNames[] = * ReturnObjectPtr - Pointer to the object returned from the * evaluation of a method or object * - * RETURN: Status. AE_OK if repair was successful. If name is not + * RETURN: Status. AE_OK if repair was successful. If name is not * matched, ValidateStatus is returned. * * DESCRIPTION: Attempt to repair/convert a return object of a type that was @@ -315,6 +328,99 @@ AcpiNsRepair_ALR ( /****************************************************************************** * + * FUNCTION: AcpiNsRepair_FDE + * + * PARAMETERS: Data - Pointer to validation data structure + * ReturnObjectPtr - Pointer to the object returned from the + * evaluation of a method or object + * + * RETURN: Status. AE_OK if object is OK or was repaired successfully + * + * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return + * value is a Buffer of 5 DWORDs. This function repairs a common + * problem where the return value is a Buffer of BYTEs, not + * DWORDs. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_FDE ( + ACPI_PREDEFINED_DATA *Data, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *BufferObject; + UINT8 *ByteBuffer; + UINT32 *DwordBuffer; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsRepair_FDE); + + + switch (ReturnObject->Common.Type) + { + case ACPI_TYPE_BUFFER: + + /* This is the expected type. Length should be (at least) 5 DWORDs */ + + if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE) + { + return (AE_OK); + } + + /* We can only repair if we have exactly 5 BYTEs */ + + if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, + "Incorrect return buffer length %u, expected %u", + ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE)); + + return (AE_AML_OPERAND_TYPE); + } + + /* Create the new (larger) buffer object */ + + BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE); + if (!BufferObject) + { + return (AE_NO_MEMORY); + } + + /* Expand each byte to a DWORD */ + + ByteBuffer = ReturnObject->Buffer.Pointer; + DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer); + + for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) + { + *DwordBuffer = (UINT32) *ByteBuffer; + DwordBuffer++; + ByteBuffer++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s Expanded Byte Buffer to expected DWord Buffer\n", + Data->Pathname)); + break; + + default: + return (AE_AML_OPERAND_TYPE); + } + + /* Delete the original return object, return the new buffer object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = BufferObject; + + Data->Flags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * * FUNCTION: AcpiNsRepair_TSS * * PARAMETERS: Data - Pointer to validation data structure @@ -454,6 +560,9 @@ AcpiNsCheckSortedList ( ACPI_STATUS Status; + ACPI_FUNCTION_NAME (NsCheckSortedList); + + /* The top-level object must be a package */ if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) @@ -462,26 +571,10 @@ AcpiNsCheckSortedList ( } /* - * Detect any NULL package elements and remove them from the - * package. - * - * TBD: We may want to do this for all predefined names that - * return a variable-length package of packages. + * NOTE: assumes list of sub-packages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to AcpiNsRemoveNullElements. */ - Status = AcpiNsRemoveNullElements (ReturnObject); - if (Status == AE_NULL_ENTRY) - { - ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "NULL elements removed from package")); - - /* Exit if package is now zero length */ - - if (!ReturnObject->Package.Count) - { - return (AE_NULL_ENTRY); - } - } - OuterElements = ReturnObject->Package.Elements; OuterElementCount = ReturnObject->Package.Count; if (!OuterElementCount) @@ -539,8 +632,9 @@ AcpiNsCheckSortedList ( Data->Flags |= ACPI_OBJECT_REPAIRED; - ACPI_INFO_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, - "Repaired unsorted list - now sorted by %s", SortKeyName)); + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Repaired unsorted list - now sorted by %s\n", + Data->Pathname, SortKeyName)); return (AE_OK); } @@ -556,40 +650,69 @@ AcpiNsCheckSortedList ( * * FUNCTION: AcpiNsRemoveNullElements * - * PARAMETERS: ObjDesc - A Package object + * PARAMETERS: Data - Pointer to validation data structure + * PackageType - An AcpiReturnPackageTypes value + * ObjDesc - A Package object * - * RETURN: Status. AE_NULL_ENTRY means that one or more elements were - * removed. + * RETURN: None. * - * DESCRIPTION: Remove all NULL package elements and update the package count. + * DESCRIPTION: Remove all NULL package elements from packages that contain + * a variable number of sub-packages. * *****************************************************************************/ -static ACPI_STATUS +void AcpiNsRemoveNullElements ( + ACPI_PREDEFINED_DATA *Data, + UINT8 PackageType, ACPI_OPERAND_OBJECT *ObjDesc) { ACPI_OPERAND_OBJECT **Source; ACPI_OPERAND_OBJECT **Dest; - ACPI_STATUS Status = AE_OK; UINT32 Count; UINT32 NewCount; UINT32 i; + ACPI_FUNCTION_NAME (NsRemoveNullElements); + + + /* + * PTYPE1 packages contain no subpackages. + * PTYPE2 packages contain a variable number of sub-packages. We can + * safely remove all NULL elements from the PTYPE2 packages. + */ + switch (PackageType) + { + case ACPI_PTYPE1_FIXED: + case ACPI_PTYPE1_VAR: + case ACPI_PTYPE1_OPTION: + return; + + case ACPI_PTYPE2: + case ACPI_PTYPE2_COUNT: + case ACPI_PTYPE2_PKG_COUNT: + case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_REV_FIXED: + break; + + default: + return; + } + Count = ObjDesc->Package.Count; NewCount = Count; Source = ObjDesc->Package.Elements; Dest = Source; - /* Examine all elements of the package object */ + /* Examine all elements of the package object, remove nulls */ for (i = 0; i < Count; i++) { if (!*Source) { - Status = AE_NULL_ENTRY; NewCount--; } else @@ -600,15 +723,19 @@ AcpiNsRemoveNullElements ( Source++; } - if (Status == AE_NULL_ENTRY) + /* Update parent package if any null elements were removed */ + + if (NewCount < Count) { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Found and removed %u NULL elements\n", + Data->Pathname, (Count - NewCount))); + /* NULL terminate list and update the package count */ *Dest = NULL; ObjDesc->Package.Count = NewCount; } - - return (Status); } diff --git a/namespace/nsutils.c b/namespace/nsutils.c index dffc0d4432b1..ed0c3f7ec810 100644 --- a/namespace/nsutils.c +++ b/namespace/nsutils.c @@ -857,25 +857,26 @@ AcpiNsExternalizeName ( /******************************************************************************* * - * FUNCTION: AcpiNsMapHandleToNode + * FUNCTION: AcpiNsValidateHandle * - * PARAMETERS: Handle - Handle to be converted to an Node + * PARAMETERS: Handle - Handle to be validated and typecast to a + * namespace node. * - * RETURN: A Name table entry pointer + * RETURN: A pointer to a namespace node * - * DESCRIPTION: Convert a namespace handle to a real Node + * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special + * cases for the root node. * - * Note: Real integer handles would allow for more verification + * NOTE: Real integer handles would allow for more verification * and keep all pointers within this subsystem - however this introduces - * more (and perhaps unnecessary) overhead. - * - * The current implemenation is basically a placeholder until such time comes - * that it is needed. + * more overhead and has not been necessary to this point. Drivers + * holding handles are typically notified before a node becomes invalid + * due to a table unload. * ******************************************************************************/ ACPI_NAMESPACE_NODE * -AcpiNsMapHandleToNode ( +AcpiNsValidateHandle ( ACPI_HANDLE Handle) { @@ -902,48 +903,6 @@ AcpiNsMapHandleToNode ( /******************************************************************************* * - * FUNCTION: AcpiNsConvertEntryToHandle - * - * PARAMETERS: Node - Node to be converted to a Handle - * - * RETURN: A user handle - * - * DESCRIPTION: Convert a real Node to a namespace handle - * - ******************************************************************************/ - -ACPI_HANDLE -AcpiNsConvertEntryToHandle ( - ACPI_NAMESPACE_NODE *Node) -{ - - - /* - * Simple implementation for now; - */ - return ((ACPI_HANDLE) Node); - - -/* Example future implementation --------------------- - - if (!Node) - { - return (NULL); - } - - if (Node == AcpiGbl_RootNode) - { - return (ACPI_ROOT_OBJECT); - } - - - return ((ACPI_HANDLE) Node); -------------------------------------------------------*/ -} - - -/******************************************************************************* - * * FUNCTION: AcpiNsTerminate * * PARAMETERS: none diff --git a/namespace/nsxfeval.c b/namespace/nsxfeval.c index 1ba85ab05fd7..a0f96a04ee09 100644 --- a/namespace/nsxfeval.c +++ b/namespace/nsxfeval.c @@ -281,7 +281,7 @@ AcpiEvaluateObject ( /* Convert and validate the device handle */ - Info->PrefixNode = AcpiNsMapHandleToNode (Handle); + Info->PrefixNode = AcpiNsValidateHandle (Handle); if (!Info->PrefixNode) { Status = AE_BAD_PARAMETER; @@ -676,7 +676,7 @@ AcpiNsGetDeviceCallback ( return (Status); } - Node = AcpiNsMapHandleToNode (ObjHandle); + Node = AcpiNsValidateHandle (ObjHandle); Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { @@ -888,7 +888,7 @@ AcpiAttachData ( /* Convert and validate the handle */ - Node = AcpiNsMapHandleToNode (ObjHandle); + Node = AcpiNsValidateHandle (ObjHandle); if (!Node) { Status = AE_BAD_PARAMETER; @@ -943,7 +943,7 @@ AcpiDetachData ( /* Convert and validate the handle */ - Node = AcpiNsMapHandleToNode (ObjHandle); + Node = AcpiNsValidateHandle (ObjHandle); if (!Node) { Status = AE_BAD_PARAMETER; @@ -1001,7 +1001,7 @@ AcpiGetData ( /* Convert and validate the handle */ - Node = AcpiNsMapHandleToNode (ObjHandle); + Node = AcpiNsValidateHandle (ObjHandle); if (!Node) { Status = AE_BAD_PARAMETER; diff --git a/namespace/nsxfname.c b/namespace/nsxfname.c index 166862bc2a9c..cb7aaa6f941f 100644 --- a/namespace/nsxfname.c +++ b/namespace/nsxfname.c @@ -178,7 +178,7 @@ AcpiGetHandle ( if (Parent) { - PrefixNode = AcpiNsMapHandleToNode (Parent); + PrefixNode = AcpiNsValidateHandle (Parent); if (!PrefixNode) { return (AE_BAD_PARAMETER); @@ -200,7 +200,7 @@ AcpiGetHandle ( if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH)) { - *RetHandle = AcpiNsConvertEntryToHandle (AcpiGbl_RootNode); + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode); return (AE_OK); } } @@ -216,7 +216,7 @@ AcpiGetHandle ( Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node); if (ACPI_SUCCESS (Status)) { - *RetHandle = AcpiNsConvertEntryToHandle (Node); + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node); } return (Status); @@ -282,7 +282,7 @@ AcpiGetName ( return (Status); } - Node = AcpiNsMapHandleToNode (Handle); + Node = AcpiNsValidateHandle (Handle); if (!Node) { Status = AE_BAD_PARAMETER; @@ -399,7 +399,7 @@ AcpiGetObjectInfo ( goto Cleanup; } - Node = AcpiNsMapHandleToNode (Handle); + Node = AcpiNsValidateHandle (Handle); if (!Node) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); diff --git a/namespace/nsxfobj.c b/namespace/nsxfobj.c index 023cb6990b0d..9c42a33f8b21 100644 --- a/namespace/nsxfobj.c +++ b/namespace/nsxfobj.c @@ -172,7 +172,7 @@ AcpiGetType ( /* Convert and validate the handle */ - Node = AcpiNsMapHandleToNode (Handle); + Node = AcpiNsValidateHandle (Handle); if (!Node) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); @@ -233,7 +233,7 @@ AcpiGetParent ( /* Convert and validate the handle */ - Node = AcpiNsMapHandleToNode (Handle); + Node = AcpiNsValidateHandle (Handle); if (!Node) { Status = AE_BAD_PARAMETER; @@ -243,7 +243,7 @@ AcpiGetParent ( /* Get the parent entry */ ParentNode = AcpiNsGetParentNode (Node); - *RetHandle = AcpiNsConvertEntryToHandle (ParentNode); + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, ParentNode); /* Return exception if parent is null */ @@ -312,7 +312,7 @@ AcpiGetNextObject ( { /* Start search at the beginning of the specified scope */ - ParentNode = AcpiNsMapHandleToNode (Parent); + ParentNode = AcpiNsValidateHandle (Parent); if (!ParentNode) { Status = AE_BAD_PARAMETER; @@ -324,7 +324,7 @@ AcpiGetNextObject ( /* Non-null handle, ignore the parent */ /* Convert and validate the handle */ - ChildNode = AcpiNsMapHandleToNode (Child); + ChildNode = AcpiNsValidateHandle (Child); if (!ChildNode) { Status = AE_BAD_PARAMETER; @@ -343,7 +343,7 @@ AcpiGetNextObject ( if (RetHandle) { - *RetHandle = AcpiNsConvertEntryToHandle (Node); + *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node); } |