diff options
author | jkim <jkim@FreeBSD.org> | 2012-02-16 00:24:10 +0000 |
---|---|---|
committer | jkim <jkim@FreeBSD.org> | 2012-02-16 00:24:10 +0000 |
commit | a6dfe3119152f97e640cc135d963b9f7c95c84ef (patch) | |
tree | 71526afe7e3c45a4c88ba7b5d8d57d1e469feec2 /source/components/utilities | |
parent | 4cca06feceaf26d2d8b24e1d834b5ab61208d3fa (diff) | |
download | FreeBSD-src-a6dfe3119152f97e640cc135d963b9f7c95c84ef.zip FreeBSD-src-a6dfe3119152f97e640cc135d963b9f7c95c84ef.tar.gz |
Import ACPICA 20120215.
Diffstat (limited to 'source/components/utilities')
24 files changed, 13566 insertions, 0 deletions
diff --git a/source/components/utilities/utaddress.c b/source/components/utilities/utaddress.c new file mode 100644 index 0000000..0b357b6 --- /dev/null +++ b/source/components/utilities/utaddress.c @@ -0,0 +1,322 @@ +/****************************************************************************** + * + * Module Name: utaddress - OpRegion address range check + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTADDRESS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utaddress") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAddAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - OpRegion start address + * Length - OpRegion length + * RegionNode - OpRegion namespace node + * + * RETURN: Status + * + * DESCRIPTION: Add the Operation Region address range to the global list. + * The only supported Space IDs are Memory and I/O. Called when + * the OpRegion address/length operands are fully evaluated. + * + * MUTEX: Locks the namespace + * + * NOTE: Because this interface is only called when an OpRegion argument + * list is evaluated, there cannot be any duplicate RegionNodes. + * Duplicate Address/Length values are allowed, however, so that multiple + * address conflicts can be detected. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAddAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + ACPI_NAMESPACE_NODE *RegionNode) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtAddAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_ACPI_STATUS (AE_OK); + } + + /* Allocate/init a new info block, add it to the appropriate list */ + + RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE)); + if (!RangeInfo) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + RangeInfo->StartAddress = Address; + RangeInfo->EndAddress = (Address + Length - 1); + RangeInfo->RegionNode = RegionNode; + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (RangeInfo); + return_ACPI_STATUS (Status); + } + + RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId]; + AcpiGbl_AddressRangeList[SpaceId] = RangeInfo; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "\nAdded [%4.4s] address range: 0x%p-0x%p\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_CAST_PTR (void, Address), + ACPI_CAST_PTR (void, RangeInfo->EndAddress))); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * RegionNode - OpRegion namespace node + * + * RETURN: None + * + * DESCRIPTION: Remove the Operation Region from the global list. The only + * supported Space IDs are Memory and I/O. Called when an + * OpRegion is deleted. + * + * MUTEX: Assumes the namespace is locked + * + ******************************************************************************/ + +void +AcpiUtRemoveAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_NAMESPACE_NODE *RegionNode) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_ADDRESS_RANGE *Prev; + + + ACPI_FUNCTION_TRACE (UtRemoveAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_VOID; + } + + /* Get the appropriate list head and check the list */ + + RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId]; + while (RangeInfo) + { + if (RangeInfo->RegionNode == RegionNode) + { + if (RangeInfo == Prev) /* Found at list head */ + { + AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next; + } + else + { + Prev->Next = RangeInfo->Next; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_CAST_PTR (void, RangeInfo->StartAddress), + ACPI_CAST_PTR (void, RangeInfo->EndAddress))); + + ACPI_FREE (RangeInfo); + return_VOID; + } + + Prev = RangeInfo; + RangeInfo = RangeInfo->Next; + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCheckAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - Start address + * Length - Length of address range + * Warn - TRUE if warning on overlap desired + * + * RETURN: Count of the number of conflicts detected. Zero is always + * returned for Space IDs other than Memory or I/O. + * + * DESCRIPTION: Check if the input address range overlaps any of the + * ASL operation region address ranges. The only supported + * Space IDs are Memory and I/O. + * + * MUTEX: Assumes the namespace is locked. + * + ******************************************************************************/ + +UINT32 +AcpiUtCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + UINT32 Length, + BOOLEAN Warn) +{ + ACPI_ADDRESS_RANGE *RangeInfo; + ACPI_PHYSICAL_ADDRESS EndAddress; + char *Pathname; + UINT32 OverlapCount = 0; + + + ACPI_FUNCTION_TRACE (UtCheckAddressRange); + + + if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && + (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) + { + return_UINT32 (0); + } + + RangeInfo = AcpiGbl_AddressRangeList[SpaceId]; + EndAddress = Address + Length - 1; + + /* Check entire list for all possible conflicts */ + + while (RangeInfo) + { + /* + * Check if the requested Address/Length overlaps this AddressRange. + * Four cases to consider: + * + * 1) Input address/length is contained completely in the address range + * 2) Input address/length overlaps range at the range start + * 3) Input address/length overlaps range at the range end + * 4) Input address/length completely encompasses the range + */ + if ((Address <= RangeInfo->EndAddress) && + (EndAddress >= RangeInfo->StartAddress)) + { + /* Found an address range overlap */ + + OverlapCount++; + if (Warn) /* Optional warning message */ + { + Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode); + + ACPI_WARNING ((AE_INFO, + "0x%p-0x%p %s conflicts with Region %s %d", + ACPI_CAST_PTR (void, Address), + ACPI_CAST_PTR (void, EndAddress), + AcpiUtGetRegionName (SpaceId), Pathname, OverlapCount)); + ACPI_FREE (Pathname); + } + } + + RangeInfo = RangeInfo->Next; + } + + return_UINT32 (OverlapCount); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteAddressLists + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all global address range lists (called during + * subsystem shutdown). + * + ******************************************************************************/ + +void +AcpiUtDeleteAddressLists ( + void) +{ + ACPI_ADDRESS_RANGE *Next; + ACPI_ADDRESS_RANGE *RangeInfo; + int i; + + + /* Delete all elements in all address range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) + { + Next = AcpiGbl_AddressRangeList[i]; + + while (Next) + { + RangeInfo = Next; + Next = RangeInfo->Next; + ACPI_FREE (RangeInfo); + } + + AcpiGbl_AddressRangeList[i] = NULL; + } +} diff --git a/source/components/utilities/utalloc.c b/source/components/utilities/utalloc.c new file mode 100644 index 0000000..d2eb11e --- /dev/null +++ b/source/components/utilities/utalloc.c @@ -0,0 +1,416 @@ +/****************************************************************************** + * + * Module Name: utalloc - local memory allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTALLOC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utalloc") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateCaches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Create all local caches + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateCaches ( + void) +{ + ACPI_STATUS Status; + + + /* Object Caches, for frequently used objects */ + + Status = AcpiOsCreateCache ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE), + ACPI_MAX_NAMESPACE_CACHE_DEPTH, &AcpiGbl_NamespaceCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-State", sizeof (ACPI_GENERIC_STATE), + ACPI_MAX_STATE_CACHE_DEPTH, &AcpiGbl_StateCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-Parse", sizeof (ACPI_PARSE_OBJ_COMMON), + ACPI_MAX_PARSE_CACHE_DEPTH, &AcpiGbl_PsNodeCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-ParseExt", sizeof (ACPI_PARSE_OBJ_NAMED), + ACPI_MAX_EXTPARSE_CACHE_DEPTH, &AcpiGbl_PsNodeExtCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateCache ("Acpi-Operand", sizeof (ACPI_OPERAND_OBJECT), + ACPI_MAX_OBJECT_CACHE_DEPTH, &AcpiGbl_OperandCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Memory allocation lists */ + + Status = AcpiUtCreateList ("Acpi-Global", 0, + &AcpiGbl_GlobalList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtCreateList ("Acpi-Namespace", sizeof (ACPI_NAMESPACE_NODE), + &AcpiGbl_NsNodeList); + if (ACPI_FAILURE (Status)) + { + return (Status); + } +#endif + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteCaches + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Purge and delete all local caches + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtDeleteCaches ( + void) +{ +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + char Buffer[7]; + + if (AcpiGbl_DisplayFinalMemStats) + { + ACPI_STRCPY (Buffer, "MEMORY"); + (void) AcpiDbDisplayStatistics (Buffer); + } +#endif + + (void) AcpiOsDeleteCache (AcpiGbl_NamespaceCache); + AcpiGbl_NamespaceCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_StateCache); + AcpiGbl_StateCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_OperandCache); + AcpiGbl_OperandCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_PsNodeCache); + AcpiGbl_PsNodeCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_PsNodeExtCache); + AcpiGbl_PsNodeExtCache = NULL; + + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + + /* Debug only - display leftover memory allocation, if any */ + + AcpiUtDumpAllocations (ACPI_UINT32_MAX, NULL); + + /* Free memory lists */ + + AcpiOsFree (AcpiGbl_GlobalList); + AcpiGbl_GlobalList = NULL; + + AcpiOsFree (AcpiGbl_NsNodeList); + AcpiGbl_NsNodeList = NULL; +#endif + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateBuffer + * + * PARAMETERS: Buffer - Buffer descriptor to be validated + * + * RETURN: Status + * + * DESCRIPTION: Perform parameter validation checks on an ACPI_BUFFER + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtValidateBuffer ( + ACPI_BUFFER *Buffer) +{ + + /* Obviously, the structure pointer must be valid */ + + if (!Buffer) + { + return (AE_BAD_PARAMETER); + } + + /* Special semantics for the length */ + + if ((Buffer->Length == ACPI_NO_BUFFER) || + (Buffer->Length == ACPI_ALLOCATE_BUFFER) || + (Buffer->Length == ACPI_ALLOCATE_LOCAL_BUFFER)) + { + return (AE_OK); + } + + /* Length is valid, the buffer pointer must be also */ + + if (!Buffer->Pointer) + { + return (AE_BAD_PARAMETER); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitializeBuffer + * + * PARAMETERS: Buffer - Buffer to be validated + * RequiredLength - Length needed + * + * RETURN: Status + * + * DESCRIPTION: Validate that the buffer is of the required length or + * allocate a new buffer. Returned buffer is always zeroed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitializeBuffer ( + ACPI_BUFFER *Buffer, + ACPI_SIZE RequiredLength) +{ + ACPI_SIZE InputBufferLength; + + + /* Parameter validation */ + + if (!Buffer || !RequiredLength) + { + return (AE_BAD_PARAMETER); + } + + /* + * Buffer->Length is used as both an input and output parameter. Get the + * input actual length and set the output required buffer length. + */ + InputBufferLength = Buffer->Length; + Buffer->Length = RequiredLength; + + /* + * The input buffer length contains the actual buffer length, or the type + * of buffer to be allocated by this routine. + */ + switch (InputBufferLength) + { + case ACPI_NO_BUFFER: + + /* Return the exception (and the required buffer length) */ + + return (AE_BUFFER_OVERFLOW); + + case ACPI_ALLOCATE_BUFFER: + + /* Allocate a new buffer */ + + Buffer->Pointer = AcpiOsAllocate (RequiredLength); + break; + + case ACPI_ALLOCATE_LOCAL_BUFFER: + + /* Allocate a new buffer with local interface to allow tracking */ + + Buffer->Pointer = ACPI_ALLOCATE (RequiredLength); + break; + + default: + + /* Existing buffer: Validate the size of the buffer */ + + if (InputBufferLength < RequiredLength) + { + return (AE_BUFFER_OVERFLOW); + } + break; + } + + /* Validate allocation from above or input buffer pointer */ + + if (!Buffer->Pointer) + { + return (AE_NO_MEMORY); + } + + /* Have a valid buffer, clear it */ + + ACPI_MEMSET (Buffer->Pointer, 0, RequiredLength); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocate + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of malloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocate ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + void *Allocation; + + + ACPI_FUNCTION_TRACE_U32 (UtAllocate, Size); + + + /* Check for an inadvertent size of zero bytes */ + + if (!Size) + { + ACPI_WARNING ((Module, Line, + "Attempt to allocate zero bytes, allocating 1 byte")); + Size = 1; + } + + Allocation = AcpiOsAllocate (Size); + if (!Allocation) + { + /* Report allocation error */ + + ACPI_WARNING ((Module, Line, + "Could not allocate size %u", (UINT32) Size)); + + return_PTR (NULL); + } + + return_PTR (Allocation); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateZeroed + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * + ******************************************************************************/ + +void * +AcpiUtAllocateZeroed ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + void *Allocation; + + + ACPI_FUNCTION_ENTRY (); + + + Allocation = AcpiUtAllocate (Size, Component, Module, Line); + if (Allocation) + { + /* Clear the memory block */ + + ACPI_MEMSET (Allocation, 0, Size); + } + + return (Allocation); +} + diff --git a/source/components/utilities/utcache.c b/source/components/utilities/utcache.c new file mode 100644 index 0000000..7b3abe2 --- /dev/null +++ b/source/components/utilities/utcache.c @@ -0,0 +1,361 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTCACHE_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utcache") + + +#ifdef ACPI_USE_LOCAL_CACHE +/******************************************************************************* + * + * FUNCTION: AcpiOsCreateCache + * + * PARAMETERS: CacheName - Ascii name for the cache + * ObjectSize - Size of each cached object + * MaxDepth - Maximum depth of the cache (in objects) + * ReturnCache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a cache object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsCreateCache ( + char *CacheName, + UINT16 ObjectSize, + UINT16 MaxDepth, + ACPI_MEMORY_LIST **ReturnCache) +{ + ACPI_MEMORY_LIST *Cache; + + + ACPI_FUNCTION_ENTRY (); + + + if (!CacheName || !ReturnCache || (ObjectSize < 16)) + { + return (AE_BAD_PARAMETER); + } + + /* Create the cache object */ + + Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); + if (!Cache) + { + return (AE_NO_MEMORY); + } + + /* Populate the cache object and return it */ + + ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + Cache->LinkOffset = 8; + Cache->ListName = CacheName; + Cache->ObjectSize = ObjectSize; + Cache->MaxDepth = MaxDepth; + + *ReturnCache = Cache; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsPurgeCache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsPurgeCache ( + ACPI_MEMORY_LIST *Cache) +{ + char *Next; + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Cache) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Walk the list of objects in this cache */ + + while (Cache->ListHead) + { + /* Delete and unlink one cached state object */ + + Next = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Cache->ListHead)[Cache->LinkOffset]))); + ACPI_FREE (Cache->ListHead); + + Cache->ListHead = Next; + Cache->CurrentDepth--; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsDeleteCache + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: Status + * + * DESCRIPTION: Free all objects within the requested cache and delete the + * cache object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsDeleteCache ( + ACPI_MEMORY_LIST *Cache) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + /* Purge all objects in the cache */ + + Status = AcpiOsPurgeCache (Cache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Now we can delete the cache object */ + + AcpiOsFree (Cache); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsReleaseObject + * + * PARAMETERS: Cache - Handle to cache object + * Object - The object to be released + * + * RETURN: None + * + * DESCRIPTION: Release an object to the specified cache. If cache is full, + * the object is deleted. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiOsReleaseObject ( + ACPI_MEMORY_LIST *Cache, + void *Object) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if (!Cache || !Object) + { + return (AE_BAD_PARAMETER); + } + + /* If cache is full, just free this object */ + + if (Cache->CurrentDepth >= Cache->MaxDepth) + { + ACPI_FREE (Object); + ACPI_MEM_TRACKING (Cache->TotalFreed++); + } + + /* Otherwise put this object back into the cache */ + + else + { + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Mark the object as cached */ + + ACPI_MEMSET (Object, 0xCA, Cache->ObjectSize); + ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_CACHED); + + /* Put the object at the head of the cache list */ + + * (ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Object)[Cache->LinkOffset]))) = Cache->ListHead; + Cache->ListHead = Object; + Cache->CurrentDepth++; + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiOsAcquireObject + * + * PARAMETERS: Cache - Handle to cache object + * + * RETURN: the acquired object. NULL on error + * + * DESCRIPTION: Get an object from the specified cache. If cache is empty, + * the object is allocated. + * + ******************************************************************************/ + +void * +AcpiOsAcquireObject ( + ACPI_MEMORY_LIST *Cache) +{ + ACPI_STATUS Status; + void *Object; + + + ACPI_FUNCTION_NAME (OsAcquireObject); + + + if (!Cache) + { + return (NULL); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + ACPI_MEM_TRACKING (Cache->Requests++); + + /* Check the cache first */ + + if (Cache->ListHead) + { + /* There is an object available, use it */ + + Object = Cache->ListHead; + Cache->ListHead = *(ACPI_CAST_INDIRECT_PTR (char, + &(((char *) Object)[Cache->LinkOffset]))); + + Cache->CurrentDepth--; + + ACPI_MEM_TRACKING (Cache->Hits++); + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Object %p from %s cache\n", Object, Cache->ListName)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + /* Clear (zero) the previously used Object */ + + ACPI_MEMSET (Object, 0, Cache->ObjectSize); + } + else + { + /* The cache is empty, create a new object */ + + ACPI_MEM_TRACKING (Cache->TotalAllocated++); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) + { + Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; + } +#endif + + /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ + + Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return (NULL); + } + + Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); + if (!Object) + { + return (NULL); + } + } + + return (Object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ + + diff --git a/source/components/utilities/utclib.c b/source/components/utilities/utclib.c new file mode 100644 index 0000000..d0153ec --- /dev/null +++ b/source/components/utilities/utclib.c @@ -0,0 +1,889 @@ +/****************************************************************************** + * + * Module Name: cmclib - Local implementation of C library functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __CMCLIB_C__ + +#include "acpi.h" +#include "accommon.h" + +/* + * These implementations of standard C Library routines can optionally be + * used if a C library is not available. In general, they are less efficient + * than an inline or assembly implementation + */ + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("cmclib") + + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +#define NEGATIVE 1 +#define POSITIVE 0 + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemcmp (memcmp) + * + * PARAMETERS: Buffer1 - First Buffer + * Buffer2 - Second Buffer + * Count - Maximum # of bytes to compare + * + * RETURN: Index where Buffers mismatched, or 0 if Buffers matched + * + * DESCRIPTION: Compare two Buffers, with a maximum length + * + ******************************************************************************/ + +int +AcpiUtMemcmp ( + const char *Buffer1, + const char *Buffer2, + ACPI_SIZE Count) +{ + + for ( ; Count-- && (*Buffer1 == *Buffer2); Buffer1++, Buffer2++) + { + } + + return ((Count == ACPI_SIZE_MAX) ? 0 : ((unsigned char) *Buffer1 - + (unsigned char) *Buffer2)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemcpy (memcpy) + * + * PARAMETERS: Dest - Target of the copy + * Src - Source buffer to copy + * Count - Number of bytes to copy + * + * RETURN: Dest + * + * DESCRIPTION: Copy arbitrary bytes of memory + * + ******************************************************************************/ + +void * +AcpiUtMemcpy ( + void *Dest, + const void *Src, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + char *Old = (char *) Src; + + + while (Count) + { + *New = *Old; + New++; + Old++; + Count--; + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMemset (memset) + * + * PARAMETERS: Dest - Buffer to set + * Value - Value to set each byte of memory + * Count - Number of bytes to set + * + * RETURN: Dest + * + * DESCRIPTION: Initialize a buffer to a known value. + * + ******************************************************************************/ + +void * +AcpiUtMemset ( + void *Dest, + UINT8 Value, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + + + while (Count) + { + *New = (char) Value; + New++; + Count--; + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlen (strlen) + * + * PARAMETERS: String - Null terminated string + * + * RETURN: Length + * + * DESCRIPTION: Returns the length of the input string + * + ******************************************************************************/ + + +ACPI_SIZE +AcpiUtStrlen ( + const char *String) +{ + UINT32 Length = 0; + + + /* Count the string until a null is encountered */ + + while (*String) + { + Length++; + String++; + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcpy (strcpy) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * + * RETURN: DstString + * + * DESCRIPTION: Copy a null terminated string + * + ******************************************************************************/ + +char * +AcpiUtStrcpy ( + char *DstString, + const char *SrcString) +{ + char *String = DstString; + + + /* Move bytes brute force */ + + while (*SrcString) + { + *String = *SrcString; + + String++; + SrcString++; + } + + /* Null terminate */ + + *String = 0; + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncpy (strncpy) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: DstString + * + * DESCRIPTION: Copy a null terminated string, with a maximum length + * + ******************************************************************************/ + +char * +AcpiUtStrncpy ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count) +{ + char *String = DstString; + + + /* Copy the string */ + + for (String = DstString; + Count && (Count--, (*String++ = *SrcString++)); ) + {;} + + /* Pad with nulls if necessary */ + + while (Count--) + { + *String = 0; + String++; + } + + /* Return original pointer */ + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcmp (strcmp) + * + * PARAMETERS: String1 - First string + * String2 - Second string + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings + * + ******************************************************************************/ + +int +AcpiUtStrcmp ( + const char *String1, + const char *String2) +{ + + + for ( ; (*String1 == *String2); String2++) + { + if (!*String1++) + { + return (0); + } + } + + return ((unsigned char) *String1 - (unsigned char) *String2); +} + + +#ifdef ACPI_FUTURE_IMPLEMENTATION +/* Not used at this time */ +/******************************************************************************* + * + * FUNCTION: AcpiUtStrchr (strchr) + * + * PARAMETERS: String - Search string + * ch - character to search for + * + * RETURN: Ptr to char or NULL if not found + * + * DESCRIPTION: Search a string for a character + * + ******************************************************************************/ + +char * +AcpiUtStrchr ( + const char *String, + int ch) +{ + + + for ( ; (*String); String++) + { + if ((*String) == (char) ch) + { + return ((char *) String); + } + } + + return (NULL); +} +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncmp (strncmp) + * + * PARAMETERS: String1 - First string + * String2 - Second string + * Count - Maximum # of bytes to compare + * + * RETURN: Index where strings mismatched, or 0 if strings matched + * + * DESCRIPTION: Compare two null terminated strings, with a maximum length + * + ******************************************************************************/ + +int +AcpiUtStrncmp ( + const char *String1, + const char *String2, + ACPI_SIZE Count) +{ + + + for ( ; Count-- && (*String1 == *String2); String2++) + { + if (!*String1++) + { + return (0); + } + } + + return ((Count == ACPI_SIZE_MAX) ? 0 : ((unsigned char) *String1 - + (unsigned char) *String2)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrcat (Strcat) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * + * RETURN: DstString + * + * DESCRIPTION: Append a null terminated string to a null terminated string + * + ******************************************************************************/ + +char * +AcpiUtStrcat ( + char *DstString, + const char *SrcString) +{ + char *String; + + + /* Find end of the destination string */ + + for (String = DstString; *String++; ) + { ; } + + /* Concatenate the string */ + + for (--String; (*String++ = *SrcString++); ) + { ; } + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrncat (strncat) + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * Count - Maximum # of bytes to copy + * + * RETURN: DstString + * + * DESCRIPTION: Append a null terminated string to a null terminated string, + * with a maximum count. + * + ******************************************************************************/ + +char * +AcpiUtStrncat ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count) +{ + char *String; + + + if (Count) + { + /* Find end of the destination string */ + + for (String = DstString; *String++; ) + { ; } + + /* Concatenate the string */ + + for (--String; (*String++ = *SrcString++) && --Count; ) + { ; } + + /* Null terminate if necessary */ + + if (!Count) + { + *String = 0; + } + } + + return (DstString); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrstr (strstr) + * + * PARAMETERS: String1 - Target string + * String2 - Substring to search for + * + * RETURN: Where substring match starts, Null if no match found + * + * DESCRIPTION: Checks if String2 occurs in String1. This is not really a + * full implementation of strstr, only sufficient for command + * matching + * + ******************************************************************************/ + +char * +AcpiUtStrstr ( + char *String1, + char *String2) +{ + char *String; + + + if (AcpiUtStrlen (String2) > AcpiUtStrlen (String1)) + { + return (NULL); + } + + /* Walk entire string, comparing the letters */ + + for (String = String1; *String2; ) + { + if (*String2 != *String) + { + return (NULL); + } + + String2++; + String++; + } + + return (String1); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul (strtoul) + * + * PARAMETERS: String - Null terminated string + * Terminater - Where a pointer to the terminating byte is + * returned + * Base - Radix of the string + * + * RETURN: Converted value + * + * DESCRIPTION: Convert a string into a 32-bit unsigned value. + * Note: use AcpiUtStrtoul64 for 64-bit integers. + * + ******************************************************************************/ + +UINT32 +AcpiUtStrtoul ( + const char *String, + char **Terminator, + UINT32 Base) +{ + UINT32 converted = 0; + UINT32 index; + UINT32 sign; + const char *StringStart; + UINT32 ReturnValue = 0; + ACPI_STATUS Status = AE_OK; + + + /* + * Save the value of the pointer to the buffer's first + * character, save the current errno value, and then + * skip over any white space in the buffer: + */ + StringStart = String; + while (ACPI_IS_SPACE (*String) || *String == '\t') + { + ++String; + } + + /* + * The buffer may contain an optional plus or minus sign. + * If it does, then skip over it but remember what is was: + */ + if (*String == '-') + { + sign = NEGATIVE; + ++String; + } + else if (*String == '+') + { + ++String; + sign = POSITIVE; + } + else + { + sign = POSITIVE; + } + + /* + * If the input parameter Base is zero, then we need to + * determine if it is octal, decimal, or hexadecimal: + */ + if (Base == 0) + { + if (*String == '0') + { + if (AcpiUtToLower (*(++String)) == 'x') + { + Base = 16; + ++String; + } + else + { + Base = 8; + } + } + else + { + Base = 10; + } + } + else if (Base < 2 || Base > 36) + { + /* + * The specified Base parameter is not in the domain of + * this function: + */ + goto done; + } + + /* + * For octal and hexadecimal bases, skip over the leading + * 0 or 0x, if they are present. + */ + if (Base == 8 && *String == '0') + { + String++; + } + + if (Base == 16 && + *String == '0' && + AcpiUtToLower (*(++String)) == 'x') + { + String++; + } + + /* + * Main loop: convert the string to an unsigned long: + */ + while (*String) + { + if (ACPI_IS_DIGIT (*String)) + { + index = (UINT32) ((UINT8) *String - '0'); + } + else + { + index = (UINT32) AcpiUtToUpper (*String); + if (ACPI_IS_UPPER (index)) + { + index = index - 'A' + 10; + } + else + { + goto done; + } + } + + if (index >= Base) + { + goto done; + } + + /* + * Check to see if value is out of range: + */ + + if (ReturnValue > ((ACPI_UINT32_MAX - (UINT32) index) / + (UINT32) Base)) + { + Status = AE_ERROR; + ReturnValue = 0; /* reset */ + } + else + { + ReturnValue *= Base; + ReturnValue += index; + converted = 1; + } + + ++String; + } + +done: + /* + * If appropriate, update the caller's pointer to the next + * unconverted character in the buffer. + */ + if (Terminator) + { + if (converted == 0 && ReturnValue == 0 && String != NULL) + { + *Terminator = (char *) StringStart; + } + else + { + *Terminator = (char *) String; + } + } + + if (Status == AE_ERROR) + { + ReturnValue = ACPI_UINT32_MAX; + } + + /* + * If a minus sign was present, then "the conversion is negated": + */ + if (sign == NEGATIVE) + { + ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; + } + + return (ReturnValue); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtToUpper (TOUPPER) + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to uppercase + * + ******************************************************************************/ + +int +AcpiUtToUpper ( + int c) +{ + + return (ACPI_IS_LOWER(c) ? ((c)-0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtToLower (TOLOWER) + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to lowercase + * + ******************************************************************************/ + +int +AcpiUtToLower ( + int c) +{ + + return (ACPI_IS_UPPER(c) ? ((c)+0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: is* functions + * + * DESCRIPTION: is* functions use the ctype table below + * + ******************************************************************************/ + +const UINT8 _acpi_ctype[257] = { + _ACPI_CN, /* 0x0 0. */ + _ACPI_CN, /* 0x1 1. */ + _ACPI_CN, /* 0x2 2. */ + _ACPI_CN, /* 0x3 3. */ + _ACPI_CN, /* 0x4 4. */ + _ACPI_CN, /* 0x5 5. */ + _ACPI_CN, /* 0x6 6. */ + _ACPI_CN, /* 0x7 7. */ + _ACPI_CN, /* 0x8 8. */ + _ACPI_CN|_ACPI_SP, /* 0x9 9. */ + _ACPI_CN|_ACPI_SP, /* 0xA 10. */ + _ACPI_CN|_ACPI_SP, /* 0xB 11. */ + _ACPI_CN|_ACPI_SP, /* 0xC 12. */ + _ACPI_CN|_ACPI_SP, /* 0xD 13. */ + _ACPI_CN, /* 0xE 14. */ + _ACPI_CN, /* 0xF 15. */ + _ACPI_CN, /* 0x10 16. */ + _ACPI_CN, /* 0x11 17. */ + _ACPI_CN, /* 0x12 18. */ + _ACPI_CN, /* 0x13 19. */ + _ACPI_CN, /* 0x14 20. */ + _ACPI_CN, /* 0x15 21. */ + _ACPI_CN, /* 0x16 22. */ + _ACPI_CN, /* 0x17 23. */ + _ACPI_CN, /* 0x18 24. */ + _ACPI_CN, /* 0x19 25. */ + _ACPI_CN, /* 0x1A 26. */ + _ACPI_CN, /* 0x1B 27. */ + _ACPI_CN, /* 0x1C 28. */ + _ACPI_CN, /* 0x1D 29. */ + _ACPI_CN, /* 0x1E 30. */ + _ACPI_CN, /* 0x1F 31. */ + _ACPI_XS|_ACPI_SP, /* 0x20 32. ' ' */ + _ACPI_PU, /* 0x21 33. '!' */ + _ACPI_PU, /* 0x22 34. '"' */ + _ACPI_PU, /* 0x23 35. '#' */ + _ACPI_PU, /* 0x24 36. '$' */ + _ACPI_PU, /* 0x25 37. '%' */ + _ACPI_PU, /* 0x26 38. '&' */ + _ACPI_PU, /* 0x27 39. ''' */ + _ACPI_PU, /* 0x28 40. '(' */ + _ACPI_PU, /* 0x29 41. ')' */ + _ACPI_PU, /* 0x2A 42. '*' */ + _ACPI_PU, /* 0x2B 43. '+' */ + _ACPI_PU, /* 0x2C 44. ',' */ + _ACPI_PU, /* 0x2D 45. '-' */ + _ACPI_PU, /* 0x2E 46. '.' */ + _ACPI_PU, /* 0x2F 47. '/' */ + _ACPI_XD|_ACPI_DI, /* 0x30 48. '0' */ + _ACPI_XD|_ACPI_DI, /* 0x31 49. '1' */ + _ACPI_XD|_ACPI_DI, /* 0x32 50. '2' */ + _ACPI_XD|_ACPI_DI, /* 0x33 51. '3' */ + _ACPI_XD|_ACPI_DI, /* 0x34 52. '4' */ + _ACPI_XD|_ACPI_DI, /* 0x35 53. '5' */ + _ACPI_XD|_ACPI_DI, /* 0x36 54. '6' */ + _ACPI_XD|_ACPI_DI, /* 0x37 55. '7' */ + _ACPI_XD|_ACPI_DI, /* 0x38 56. '8' */ + _ACPI_XD|_ACPI_DI, /* 0x39 57. '9' */ + _ACPI_PU, /* 0x3A 58. ':' */ + _ACPI_PU, /* 0x3B 59. ';' */ + _ACPI_PU, /* 0x3C 60. '<' */ + _ACPI_PU, /* 0x3D 61. '=' */ + _ACPI_PU, /* 0x3E 62. '>' */ + _ACPI_PU, /* 0x3F 63. '?' */ + _ACPI_PU, /* 0x40 64. '@' */ + _ACPI_XD|_ACPI_UP, /* 0x41 65. 'A' */ + _ACPI_XD|_ACPI_UP, /* 0x42 66. 'B' */ + _ACPI_XD|_ACPI_UP, /* 0x43 67. 'C' */ + _ACPI_XD|_ACPI_UP, /* 0x44 68. 'D' */ + _ACPI_XD|_ACPI_UP, /* 0x45 69. 'E' */ + _ACPI_XD|_ACPI_UP, /* 0x46 70. 'F' */ + _ACPI_UP, /* 0x47 71. 'G' */ + _ACPI_UP, /* 0x48 72. 'H' */ + _ACPI_UP, /* 0x49 73. 'I' */ + _ACPI_UP, /* 0x4A 74. 'J' */ + _ACPI_UP, /* 0x4B 75. 'K' */ + _ACPI_UP, /* 0x4C 76. 'L' */ + _ACPI_UP, /* 0x4D 77. 'M' */ + _ACPI_UP, /* 0x4E 78. 'N' */ + _ACPI_UP, /* 0x4F 79. 'O' */ + _ACPI_UP, /* 0x50 80. 'P' */ + _ACPI_UP, /* 0x51 81. 'Q' */ + _ACPI_UP, /* 0x52 82. 'R' */ + _ACPI_UP, /* 0x53 83. 'S' */ + _ACPI_UP, /* 0x54 84. 'T' */ + _ACPI_UP, /* 0x55 85. 'U' */ + _ACPI_UP, /* 0x56 86. 'V' */ + _ACPI_UP, /* 0x57 87. 'W' */ + _ACPI_UP, /* 0x58 88. 'X' */ + _ACPI_UP, /* 0x59 89. 'Y' */ + _ACPI_UP, /* 0x5A 90. 'Z' */ + _ACPI_PU, /* 0x5B 91. '[' */ + _ACPI_PU, /* 0x5C 92. '\' */ + _ACPI_PU, /* 0x5D 93. ']' */ + _ACPI_PU, /* 0x5E 94. '^' */ + _ACPI_PU, /* 0x5F 95. '_' */ + _ACPI_PU, /* 0x60 96. '`' */ + _ACPI_XD|_ACPI_LO, /* 0x61 97. 'a' */ + _ACPI_XD|_ACPI_LO, /* 0x62 98. 'b' */ + _ACPI_XD|_ACPI_LO, /* 0x63 99. 'c' */ + _ACPI_XD|_ACPI_LO, /* 0x64 100. 'd' */ + _ACPI_XD|_ACPI_LO, /* 0x65 101. 'e' */ + _ACPI_XD|_ACPI_LO, /* 0x66 102. 'f' */ + _ACPI_LO, /* 0x67 103. 'g' */ + _ACPI_LO, /* 0x68 104. 'h' */ + _ACPI_LO, /* 0x69 105. 'i' */ + _ACPI_LO, /* 0x6A 106. 'j' */ + _ACPI_LO, /* 0x6B 107. 'k' */ + _ACPI_LO, /* 0x6C 108. 'l' */ + _ACPI_LO, /* 0x6D 109. 'm' */ + _ACPI_LO, /* 0x6E 110. 'n' */ + _ACPI_LO, /* 0x6F 111. 'o' */ + _ACPI_LO, /* 0x70 112. 'p' */ + _ACPI_LO, /* 0x71 113. 'q' */ + _ACPI_LO, /* 0x72 114. 'r' */ + _ACPI_LO, /* 0x73 115. 's' */ + _ACPI_LO, /* 0x74 116. 't' */ + _ACPI_LO, /* 0x75 117. 'u' */ + _ACPI_LO, /* 0x76 118. 'v' */ + _ACPI_LO, /* 0x77 119. 'w' */ + _ACPI_LO, /* 0x78 120. 'x' */ + _ACPI_LO, /* 0x79 121. 'y' */ + _ACPI_LO, /* 0x7A 122. 'z' */ + _ACPI_PU, /* 0x7B 123. '{' */ + _ACPI_PU, /* 0x7C 124. '|' */ + _ACPI_PU, /* 0x7D 125. '}' */ + _ACPI_PU, /* 0x7E 126. '~' */ + _ACPI_CN, /* 0x7F 127. */ + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */ +}; + + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + diff --git a/source/components/utilities/utcopy.c b/source/components/utilities/utcopy.c new file mode 100644 index 0000000..ab04a7a --- /dev/null +++ b/source/components/utilities/utcopy.c @@ -0,0 +1,1078 @@ +/****************************************************************************** + * + * Module Name: utcopy - Internal to external object translation utilities + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTCOPY_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utcopy") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtCopyIsimpleToEsimple ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_OBJECT *ExternalObject, + UINT8 *DataSpace, + ACPI_SIZE *BufferSpaceUsed); + +static ACPI_STATUS +AcpiUtCopyIelementToIelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + +static ACPI_STATUS +AcpiUtCopyIpackageToEpackage ( + ACPI_OPERAND_OBJECT *InternalObject, + UINT8 *Buffer, + ACPI_SIZE *SpaceUsed); + +static ACPI_STATUS +AcpiUtCopyEsimpleToIsimple( + ACPI_OBJECT *UserObj, + ACPI_OPERAND_OBJECT **ReturnObj); + +static ACPI_STATUS +AcpiUtCopyEpackageToIpackage ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject); + +static ACPI_STATUS +AcpiUtCopySimpleObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc); + +static ACPI_STATUS +AcpiUtCopyIelementToEelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + +static ACPI_STATUS +AcpiUtCopyIpackageToIpackage ( + ACPI_OPERAND_OBJECT *SourceObj, + ACPI_OPERAND_OBJECT *DestObj, + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIsimpleToEsimple + * + * PARAMETERS: InternalObject - Source object to be copied + * ExternalObject - Where to return the copied object + * DataSpace - Where object data is returned (such as + * buffer and string data) + * BufferSpaceUsed - Length of DataSpace that was used + * + * RETURN: Status + * + * DESCRIPTION: This function is called to copy a simple internal object to + * an external object. + * + * The DataSpace buffer is assumed to have sufficient space for + * the object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIsimpleToEsimple ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_OBJECT *ExternalObject, + UINT8 *DataSpace, + ACPI_SIZE *BufferSpaceUsed) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple); + + + *BufferSpaceUsed = 0; + + /* + * Check for NULL object case (could be an uninitialized + * package element) + */ + if (!InternalObject) + { + return_ACPI_STATUS (AE_OK); + } + + /* Always clear the external object */ + + ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT)); + + /* + * In general, the external object will be the same type as + * the internal object + */ + ExternalObject->Type = InternalObject->Common.Type; + + /* However, only a limited number of external types are supported */ + + switch (InternalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + ExternalObject->String.Pointer = (char *) DataSpace; + ExternalObject->String.Length = InternalObject->String.Length; + *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( + (ACPI_SIZE) InternalObject->String.Length + 1); + + ACPI_MEMCPY ((void *) DataSpace, + (void *) InternalObject->String.Pointer, + (ACPI_SIZE) InternalObject->String.Length + 1); + break; + + + case ACPI_TYPE_BUFFER: + + ExternalObject->Buffer.Pointer = DataSpace; + ExternalObject->Buffer.Length = InternalObject->Buffer.Length; + *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD ( + InternalObject->String.Length); + + ACPI_MEMCPY ((void *) DataSpace, + (void *) InternalObject->Buffer.Pointer, + InternalObject->Buffer.Length); + break; + + + case ACPI_TYPE_INTEGER: + + ExternalObject->Integer.Value = InternalObject->Integer.Value; + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* This is an object reference. */ + + switch (InternalObject->Reference.Class) + { + case ACPI_REFCLASS_NAME: + + /* + * For namepath, return the object handle ("reference") + * We are referring to the namespace node + */ + ExternalObject->Reference.Handle = + InternalObject->Reference.Node; + ExternalObject->Reference.ActualType = + AcpiNsGetType (InternalObject->Reference.Node); + break; + + default: + + /* All other reference types are unsupported */ + + return_ACPI_STATUS (AE_TYPE); + } + break; + + + case ACPI_TYPE_PROCESSOR: + + ExternalObject->Processor.ProcId = + InternalObject->Processor.ProcId; + ExternalObject->Processor.PblkAddress = + InternalObject->Processor.Address; + ExternalObject->Processor.PblkLength = + InternalObject->Processor.Length; + break; + + + case ACPI_TYPE_POWER: + + ExternalObject->PowerResource.SystemLevel = + InternalObject->PowerResource.SystemLevel; + + ExternalObject->PowerResource.ResourceOrder = + InternalObject->PowerResource.ResourceOrder; + break; + + + default: + /* + * There is no corresponding external object type + */ + ACPI_ERROR ((AE_INFO, + "Unsupported object type, cannot convert to external object: %s", + AcpiUtGetTypeName (InternalObject->Common.Type))); + + return_ACPI_STATUS (AE_SUPPORT); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIelementToEelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIelementToEelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; + ACPI_SIZE ObjectSpace; + UINT32 ThisIndex; + ACPI_OBJECT *TargetObject; + + + ACPI_FUNCTION_ENTRY (); + + + ThisIndex = State->Pkg.Index; + TargetObject = (ACPI_OBJECT *) + &((ACPI_OBJECT *)(State->Pkg.DestObject))->Package.Elements[ThisIndex]; + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * This is a simple or null object + */ + Status = AcpiUtCopyIsimpleToEsimple (SourceObject, + TargetObject, Info->FreeSpace, &ObjectSpace); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * Build the package object + */ + TargetObject->Type = ACPI_TYPE_PACKAGE; + TargetObject->Package.Count = SourceObject->Package.Count; + TargetObject->Package.Elements = + ACPI_CAST_PTR (ACPI_OBJECT, Info->FreeSpace); + + /* + * Pass the new package object back to the package walk routine + */ + State->Pkg.ThisTargetObj = TargetObject; + + /* + * Save space for the array of objects (Package elements) + * update the buffer length counter + */ + ObjectSpace = ACPI_ROUND_UP_TO_NATIVE_WORD ( + (ACPI_SIZE) TargetObject->Package.Count * + sizeof (ACPI_OBJECT)); + break; + + + default: + return (AE_BAD_PARAMETER); + } + + Info->FreeSpace += ObjectSpace; + Info->Length += ObjectSpace; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIpackageToEpackage + * + * PARAMETERS: InternalObject - Pointer to the object we are returning + * Buffer - Where the object is returned + * SpaceUsed - Where the object length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to place a package object in a user + * buffer. A package object by definition contains other objects. + * + * The buffer is assumed to have sufficient space for the object. + * The caller must have verified the buffer length needed using + * the AcpiUtGetObjectSize function before calling this function. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIpackageToEpackage ( + ACPI_OPERAND_OBJECT *InternalObject, + UINT8 *Buffer, + ACPI_SIZE *SpaceUsed) +{ + ACPI_OBJECT *ExternalObject; + ACPI_STATUS Status; + ACPI_PKG_INFO Info; + + + ACPI_FUNCTION_TRACE (UtCopyIpackageToEpackage); + + + /* + * First package at head of the buffer + */ + ExternalObject = ACPI_CAST_PTR (ACPI_OBJECT, Buffer); + + /* + * Free space begins right after the first package + */ + Info.Length = ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + Info.FreeSpace = Buffer + ACPI_ROUND_UP_TO_NATIVE_WORD ( + sizeof (ACPI_OBJECT)); + Info.ObjectSpace = 0; + Info.NumPackages = 1; + + ExternalObject->Type = InternalObject->Common.Type; + ExternalObject->Package.Count = InternalObject->Package.Count; + ExternalObject->Package.Elements = ACPI_CAST_PTR (ACPI_OBJECT, + Info.FreeSpace); + + /* + * Leave room for an array of ACPI_OBJECTS in the buffer + * and move the free space past it + */ + Info.Length += (ACPI_SIZE) ExternalObject->Package.Count * + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + Info.FreeSpace += ExternalObject->Package.Count * + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)); + + Status = AcpiUtWalkPackageTree (InternalObject, ExternalObject, + AcpiUtCopyIelementToEelement, &Info); + + *SpaceUsed = Info.Length; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIobjectToEobject + * + * PARAMETERS: InternalObject - The internal object to be converted + * RetBuffer - Where the object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to build an API object to be returned + * to the caller. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyIobjectToEobject ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_BUFFER *RetBuffer) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtCopyIobjectToEobject); + + + if (InternalObject->Common.Type == ACPI_TYPE_PACKAGE) + { + /* + * Package object: Copy all subobjects (including + * nested packages) + */ + Status = AcpiUtCopyIpackageToEpackage (InternalObject, + RetBuffer->Pointer, &RetBuffer->Length); + } + else + { + /* + * Build a simple object (no nested objects) + */ + Status = AcpiUtCopyIsimpleToEsimple (InternalObject, + ACPI_CAST_PTR (ACPI_OBJECT, RetBuffer->Pointer), + ACPI_ADD_PTR (UINT8, RetBuffer->Pointer, + ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))), + &RetBuffer->Length); + /* + * build simple does not include the object size in the length + * so we add it in here + */ + RetBuffer->Length += sizeof (ACPI_OBJECT); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEsimpleToIsimple + * + * PARAMETERS: ExternalObject - The external object to be converted + * RetInternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: This function copies an external object to an internal one. + * NOTE: Pointers can be copied, we don't need to copy data. + * (The pointers have to be valid in our address space no matter + * what we do with them!) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyEsimpleToIsimple ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **RetInternalObject) +{ + ACPI_OPERAND_OBJECT *InternalObject; + + + ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple); + + + /* + * Simple types supported are: String, Buffer, Integer + */ + switch (ExternalObject->Type) + { + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_LOCAL_REFERENCE: + + InternalObject = AcpiUtCreateInternalObject ( + (UINT8) ExternalObject->Type); + if (!InternalObject) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + break; + + case ACPI_TYPE_ANY: /* This is the case for a NULL object */ + + *RetInternalObject = NULL; + return_ACPI_STATUS (AE_OK); + + default: + /* All other types are not supported */ + + ACPI_ERROR ((AE_INFO, + "Unsupported object type, cannot convert to internal object: %s", + AcpiUtGetTypeName (ExternalObject->Type))); + + return_ACPI_STATUS (AE_SUPPORT); + } + + + /* Must COPY string and buffer contents */ + + switch (ExternalObject->Type) + { + case ACPI_TYPE_STRING: + + InternalObject->String.Pointer = + ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) + ExternalObject->String.Length + 1); + + if (!InternalObject->String.Pointer) + { + goto ErrorExit; + } + + ACPI_MEMCPY (InternalObject->String.Pointer, + ExternalObject->String.Pointer, + ExternalObject->String.Length); + + InternalObject->String.Length = ExternalObject->String.Length; + break; + + + case ACPI_TYPE_BUFFER: + + InternalObject->Buffer.Pointer = + ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length); + if (!InternalObject->Buffer.Pointer) + { + goto ErrorExit; + } + + ACPI_MEMCPY (InternalObject->Buffer.Pointer, + ExternalObject->Buffer.Pointer, + ExternalObject->Buffer.Length); + + InternalObject->Buffer.Length = ExternalObject->Buffer.Length; + + /* Mark buffer data valid */ + + InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID; + break; + + + case ACPI_TYPE_INTEGER: + + InternalObject->Integer.Value = ExternalObject->Integer.Value; + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + + /* TBD: should validate incoming handle */ + + InternalObject->Reference.Class = ACPI_REFCLASS_NAME; + InternalObject->Reference.Node = ExternalObject->Reference.Handle; + break; + + default: + /* Other types can't get here */ + break; + } + + *RetInternalObject = InternalObject; + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + AcpiUtRemoveReference (InternalObject); + return_ACPI_STATUS (AE_NO_MEMORY); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEpackageToIpackage + * + * PARAMETERS: ExternalObject - The external object to be converted + * InternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Copy an external package object to an internal package. + * Handles nested packages. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyEpackageToIpackage ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject) +{ + ACPI_STATUS Status = AE_OK; + ACPI_OPERAND_OBJECT *PackageObject; + ACPI_OPERAND_OBJECT **PackageElements; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtCopyEpackageToIpackage); + + + /* Create the package object */ + + PackageObject = AcpiUtCreatePackageObject (ExternalObject->Package.Count); + if (!PackageObject) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + PackageElements = PackageObject->Package.Elements; + + /* + * Recursive implementation. Probably ok, since nested external packages + * as parameters should be very rare. + */ + for (i = 0; i < ExternalObject->Package.Count; i++) + { + Status = AcpiUtCopyEobjectToIobject ( + &ExternalObject->Package.Elements[i], + &PackageElements[i]); + if (ACPI_FAILURE (Status)) + { + /* Truncate package and delete it */ + + PackageObject->Package.Count = i; + PackageElements[i] = NULL; + AcpiUtRemoveReference (PackageObject); + return_ACPI_STATUS (Status); + } + } + + /* Mark package data valid */ + + PackageObject->Package.Flags |= AOPOBJ_DATA_VALID; + + *InternalObject = PackageObject; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyEobjectToIobject + * + * PARAMETERS: ExternalObject - The external object to be converted + * InternalObject - Where the internal object is returned + * + * RETURN: Status + * + * DESCRIPTION: Converts an external object to an internal object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyEobjectToIobject ( + ACPI_OBJECT *ExternalObject, + ACPI_OPERAND_OBJECT **InternalObject) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtCopyEobjectToIobject); + + + if (ExternalObject->Type == ACPI_TYPE_PACKAGE) + { + Status = AcpiUtCopyEpackageToIpackage (ExternalObject, InternalObject); + } + else + { + /* + * Build a simple object (no nested objects) + */ + Status = AcpiUtCopyEsimpleToIsimple (ExternalObject, InternalObject); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopySimpleObject + * + * PARAMETERS: SourceDesc - The internal object to be copied + * DestDesc - New target object + * + * RETURN: Status + * + * DESCRIPTION: Simple copy of one internal object to another. Reference count + * of the destination object is preserved. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopySimpleObject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *DestDesc) +{ + UINT16 ReferenceCount; + ACPI_OPERAND_OBJECT *NextObject; + ACPI_STATUS Status; + ACPI_SIZE CopySize; + + + /* Save fields from destination that we don't want to overwrite */ + + ReferenceCount = DestDesc->Common.ReferenceCount; + NextObject = DestDesc->Common.NextObject; + + /* + * Copy the entire source object over the destination object. + * Note: Source can be either an operand object or namespace node. + */ + CopySize = sizeof (ACPI_OPERAND_OBJECT); + if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED) + { + CopySize = sizeof (ACPI_NAMESPACE_NODE); + } + + ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc), + ACPI_CAST_PTR (char, SourceDesc), CopySize); + + /* Restore the saved fields */ + + DestDesc->Common.ReferenceCount = ReferenceCount; + DestDesc->Common.NextObject = NextObject; + + /* New object is not static, regardless of source */ + + DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER; + + /* Handle the objects with extra data */ + + switch (DestDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + /* + * Allocate and copy the actual buffer if and only if: + * 1) There is a valid buffer pointer + * 2) The buffer has a length > 0 + */ + if ((SourceDesc->Buffer.Pointer) && + (SourceDesc->Buffer.Length)) + { + DestDesc->Buffer.Pointer = + ACPI_ALLOCATE (SourceDesc->Buffer.Length); + if (!DestDesc->Buffer.Pointer) + { + return (AE_NO_MEMORY); + } + + /* Copy the actual buffer data */ + + ACPI_MEMCPY (DestDesc->Buffer.Pointer, + SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length); + } + break; + + case ACPI_TYPE_STRING: + /* + * Allocate and copy the actual string if and only if: + * 1) There is a valid string pointer + * (Pointer to a NULL string is allowed) + */ + if (SourceDesc->String.Pointer) + { + DestDesc->String.Pointer = + ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1); + if (!DestDesc->String.Pointer) + { + return (AE_NO_MEMORY); + } + + /* Copy the actual string data */ + + ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer, + (ACPI_SIZE) SourceDesc->String.Length + 1); + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * We copied the reference object, so we now must add a reference + * to the object pointed to by the reference + * + * DDBHandle reference (from Load/LoadTable) is a special reference, + * it does not have a Reference.Object, so does not need to + * increase the reference count + */ + if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE) + { + break; + } + + AcpiUtAddReference (SourceDesc->Reference.Object); + break; + + case ACPI_TYPE_REGION: + /* + * We copied the Region Handler, so we now must add a reference + */ + if (DestDesc->Region.Handler) + { + AcpiUtAddReference (DestDesc->Region.Handler); + } + break; + + /* + * For Mutex and Event objects, we cannot simply copy the underlying + * OS object. We must create a new one. + */ + case ACPI_TYPE_MUTEX: + + Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + case ACPI_TYPE_EVENT: + + Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0, + &DestDesc->Event.OsSemaphore); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + break; + + default: + /* Nothing to do for other simple objects */ + break; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIelementToIelement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Copy one package element to another package element + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIelementToIelement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + UINT32 ThisIndex; + ACPI_OPERAND_OBJECT **ThisTargetPtr; + ACPI_OPERAND_OBJECT *TargetObject; + + + ACPI_FUNCTION_ENTRY (); + + + ThisIndex = State->Pkg.Index; + ThisTargetPtr = (ACPI_OPERAND_OBJECT **) + &State->Pkg.DestObject->Package.Elements[ThisIndex]; + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* A null source object indicates a (legal) null package element */ + + if (SourceObject) + { + /* + * This is a simple object, just copy it + */ + TargetObject = AcpiUtCreateInternalObject ( + SourceObject->Common.Type); + if (!TargetObject) + { + return (AE_NO_MEMORY); + } + + Status = AcpiUtCopySimpleObject (SourceObject, TargetObject); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + *ThisTargetPtr = TargetObject; + } + else + { + /* Pass through a null element */ + + *ThisTargetPtr = NULL; + } + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* + * This object is a package - go down another nesting level + * Create and build the package object + */ + TargetObject = AcpiUtCreatePackageObject (SourceObject->Package.Count); + if (!TargetObject) + { + return (AE_NO_MEMORY); + } + + TargetObject->Common.Flags = SourceObject->Common.Flags; + + /* Pass the new package object back to the package walk routine */ + + State->Pkg.ThisTargetObj = TargetObject; + + /* Store the object pointer in the parent package object */ + + *ThisTargetPtr = TargetObject; + break; + + + default: + return (AE_BAD_PARAMETER); + } + + return (Status); + +ErrorExit: + AcpiUtRemoveReference (TargetObject); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIpackageToIpackage + * + * PARAMETERS: SourceObj - Pointer to the source package object + * DestObj - Where the internal object is returned + * WalkState - Current Walk state descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to copy an internal package object + * into another internal package object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCopyIpackageToIpackage ( + ACPI_OPERAND_OBJECT *SourceObj, + ACPI_OPERAND_OBJECT *DestObj, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIpackageToIpackage); + + + DestObj->Common.Type = SourceObj->Common.Type; + DestObj->Common.Flags = SourceObj->Common.Flags; + DestObj->Package.Count = SourceObj->Package.Count; + + /* + * Create the object array and walk the source package tree + */ + DestObj->Package.Elements = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) SourceObj->Package.Count + 1) * + sizeof (void *)); + if (!DestObj->Package.Elements) + { + ACPI_ERROR ((AE_INFO, "Package allocation failure")); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* + * Copy the package element-by-element by walking the package "tree". + * This handles nested packages of arbitrary depth. + */ + Status = AcpiUtWalkPackageTree (SourceObj, DestObj, + AcpiUtCopyIelementToIelement, WalkState); + if (ACPI_FAILURE (Status)) + { + /* On failure, delete the destination package object */ + + AcpiUtRemoveReference (DestObj); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCopyIobjectToIobject + * + * PARAMETERS: SourceDesc - The internal object to be copied + * DestDesc - Where the copied object is returned + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Copy an internal object to a new internal object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCopyIobjectToIobject ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT **DestDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (UtCopyIobjectToIobject); + + + /* Create the top level object */ + + *DestDesc = AcpiUtCreateInternalObject (SourceDesc->Common.Type); + if (!*DestDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the object and possible subobjects */ + + if (SourceDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + Status = AcpiUtCopyIpackageToIpackage (SourceDesc, *DestDesc, + WalkState); + } + else + { + Status = AcpiUtCopySimpleObject (SourceDesc, *DestDesc); + } + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/utilities/utdebug.c b/source/components/utilities/utdebug.c new file mode 100644 index 0000000..051d47b --- /dev/null +++ b/source/components/utilities/utdebug.c @@ -0,0 +1,741 @@ +/****************************************************************************** + * + * Module Name: utdebug - Debug print routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDEBUG_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdebug") + + +#ifdef ACPI_DEBUG_OUTPUT + +static ACPI_THREAD_ID AcpiGbl_PrevThreadId = (ACPI_THREAD_ID) 0xFFFFFFFF; +static char *AcpiGbl_FnEntryStr = "----Entry"; +static char *AcpiGbl_FnExitStr = "----Exit-"; + +/* Local prototypes */ + +static const char * +AcpiUtTrimFunctionName ( + const char *FunctionName); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitStackPtrTrace + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer at subsystem startup + * + ******************************************************************************/ + +void +AcpiUtInitStackPtrTrace ( + void) +{ + ACPI_SIZE CurrentSp; + + + AcpiGbl_EntryStackPointer = &CurrentSp; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrackStackPtr + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer + * + ******************************************************************************/ + +void +AcpiUtTrackStackPtr ( + void) +{ + ACPI_SIZE CurrentSp; + + + if (&CurrentSp < AcpiGbl_LowestStackPointer) + { + AcpiGbl_LowestStackPointer = &CurrentSp; + } + + if (AcpiGbl_NestingLevel > AcpiGbl_DeepestNesting) + { + AcpiGbl_DeepestNesting = AcpiGbl_NestingLevel; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrimFunctionName + * + * PARAMETERS: FunctionName - Ascii string containing a procedure name + * + * RETURN: Updated pointer to the function name + * + * DESCRIPTION: Remove the "Acpi" prefix from the function name, if present. + * This allows compiler macros such as __FUNCTION__ to be used + * with no change to the debug output. + * + ******************************************************************************/ + +static const char * +AcpiUtTrimFunctionName ( + const char *FunctionName) +{ + + /* All Function names are longer than 4 chars, check is safe */ + + if (*(ACPI_CAST_PTR (UINT32, FunctionName)) == ACPI_PREFIX_MIXED) + { + /* This is the case where the original source has not been modified */ + + return (FunctionName + 4); + } + + if (*(ACPI_CAST_PTR (UINT32, FunctionName)) == ACPI_PREFIX_LOWER) + { + /* This is the case where the source has been 'linuxized' */ + + return (FunctionName + 5); + } + + return (FunctionName); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDebugPrint + * + * PARAMETERS: RequestedDebugLevel - Requested debug print level + * LineNumber - Caller's line number (for error output) + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print error message with prefix consisting of the module name, + * line number, and component ID. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrint ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) +{ + ACPI_THREAD_ID ThreadId; + va_list args; + + + /* + * Stay silent if the debug level or component ID is disabled + */ + if (!(RequestedDebugLevel & AcpiDbgLevel) || + !(ComponentId & AcpiDbgLayer)) + { + return; + } + + /* + * Thread tracking and context switch notification + */ + ThreadId = AcpiOsGetThreadId (); + if (ThreadId != AcpiGbl_PrevThreadId) + { + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ( + "\n**** Context Switch from TID %u to TID %u ****\n\n", + (UINT32) AcpiGbl_PrevThreadId, (UINT32) ThreadId); + } + + AcpiGbl_PrevThreadId = ThreadId; + } + + /* + * Display the module name, current line number, thread ID (if requested), + * current procedure nesting level, and the current procedure name + */ + AcpiOsPrintf ("%8s-%04ld ", ModuleName, LineNumber); + + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ("[%u] ", (UINT32) ThreadId); + } + + AcpiOsPrintf ("[%02ld] %-22.22s: ", + AcpiGbl_NestingLevel, AcpiUtTrimFunctionName (FunctionName)); + + va_start (args, Format); + AcpiOsVprintf (Format, args); + va_end (args); +} + +ACPI_EXPORT_SYMBOL (AcpiDebugPrint) + + +/******************************************************************************* + * + * FUNCTION: AcpiDebugPrintRaw + * + * PARAMETERS: RequestedDebugLevel - Requested debug print level + * LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Format - Printf format field + * ... - Optional printf arguments + * + * RETURN: None + * + * DESCRIPTION: Print message with no headers. Has same interface as + * DebugPrint so that the same macros can be used. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrintRaw ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...) +{ + va_list args; + + + if (!(RequestedDebugLevel & AcpiDbgLevel) || + !(ComponentId & AcpiDbgLayer)) + { + return; + } + + va_start (args, Format); + AcpiOsVprintf (Format, args); + va_end (args); +} + +ACPI_EXPORT_SYMBOL (AcpiDebugPrintRaw) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrace + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTrace ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FnEntryStr); +} + +ACPI_EXPORT_SYMBOL (AcpiUtTrace) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTracePtr + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Pointer - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTracePtr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + void *Pointer) +{ + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FnEntryStr, Pointer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTraceStr + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * String - Additional string to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTraceStr ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + char *String) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FnEntryStr, String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTraceU32 + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Integer - Integer to display + * + * RETURN: None + * + * DESCRIPTION: Function entry trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtTraceU32 ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT32 Integer) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %08X\n", AcpiGbl_FnEntryStr, Integer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel + * + ******************************************************************************/ + +void +AcpiUtExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FnExitStr); + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStatusExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Status - Exit status code + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit status also. + * + ******************************************************************************/ + +void +AcpiUtStatusExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + ACPI_STATUS Status) +{ + + if (ACPI_SUCCESS (Status)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FnExitStr, + AcpiFormatException (Status)); + } + else + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s ****Exception****: %s\n", AcpiGbl_FnExitStr, + AcpiFormatException (Status)); + } + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtStatusExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValueExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Value - Value to be printed with exit msg + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit value also. + * + ******************************************************************************/ + +void +AcpiUtValueExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT64 Value) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %8.8X%8.8X\n", AcpiGbl_FnExitStr, + ACPI_FORMAT_UINT64 (Value)); + + AcpiGbl_NestingLevel--; +} + +ACPI_EXPORT_SYMBOL (AcpiUtValueExit) + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPtrExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * Ptr - Pointer to display + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit value also. + * + ******************************************************************************/ + +void +AcpiUtPtrExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + UINT8 *Ptr) +{ + + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FnExitStr, Ptr); + + AcpiGbl_NestingLevel--; +} + +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * ComponentID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDumpBuffer2 ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display) +{ + UINT32 i = 0; + UINT32 j; + UINT32 Temp32; + UINT8 BufChar; + + + if (!Buffer) + { + AcpiOsPrintf ("Null Buffer Pointer in DumpBuffer!\n"); + return; + } + + if ((Count < 4) || (Count & 0x01)) + { + Display = DB_BYTE_DISPLAY; + } + + /* Nasty little dump buffer routine! */ + + while (i < Count) + { + /* Print current offset */ + + AcpiOsPrintf ("%6.4X: ", i); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) + { + if (i + j >= Count) + { + /* Dump fill spaces */ + + AcpiOsPrintf ("%*s", ((Display * 2) + 1), " "); + j += Display; + continue; + } + + switch (Display) + { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + AcpiOsPrintf ("%02X ", Buffer[(ACPI_SIZE) i + j]); + break; + + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%04X ", Temp32); + break; + + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%08X ", Temp32); + break; + + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + AcpiOsPrintf ("%08X", Temp32); + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j + 4]); + AcpiOsPrintf ("%08X ", Temp32); + break; + } + + j += Display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + AcpiOsPrintf (" "); + for (j = 0; j < 16; j++) + { + if (i + j >= Count) + { + AcpiOsPrintf ("\n"); + return; + } + + BufChar = Buffer[(ACPI_SIZE) i + j]; + if (ACPI_IS_PRINT (BufChar)) + { + AcpiOsPrintf ("%c", BufChar); + } + else + { + AcpiOsPrintf ("."); + } + } + + /* Done with that line. */ + + AcpiOsPrintf ("\n"); + i += 16; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display + * ComponentID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 ComponentId) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & AcpiDbgLevel) && + (ComponentId & AcpiDbgLayer))) + { + return; + } + + AcpiUtDumpBuffer2 (Buffer, Count, Display); +} + + diff --git a/source/components/utilities/utdecode.c b/source/components/utilities/utdecode.c new file mode 100644 index 0000000..718d73d --- /dev/null +++ b/source/components/utilities/utdecode.c @@ -0,0 +1,637 @@ +/****************************************************************************** + * + * Module Name: utdecode - Utility decoding routines (value-to-string) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDECODE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdecode") + + +/******************************************************************************* + * + * FUNCTION: AcpiFormatException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. A valid pointer is + * always returned. + * + * DESCRIPTION: This function translates an ACPI exception into an ASCII string + * It is here instead of utxface.c so it is always present. + * + ******************************************************************************/ + +const char * +AcpiFormatException ( + ACPI_STATUS Status) +{ + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + Exception = AcpiUtValidateException (Status); + if (!Exception) + { + /* Exception code was not recognized */ + + ACPI_ERROR ((AE_INFO, + "Unknown exception code: 0x%8.8X", Status)); + + Exception = "UNKNOWN_STATUS_CODE"; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} + +ACPI_EXPORT_SYMBOL (AcpiFormatException) + + +/* + * Properties of the ACPI Object Types, both internal and external. + * The table is indexed by values of ACPI_OBJECT_TYPE + */ +const UINT8 AcpiGbl_NsProperties[ACPI_NUM_NS_TYPES] = +{ + ACPI_NS_NORMAL, /* 00 Any */ + ACPI_NS_NORMAL, /* 01 Number */ + ACPI_NS_NORMAL, /* 02 String */ + ACPI_NS_NORMAL, /* 03 Buffer */ + ACPI_NS_NORMAL, /* 04 Package */ + ACPI_NS_NORMAL, /* 05 FieldUnit */ + ACPI_NS_NEWSCOPE, /* 06 Device */ + ACPI_NS_NORMAL, /* 07 Event */ + ACPI_NS_NEWSCOPE, /* 08 Method */ + ACPI_NS_NORMAL, /* 09 Mutex */ + ACPI_NS_NORMAL, /* 10 Region */ + ACPI_NS_NEWSCOPE, /* 11 Power */ + ACPI_NS_NEWSCOPE, /* 12 Processor */ + ACPI_NS_NEWSCOPE, /* 13 Thermal */ + ACPI_NS_NORMAL, /* 14 BufferField */ + ACPI_NS_NORMAL, /* 15 DdbHandle */ + ACPI_NS_NORMAL, /* 16 Debug Object */ + ACPI_NS_NORMAL, /* 17 DefField */ + ACPI_NS_NORMAL, /* 18 BankField */ + ACPI_NS_NORMAL, /* 19 IndexField */ + ACPI_NS_NORMAL, /* 20 Reference */ + ACPI_NS_NORMAL, /* 21 Alias */ + ACPI_NS_NORMAL, /* 22 MethodAlias */ + ACPI_NS_NORMAL, /* 23 Notify */ + ACPI_NS_NORMAL, /* 24 Address Handler */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 25 Resource Desc */ + ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL, /* 26 Resource Field */ + ACPI_NS_NEWSCOPE, /* 27 Scope */ + ACPI_NS_NORMAL, /* 28 Extra */ + ACPI_NS_NORMAL, /* 29 Data */ + ACPI_NS_NORMAL /* 30 Invalid */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtHexToAsciiChar + * + * PARAMETERS: Integer - Contains the hex digit + * Position - bit position of the digit within the + * integer (multiple of 4) + * + * RETURN: The converted Ascii character + * + * DESCRIPTION: Convert a hex digit to an Ascii character + * + ******************************************************************************/ + +/* Hex to ASCII conversion table */ + +static const char AcpiGbl_HexToAscii[] = +{ + '0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F' +}; + +char +AcpiUtHexToAsciiChar ( + UINT64 Integer, + UINT32 Position) +{ + + return (AcpiGbl_HexToAscii[(Integer >> Position) & 0xF]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetRegionName + * + * PARAMETERS: Space ID - ID for the region + * + * RETURN: Decoded region SpaceId name + * + * DESCRIPTION: Translate a Space ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Region type decoding */ + +const char *AcpiGbl_RegionTypes[ACPI_NUM_PREDEFINED_REGIONS] = +{ + "SystemMemory", + "SystemIO", + "PCI_Config", + "EmbeddedControl", + "SMBus", + "SystemCMOS", + "PCIBARTarget", + "IPMI", + "GeneralPurposeIo", + "GenericSerialBus" +}; + + +char * +AcpiUtGetRegionName ( + UINT8 SpaceId) +{ + + if (SpaceId >= ACPI_USER_REGION_BEGIN) + { + return ("UserDefinedRegion"); + } + else if (SpaceId == ACPI_ADR_SPACE_DATA_TABLE) + { + return ("DataTable"); + } + else if (SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE) + { + return ("FunctionalFixedHW"); + } + else if (SpaceId >= ACPI_NUM_PREDEFINED_REGIONS) + { + return ("InvalidSpaceId"); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_RegionTypes[SpaceId])); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetEventName + * + * PARAMETERS: EventId - Fixed event ID + * + * RETURN: Decoded event ID name + * + * DESCRIPTION: Translate a Event ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Event type decoding */ + +static const char *AcpiGbl_EventTypes[ACPI_NUM_FIXED_EVENTS] = +{ + "PM_Timer", + "GlobalLock", + "PowerButton", + "SleepButton", + "RealTimeClock", +}; + + +char * +AcpiUtGetEventName ( + UINT32 EventId) +{ + + if (EventId > ACPI_EVENT_MAX) + { + return ("InvalidEventID"); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_EventTypes[EventId])); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetTypeName + * + * PARAMETERS: Type - An ACPI object type + * + * RETURN: Decoded ACPI object type name + * + * DESCRIPTION: Translate a Type ID into a name string (Debug only) + * + ******************************************************************************/ + +/* + * Elements of AcpiGbl_NsTypeNames below must match + * one-to-one with values of ACPI_OBJECT_TYPE + * + * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; + * when stored in a table it really means that we have thus far seen no + * evidence to indicate what type is actually going to be stored for this entry. + */ +static const char AcpiGbl_BadType[] = "UNDEFINED"; + +/* Printable names of the ACPI object types */ + +static const char *AcpiGbl_NsTypeNames[] = +{ + /* 00 */ "Untyped", + /* 01 */ "Integer", + /* 02 */ "String", + /* 03 */ "Buffer", + /* 04 */ "Package", + /* 05 */ "FieldUnit", + /* 06 */ "Device", + /* 07 */ "Event", + /* 08 */ "Method", + /* 09 */ "Mutex", + /* 10 */ "Region", + /* 11 */ "Power", + /* 12 */ "Processor", + /* 13 */ "Thermal", + /* 14 */ "BufferField", + /* 15 */ "DdbHandle", + /* 16 */ "DebugObject", + /* 17 */ "RegionField", + /* 18 */ "BankField", + /* 19 */ "IndexField", + /* 20 */ "Reference", + /* 21 */ "Alias", + /* 22 */ "MethodAlias", + /* 23 */ "Notify", + /* 24 */ "AddrHandler", + /* 25 */ "ResourceDesc", + /* 26 */ "ResourceFld", + /* 27 */ "Scope", + /* 28 */ "Extra", + /* 29 */ "Data", + /* 30 */ "Invalid" +}; + + +char * +AcpiUtGetTypeName ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type > ACPI_TYPE_INVALID) + { + return (ACPI_CAST_PTR (char, AcpiGbl_BadType)); + } + + return (ACPI_CAST_PTR (char, AcpiGbl_NsTypeNames[Type])); +} + + +char * +AcpiUtGetObjectTypeName ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + + if (!ObjDesc) + { + return ("[NULL Object Descriptor]"); + } + + return (AcpiUtGetTypeName (ObjDesc->Common.Type)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetNodeName + * + * PARAMETERS: Object - A namespace node + * + * RETURN: ASCII name of the node + * + * DESCRIPTION: Validate the node and return the node's ACPI name. + * + ******************************************************************************/ + +char * +AcpiUtGetNodeName ( + void *Object) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) Object; + + + /* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */ + + if (!Object) + { + return ("NULL"); + } + + /* Check for Root node */ + + if ((Object == ACPI_ROOT_OBJECT) || + (Object == AcpiGbl_RootNode)) + { + return ("\"\\\" "); + } + + /* Descriptor must be a namespace node */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + return ("####"); + } + + /* + * Ensure name is valid. The name was validated/repaired when the node + * was created, but make sure it has not been corrupted. + */ + AcpiUtRepairName (Node->Name.Ascii); + + /* Return the name */ + + return (Node->Name.Ascii); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetDescriptorName + * + * PARAMETERS: Object - An ACPI object + * + * RETURN: Decoded name of the descriptor type + * + * DESCRIPTION: Validate object and return the descriptor type + * + ******************************************************************************/ + +/* Printable names of object descriptor types */ + +static const char *AcpiGbl_DescTypeNames[] = +{ + /* 00 */ "Not a Descriptor", + /* 01 */ "Cached", + /* 02 */ "State-Generic", + /* 03 */ "State-Update", + /* 04 */ "State-Package", + /* 05 */ "State-Control", + /* 06 */ "State-RootParseScope", + /* 07 */ "State-ParseScope", + /* 08 */ "State-WalkScope", + /* 09 */ "State-Result", + /* 10 */ "State-Notify", + /* 11 */ "State-Thread", + /* 12 */ "Walk", + /* 13 */ "Parser", + /* 14 */ "Operand", + /* 15 */ "Node" +}; + + +char * +AcpiUtGetDescriptorName ( + void *Object) +{ + + if (!Object) + { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) > ACPI_DESC_TYPE_MAX) + { + return ("Not a Descriptor"); + } + + return (ACPI_CAST_PTR (char, + AcpiGbl_DescTypeNames[ACPI_GET_DESCRIPTOR_TYPE (Object)])); + +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetReferenceName + * + * PARAMETERS: Object - An ACPI reference object + * + * RETURN: Decoded name of the type of reference + * + * DESCRIPTION: Decode a reference object sub-type to a string. + * + ******************************************************************************/ + +/* Printable names of reference object sub-types */ + +static const char *AcpiGbl_RefClassNames[] = +{ + /* 00 */ "Local", + /* 01 */ "Argument", + /* 02 */ "RefOf", + /* 03 */ "Index", + /* 04 */ "DdbHandle", + /* 05 */ "Named Object", + /* 06 */ "Debug" +}; + +const char * +AcpiUtGetReferenceName ( + ACPI_OPERAND_OBJECT *Object) +{ + + if (!Object) + { + return ("NULL Object"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) + { + return ("Not an Operand object"); + } + + if (Object->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) + { + return ("Not a Reference object"); + } + + if (Object->Reference.Class > ACPI_REFCLASS_MAX) + { + return ("Unknown Reference class"); + } + + return (AcpiGbl_RefClassNames[Object->Reference.Class]); +} + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetMutexName + * + * PARAMETERS: MutexId - The predefined ID for this mutex. + * + * RETURN: Decoded name of the internal mutex + * + * DESCRIPTION: Translate a mutex ID into a name string (Debug only) + * + ******************************************************************************/ + +/* Names for internal mutex objects, used for debug output */ + +static char *AcpiGbl_MutexNames[ACPI_NUM_MUTEX] = +{ + "ACPI_MTX_Interpreter", + "ACPI_MTX_Namespace", + "ACPI_MTX_Tables", + "ACPI_MTX_Events", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", + "ACPI_MTX_CommandComplete", + "ACPI_MTX_CommandReady" +}; + +char * +AcpiUtGetMutexName ( + UINT32 MutexId) +{ + + if (MutexId > ACPI_MAX_MUTEX) + { + return ("Invalid Mutex ID"); + } + + return (AcpiGbl_MutexNames[MutexId]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetNotifyName + * + * PARAMETERS: NotifyValue - Value from the Notify() request + * + * RETURN: Decoded name for the notify value + * + * DESCRIPTION: Translate a Notify Value to a notify namestring. + * + ******************************************************************************/ + +/* Names for Notify() values, used for debug output */ + +static const char *AcpiGbl_NotifyValueNames[ACPI_NOTIFY_MAX + 1] = +{ + /* 00 */ "Bus Check", + /* 01 */ "Device Check", + /* 02 */ "Device Wake", + /* 03 */ "Eject Request", + /* 04 */ "Device Check Light", + /* 05 */ "Frequency Mismatch", + /* 06 */ "Bus Mode Mismatch", + /* 07 */ "Power Fault", + /* 08 */ "Capabilities Check", + /* 09 */ "Device PLD Check", + /* 10 */ "Reserved", + /* 11 */ "System Locality Update", + /* 12 */ "Shutdown Request" +}; + +const char * +AcpiUtGetNotifyName ( + UINT32 NotifyValue) +{ + + if (NotifyValue <= ACPI_NOTIFY_MAX) + { + return (AcpiGbl_NotifyValueNames[NotifyValue]); + } + else if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) + { + return ("Reserved"); + } + else if (NotifyValue <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) + { + return ("Device Specific"); + } + else + { + return ("Hardware Specific"); + } +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidObjectType + * + * PARAMETERS: Type - Object type to be validated + * + * RETURN: TRUE if valid object type, FALSE otherwise + * + * DESCRIPTION: Validate an object type + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidObjectType ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type > ACPI_TYPE_LOCAL_MAX) + { + /* Note: Assumes all TYPEs are contiguous (external/local) */ + + return (FALSE); + } + + return (TRUE); +} diff --git a/source/components/utilities/utdelete.c b/source/components/utilities/utdelete.c new file mode 100644 index 0000000..90baa15 --- /dev/null +++ b/source/components/utilities/utdelete.c @@ -0,0 +1,766 @@ +/******************************************************************************* + * + * Module Name: utdelete - object deletion and reference count utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTDELETE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdelete") + +/* Local prototypes */ + +static void +AcpiUtDeleteInternalObj ( + ACPI_OPERAND_OBJECT *Object); + +static void +AcpiUtUpdateRefCount ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Action); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteInternalObj + * + * PARAMETERS: Object - Object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Low level object deletion, after reference counts have been + * updated (All reference counts, including sub-objects!) + * + ******************************************************************************/ + +static void +AcpiUtDeleteInternalObj ( + ACPI_OPERAND_OBJECT *Object) +{ + void *ObjPointer = NULL; + ACPI_OPERAND_OBJECT *HandlerDesc; + ACPI_OPERAND_OBJECT *SecondDesc; + ACPI_OPERAND_OBJECT *NextDesc; + ACPI_OPERAND_OBJECT **LastObjPtr; + + + ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object); + + + if (!Object) + { + return_VOID; + } + + /* + * Must delete or free any pointers within the object that are not + * actual ACPI objects (for example, a raw buffer pointer). + */ + switch (Object->Common.Type) + { + case ACPI_TYPE_STRING: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n", + Object, Object->String.Pointer)); + + /* Free the actual string buffer */ + + if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) + { + /* But only if it is NOT a pointer into an ACPI table */ + + ObjPointer = Object->String.Pointer; + } + break; + + + case ACPI_TYPE_BUFFER: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n", + Object, Object->Buffer.Pointer)); + + /* Free the actual buffer */ + + if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) + { + /* But only if it is NOT a pointer into an ACPI table */ + + ObjPointer = Object->Buffer.Pointer; + } + break; + + + case ACPI_TYPE_PACKAGE: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n", + Object->Package.Count)); + + /* + * Elements of the package are not handled here, they are deleted + * separately + */ + + /* Free the (variable length) element pointer array */ + + ObjPointer = Object->Package.Elements; + break; + + + /* + * These objects have a possible list of notify handlers. + * Device object also may have a GPE block. + */ + case ACPI_TYPE_DEVICE: + + if (Object->Device.GpeBlock) + { + (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock); + } + + /*lint -fallthrough */ + + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Walk the notify handler list for this object */ + + HandlerDesc = Object->CommonNotify.Handler; + while (HandlerDesc) + { + NextDesc = HandlerDesc->AddressSpace.Next; + AcpiUtRemoveReference (HandlerDesc); + HandlerDesc = NextDesc; + } + break; + + + case ACPI_TYPE_MUTEX: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Mutex %p, OS Mutex %p\n", + Object, Object->Mutex.OsMutex)); + + if (Object == AcpiGbl_GlobalLockMutex) + { + /* Global Lock has extra semaphore */ + + (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore); + AcpiGbl_GlobalLockSemaphore = NULL; + + AcpiOsDeleteMutex (Object->Mutex.OsMutex); + AcpiGbl_GlobalLockMutex = NULL; + } + else + { + AcpiExUnlinkMutex (Object); + AcpiOsDeleteMutex (Object->Mutex.OsMutex); + } + break; + + + case ACPI_TYPE_EVENT: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Event %p, OS Semaphore %p\n", + Object, Object->Event.OsSemaphore)); + + (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore); + Object->Event.OsSemaphore = NULL; + break; + + + case ACPI_TYPE_METHOD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Method %p\n", Object)); + + /* Delete the method mutex if it exists */ + + if (Object->Method.Mutex) + { + AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex); + AcpiUtDeleteObjectDesc (Object->Method.Mutex); + Object->Method.Mutex = NULL; + } + break; + + + case ACPI_TYPE_REGION: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Region %p\n", Object)); + + /* + * Update AddressRange list. However, only permanent regions + * are installed in this list. (Not created within a method) + */ + if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY)) + { + AcpiUtRemoveAddressRange (Object->Region.SpaceId, + Object->Region.Node); + } + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + /* + * Free the RegionContext if and only if the handler is one of the + * default handlers -- and therefore, we created the context object + * locally, it was not created by an external caller. + */ + HandlerDesc = Object->Region.Handler; + if (HandlerDesc) + { + NextDesc = HandlerDesc->AddressSpace.RegionList; + LastObjPtr = &HandlerDesc->AddressSpace.RegionList; + + /* Remove the region object from the handler's list */ + + while (NextDesc) + { + if (NextDesc == Object) + { + *LastObjPtr = NextDesc->Region.Next; + break; + } + + /* Walk the linked list of handler */ + + LastObjPtr = &NextDesc->Region.Next; + NextDesc = NextDesc->Region.Next; + } + + if (HandlerDesc->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + { + /* Deactivate region and free region context */ + + if (HandlerDesc->AddressSpace.Setup) + { + (void) HandlerDesc->AddressSpace.Setup (Object, + ACPI_REGION_DEACTIVATE, + HandlerDesc->AddressSpace.Context, + &SecondDesc->Extra.RegionContext); + } + } + + AcpiUtRemoveReference (HandlerDesc); + } + + /* Now we can free the Extra object */ + + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + case ACPI_TYPE_BUFFER_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Buffer Field %p\n", Object)); + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Bank Field %p\n", Object)); + + SecondDesc = AcpiNsGetSecondaryObject (Object); + if (SecondDesc) + { + AcpiUtDeleteObjectDesc (SecondDesc); + } + break; + + + default: + break; + } + + /* Free any allocated memory (pointer within the object) found above */ + + if (ObjPointer) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", + ObjPointer)); + ACPI_FREE (ObjPointer); + } + + /* Now the object can be safely deleted */ + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", + Object, AcpiUtGetObjectTypeName (Object))); + + AcpiUtDeleteObjectDesc (Object); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteInternalObjectList + * + * PARAMETERS: ObjList - Pointer to the list to be deleted + * + * RETURN: None + * + * DESCRIPTION: This function deletes an internal object list, including both + * simple objects and package objects + * + ******************************************************************************/ + +void +AcpiUtDeleteInternalObjectList ( + ACPI_OPERAND_OBJECT **ObjList) +{ + ACPI_OPERAND_OBJECT **InternalObj; + + + ACPI_FUNCTION_TRACE (UtDeleteInternalObjectList); + + + /* Walk the null-terminated internal list */ + + for (InternalObj = ObjList; *InternalObj; InternalObj++) + { + AcpiUtRemoveReference (*InternalObj); + } + + /* Free the combined parameter pointer list and object array */ + + ACPI_FREE (ObjList); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateRefCount + * + * PARAMETERS: Object - Object whose ref count is to be updated + * Action - What to do + * + * RETURN: New ref count + * + * DESCRIPTION: Modify the ref count and return it. + * + ******************************************************************************/ + +static void +AcpiUtUpdateRefCount ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Action) +{ + UINT16 Count; + UINT16 NewCount; + + + ACPI_FUNCTION_NAME (UtUpdateRefCount); + + + if (!Object) + { + return; + } + + Count = Object->Common.ReferenceCount; + NewCount = Count; + + /* + * Perform the reference count action (increment, decrement, force delete) + */ + switch (Action) + { + case REF_INCREMENT: + + NewCount++; + Object->Common.ReferenceCount = NewCount; + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Incremented]\n", + Object, NewCount)); + break; + + case REF_DECREMENT: + + if (Count < 1) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, can't decrement! (Set to 0)\n", + Object, NewCount)); + + NewCount = 0; + } + else + { + NewCount--; + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, [Decremented]\n", + Object, NewCount)); + } + + if (Object->Common.Type == ACPI_TYPE_METHOD) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount)); + } + + Object->Common.ReferenceCount = NewCount; + if (NewCount == 0) + { + AcpiUtDeleteInternalObj (Object); + } + break; + + case REF_FORCE_DELETE: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count)); + + NewCount = 0; + Object->Common.ReferenceCount = NewCount; + AcpiUtDeleteInternalObj (Object); + break; + + default: + + ACPI_ERROR ((AE_INFO, "Unknown action (0x%X)", Action)); + break; + } + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + if (Count > ACPI_MAX_REFERENCE_COUNT) + { + ACPI_WARNING ((AE_INFO, + "Large Reference Count (0x%X) in object %p", Count, Object)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateObjectReference + * + * PARAMETERS: Object - Increment ref count for this object + * and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT or + * REF_FORCE_DELETE + * + * RETURN: Status + * + * DESCRIPTION: Increment the object reference count + * + * Object references are incremented when: + * 1) An object is attached to a Node (namespace object) + * 2) An object is copied (all subobjects must be incremented) + * + * Object references are decremented when: + * 1) An object is detached from an Node + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtUpdateObjectReference ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *StateList = NULL; + ACPI_OPERAND_OBJECT *NextObject = NULL; + ACPI_GENERIC_STATE *State; + UINT32 i; + + + ACPI_FUNCTION_TRACE_PTR (UtUpdateObjectReference, Object); + + + while (Object) + { + /* Make sure that this isn't a namespace handle */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) + { + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Object %p is NS handle\n", Object)); + return_ACPI_STATUS (AE_OK); + } + + /* + * All sub-objects must have their reference count incremented also. + * Different object types have different subobjects. + */ + switch (Object->Common.Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + case ACPI_TYPE_THERMAL: + + /* Update the notify objects for these types (if present) */ + + AcpiUtUpdateRefCount (Object->CommonNotify.SystemNotify, Action); + AcpiUtUpdateRefCount (Object->CommonNotify.DeviceNotify, Action); + break; + + case ACPI_TYPE_PACKAGE: + /* + * We must update all the sub-objects of the package, + * each of whom may have their own sub-objects. + */ + for (i = 0; i < Object->Package.Count; i++) + { + /* + * Push each element onto the stack for later processing. + * Note: There can be null elements within the package, + * these are simply ignored + */ + Status = AcpiUtCreateUpdateStateAndPush ( + Object->Package.Elements[i], Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + } + break; + + case ACPI_TYPE_BUFFER_FIELD: + + NextObject = Object->BufferField.BufferObj; + break; + + case ACPI_TYPE_LOCAL_REGION_FIELD: + + NextObject = Object->Field.RegionObj; + break; + + case ACPI_TYPE_LOCAL_BANK_FIELD: + + NextObject = Object->BankField.BankObj; + Status = AcpiUtCreateUpdateStateAndPush ( + Object->BankField.RegionObj, Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + break; + + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + NextObject = Object->IndexField.IndexObj; + Status = AcpiUtCreateUpdateStateAndPush ( + Object->IndexField.DataObj, Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + break; + + case ACPI_TYPE_LOCAL_REFERENCE: + /* + * The target of an Index (a package, string, or buffer) or a named + * reference must track changes to the ref count of the index or + * target object. + */ + if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || + (Object->Reference.Class== ACPI_REFCLASS_NAME)) + { + NextObject = Object->Reference.Object; + } + break; + + case ACPI_TYPE_REGION: + default: + break; /* No subobjects for all other types */ + } + + /* + * Now we can update the count in the main object. This can only + * happen after we update the sub-objects in case this causes the + * main object to be deleted. + */ + AcpiUtUpdateRefCount (Object, Action); + Object = NULL; + + /* Move on to the next object to be updated */ + + if (NextObject) + { + Object = NextObject; + NextObject = NULL; + } + else if (StateList) + { + State = AcpiUtPopGenericState (&StateList); + Object = State->Update.Object; + AcpiUtDeleteGenericState (State); + } + } + + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not update object reference count")); + + /* Free any stacked Update State objects */ + + while (StateList) + { + State = AcpiUtPopGenericState (&StateList); + AcpiUtDeleteGenericState (State); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAddReference + * + * PARAMETERS: Object - Object whose reference count is to be + * incremented + * + * RETURN: None + * + * DESCRIPTION: Add one reference to an ACPI object + * + ******************************************************************************/ + +void +AcpiUtAddReference ( + ACPI_OPERAND_OBJECT *Object) +{ + + ACPI_FUNCTION_TRACE_PTR (UtAddReference, Object); + + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return_VOID; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Incremented]\n", + Object, Object->Common.ReferenceCount)); + + /* Increment the reference count */ + + (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveReference + * + * PARAMETERS: Object - Object whose ref count will be decremented + * + * RETURN: None + * + * DESCRIPTION: Decrement the reference count of an ACPI internal object + * + ******************************************************************************/ + +void +AcpiUtRemoveReference ( + ACPI_OPERAND_OBJECT *Object) +{ + + ACPI_FUNCTION_TRACE_PTR (UtRemoveReference, Object); + + + /* + * Allow a NULL pointer to be passed in, just ignore it. This saves + * each caller from having to check. Also, ignore NS nodes. + * + */ + if (!Object || + (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)) + + { + return_VOID; + } + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return_VOID; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Current Refs=%X [To Be Decremented]\n", + Object, Object->Common.ReferenceCount)); + + /* + * Decrement the reference count, and only actually delete the object + * if the reference count becomes 0. (Must also decrement the ref count + * of all subobjects!) + */ + (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT); + return_VOID; +} + + diff --git a/source/components/utilities/uteval.c b/source/components/utilities/uteval.c new file mode 100644 index 0000000..0bcb894 --- /dev/null +++ b/source/components/utilities/uteval.c @@ -0,0 +1,370 @@ +/****************************************************************************** + * + * Module Name: uteval - Object evaluation + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTEVAL_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("uteval") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtEvaluateObject + * + * PARAMETERS: PrefixNode - Starting node + * Path - Path to object from starting node + * ExpectedReturnTypes - Bitmap of allowed return types + * ReturnDesc - Where a return value is stored + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a namespace object and verifies the type of the + * return object. Common code that simplifies accessing objects + * that have required return objects of fixed types. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtEvaluateObject ( + ACPI_NAMESPACE_NODE *PrefixNode, + char *Path, + UINT32 ExpectedReturnBtypes, + ACPI_OPERAND_OBJECT **ReturnDesc) +{ + ACPI_EVALUATE_INFO *Info; + ACPI_STATUS Status; + UINT32 ReturnBtype; + + + ACPI_FUNCTION_TRACE (UtEvaluateObject); + + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Info->PrefixNode = PrefixNode; + Info->Pathname = Path; + + /* Evaluate the object/method */ + + Status = AcpiNsEvaluate (Info); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", + AcpiUtGetNodeName (PrefixNode), Path)); + } + else + { + ACPI_ERROR_METHOD ("Method execution failed", + PrefixNode, Path, Status); + } + + goto Cleanup; + } + + /* Did we get a return object? */ + + if (!Info->ReturnObject) + { + if (ExpectedReturnBtypes) + { + ACPI_ERROR_METHOD ("No object was returned from", + PrefixNode, Path, AE_NOT_EXIST); + + Status = AE_NOT_EXIST; + } + + goto Cleanup; + } + + /* Map the return object type to the bitmapped type */ + + switch ((Info->ReturnObject)->Common.Type) + { + case ACPI_TYPE_INTEGER: + ReturnBtype = ACPI_BTYPE_INTEGER; + break; + + case ACPI_TYPE_BUFFER: + ReturnBtype = ACPI_BTYPE_BUFFER; + break; + + case ACPI_TYPE_STRING: + ReturnBtype = ACPI_BTYPE_STRING; + break; + + case ACPI_TYPE_PACKAGE: + ReturnBtype = ACPI_BTYPE_PACKAGE; + break; + + default: + ReturnBtype = 0; + break; + } + + if ((AcpiGbl_EnableInterpreterSlack) && + (!ExpectedReturnBtypes)) + { + /* + * We received a return object, but one was not expected. This can + * happen frequently if the "implicit return" feature is enabled. + * Just delete the return object and return AE_OK. + */ + AcpiUtRemoveReference (Info->ReturnObject); + goto Cleanup; + } + + /* Is the return object one of the expected types? */ + + if (!(ExpectedReturnBtypes & ReturnBtype)) + { + ACPI_ERROR_METHOD ("Return object type is incorrect", + PrefixNode, Path, AE_TYPE); + + ACPI_ERROR ((AE_INFO, + "Type returned from %s was incorrect: %s, expected Btypes: 0x%X", + Path, AcpiUtGetObjectTypeName (Info->ReturnObject), + ExpectedReturnBtypes)); + + /* On error exit, we must delete the return object */ + + AcpiUtRemoveReference (Info->ReturnObject); + Status = AE_TYPE; + goto Cleanup; + } + + /* Object type is OK, return it */ + + *ReturnDesc = Info->ReturnObject; + +Cleanup: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtEvaluateNumericObject + * + * PARAMETERS: ObjectName - Object name to be evaluated + * DeviceNode - Node for the device + * Value - Where the value is returned + * + * RETURN: Status + * + * DESCRIPTION: Evaluates a numeric namespace object for a selected device + * and stores result in *Value. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtEvaluateNumericObject ( + char *ObjectName, + ACPI_NAMESPACE_NODE *DeviceNode, + UINT64 *Value) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtEvaluateNumericObject); + + + Status = AcpiUtEvaluateObject (DeviceNode, ObjectName, + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the returned Integer */ + + *Value = ObjDesc->Integer.Value; + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_STA + * + * PARAMETERS: DeviceNode - Node for the device + * Flags - Where the status flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_STA ( + ACPI_NAMESPACE_NODE *DeviceNode, + UINT32 *Flags) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_STA); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__STA, + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + if (AE_NOT_FOUND == Status) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "_STA on %4.4s was not found, assuming device is present\n", + AcpiUtGetNodeName (DeviceNode))); + + *Flags = ACPI_UINT32_MAX; + Status = AE_OK; + } + + return_ACPI_STATUS (Status); + } + + /* Extract the status flags */ + + *Flags = (UINT32) ObjDesc->Integer.Value; + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecutePowerMethods + * + * PARAMETERS: DeviceNode - Node for the device + * MethodNames - Array of power method names + * MethodCount - Number of methods to execute + * OutValues - Where the power method values are returned + * + * RETURN: Status, OutValues + * + * DESCRIPTION: Executes the specified power methods for the device and returns + * the result(s). + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecutePowerMethods ( + ACPI_NAMESPACE_NODE *DeviceNode, + const char **MethodNames, + UINT8 MethodCount, + UINT8 *OutValues) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + ACPI_STATUS FinalStatus = AE_NOT_FOUND; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtExecutePowerMethods); + + + for (i = 0; i < MethodCount; i++) + { + /* + * Execute the power method (_SxD or _SxW). The only allowable + * return type is an Integer. + */ + Status = AcpiUtEvaluateObject (DeviceNode, + ACPI_CAST_PTR (char, MethodNames[i]), + ACPI_BTYPE_INTEGER, &ObjDesc); + if (ACPI_SUCCESS (Status)) + { + OutValues[i] = (UINT8) ObjDesc->Integer.Value; + + /* Delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + FinalStatus = AE_OK; /* At least one value is valid */ + continue; + } + + OutValues[i] = ACPI_UINT8_MAX; + if (Status == AE_NOT_FOUND) + { + continue; /* Ignore if not found */ + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Failed %s on Device %4.4s, %s\n", + ACPI_CAST_PTR (char, MethodNames[i]), + AcpiUtGetNodeName (DeviceNode), AcpiFormatException (Status))); + } + + return_ACPI_STATUS (FinalStatus); +} diff --git a/source/components/utilities/utglobal.c b/source/components/utilities/utglobal.c new file mode 100644 index 0000000..faccfb2 --- /dev/null +++ b/source/components/utilities/utglobal.c @@ -0,0 +1,365 @@ +/****************************************************************************** + * + * Module Name: utglobal - Global variables for the ACPI subsystem + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTGLOBAL_C__ +#define DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utglobal") + + +/******************************************************************************* + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* + * We want the debug switches statically initialized so they + * are already set when the debugger is entered. + */ + +/* Debug switch - level and trace mask */ + +#ifdef ACPI_DEBUG_OUTPUT +UINT32 AcpiDbgLevel = ACPI_DEBUG_DEFAULT; +#else +UINT32 AcpiDbgLevel = ACPI_NORMAL_DEFAULT; +#endif + +/* Debug switch - layer (component) mask */ + +UINT32 AcpiDbgLayer = ACPI_COMPONENT_DEFAULT; +UINT32 AcpiGbl_NestingLevel = 0; + +/* Debugger globals */ + +BOOLEAN AcpiGbl_DbTerminateThreads = FALSE; +BOOLEAN AcpiGbl_AbortMethod = FALSE; +BOOLEAN AcpiGbl_MethodExecuting = FALSE; + +/* System flags */ + +UINT32 AcpiGbl_StartupFlags = 0; + +/* System starts uninitialized */ + +BOOLEAN AcpiGbl_Shutdown = TRUE; + +const char *AcpiGbl_SleepStateNames[ACPI_S_STATE_COUNT] = +{ + "\\_S0_", + "\\_S1_", + "\\_S2_", + "\\_S3_", + "\\_S4_", + "\\_S5_" +}; + +const char *AcpiGbl_LowestDstateNames[ACPI_NUM_SxW_METHODS] = +{ + "_S0W", + "_S1W", + "_S2W", + "_S3W", + "_S4W" +}; + +const char *AcpiGbl_HighestDstateNames[ACPI_NUM_SxD_METHODS] = +{ + "_S1D", + "_S2D", + "_S3D", + "_S4D" +}; + + +/******************************************************************************* + * + * Namespace globals + * + ******************************************************************************/ + +/* + * Predefined ACPI Names (Built-in to the Interpreter) + * + * NOTES: + * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run + * during the initialization sequence. + * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to + * perform a Notify() operation on it. 09/2010: Changed to type Device. + * This still allows notifies, but does not confuse host code that + * searches for valid ThermalZone objects. + */ +const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames[] = +{ + {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_SB_", ACPI_TYPE_DEVICE, NULL}, + {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL}, + {"_TZ_", ACPI_TYPE_DEVICE, NULL}, + {"_REV", ACPI_TYPE_INTEGER, (char *) ACPI_CA_SUPPORT_LEVEL}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, (char *) 1}, + +#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) + {"_OSI", ACPI_TYPE_METHOD, (char *) 1}, +#endif + + /* Table terminator */ + + {NULL, ACPI_TYPE_ANY, NULL} +}; + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * Event and Hardware globals + * + ******************************************************************************/ + +ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG] = +{ + /* Name Parent Register Register Bit Position Register Bit Mask */ + + /* ACPI_BITREG_TIMER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_TIMER_STATUS, ACPI_BITMASK_TIMER_STATUS}, + /* ACPI_BITREG_BUS_MASTER_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_BUS_MASTER_STATUS, ACPI_BITMASK_BUS_MASTER_STATUS}, + /* ACPI_BITREG_GLOBAL_LOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_STATUS}, + /* ACPI_BITREG_POWER_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_STATUS}, + /* ACPI_BITREG_SLEEP_BUTTON_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_STATUS}, + /* ACPI_BITREG_RT_CLOCK_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_STATUS}, + /* ACPI_BITREG_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_WAKE_STATUS, ACPI_BITMASK_WAKE_STATUS}, + /* ACPI_BITREG_PCIEXP_WAKE_STATUS */ {ACPI_REGISTER_PM1_STATUS, ACPI_BITPOSITION_PCIEXP_WAKE_STATUS, ACPI_BITMASK_PCIEXP_WAKE_STATUS}, + + /* ACPI_BITREG_TIMER_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_TIMER_ENABLE, ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_BITREG_GLOBAL_LOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_BITREG_POWER_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_BITREG_SLEEP_BUTTON_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_BITREG_RT_CLOCK_ENABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_ENABLE}, + /* ACPI_BITREG_PCIEXP_WAKE_DISABLE */ {ACPI_REGISTER_PM1_ENABLE, ACPI_BITPOSITION_PCIEXP_WAKE_DISABLE, ACPI_BITMASK_PCIEXP_WAKE_DISABLE}, + + /* ACPI_BITREG_SCI_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SCI_ENABLE, ACPI_BITMASK_SCI_ENABLE}, + /* ACPI_BITREG_BUS_MASTER_RLD */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_BUS_MASTER_RLD, ACPI_BITMASK_BUS_MASTER_RLD}, + /* ACPI_BITREG_GLOBAL_LOCK_RELEASE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_GLOBAL_LOCK_RELEASE, ACPI_BITMASK_GLOBAL_LOCK_RELEASE}, + /* ACPI_BITREG_SLEEP_TYPE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_TYPE, ACPI_BITMASK_SLEEP_TYPE}, + /* ACPI_BITREG_SLEEP_ENABLE */ {ACPI_REGISTER_PM1_CONTROL, ACPI_BITPOSITION_SLEEP_ENABLE, ACPI_BITMASK_SLEEP_ENABLE}, + + /* ACPI_BITREG_ARB_DIS */ {ACPI_REGISTER_PM2_CONTROL, ACPI_BITPOSITION_ARB_DISABLE, ACPI_BITMASK_ARB_DISABLE} +}; + + +ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS] = +{ + /* ACPI_EVENT_PMTIMER */ {ACPI_BITREG_TIMER_STATUS, ACPI_BITREG_TIMER_ENABLE, ACPI_BITMASK_TIMER_STATUS, ACPI_BITMASK_TIMER_ENABLE}, + /* ACPI_EVENT_GLOBAL */ {ACPI_BITREG_GLOBAL_LOCK_STATUS, ACPI_BITREG_GLOBAL_LOCK_ENABLE, ACPI_BITMASK_GLOBAL_LOCK_STATUS, ACPI_BITMASK_GLOBAL_LOCK_ENABLE}, + /* ACPI_EVENT_POWER_BUTTON */ {ACPI_BITREG_POWER_BUTTON_STATUS, ACPI_BITREG_POWER_BUTTON_ENABLE, ACPI_BITMASK_POWER_BUTTON_STATUS, ACPI_BITMASK_POWER_BUTTON_ENABLE}, + /* ACPI_EVENT_SLEEP_BUTTON */ {ACPI_BITREG_SLEEP_BUTTON_STATUS, ACPI_BITREG_SLEEP_BUTTON_ENABLE, ACPI_BITMASK_SLEEP_BUTTON_STATUS, ACPI_BITMASK_SLEEP_BUTTON_ENABLE}, + /* ACPI_EVENT_RTC */ {ACPI_BITREG_RT_CLOCK_STATUS, ACPI_BITREG_RT_CLOCK_ENABLE, ACPI_BITMASK_RT_CLOCK_STATUS, ACPI_BITMASK_RT_CLOCK_ENABLE}, +}; +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitGlobals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Init ACPICA globals. All globals that require specific + * initialization should be initialized here! + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitGlobals ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtInitGlobals); + + + /* Create all memory caches */ + + Status = AcpiUtCreateCaches (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Address Range lists */ + + for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) + { + AcpiGbl_AddressRangeList[i] = NULL; + } + + /* Mutex locked flags */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + AcpiGbl_MutexInfo[i].Mutex = NULL; + AcpiGbl_MutexInfo[i].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + AcpiGbl_MutexInfo[i].UseCount = 0; + } + + for (i = 0; i < ACPI_NUM_OWNERID_MASKS; i++) + { + AcpiGbl_OwnerIdMask[i] = 0; + } + + /* Last OwnerID is never valid */ + + AcpiGbl_OwnerIdMask[ACPI_NUM_OWNERID_MASKS - 1] = 0x80000000; + + /* Event counters */ + + AcpiMethodCount = 0; + AcpiSciCount = 0; + AcpiGpeCount = 0; + + for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) + { + AcpiFixedEventCount[i] = 0; + } + +#if (!ACPI_REDUCED_HARDWARE) + + /* GPE support */ + + AcpiGbl_AllGpesInitialized = FALSE; + AcpiGbl_GpeXruptListHead = NULL; + AcpiGbl_GpeFadtBlocks[0] = NULL; + AcpiGbl_GpeFadtBlocks[1] = NULL; + AcpiCurrentGpeCount = 0; + + AcpiGbl_GlobalEventHandler = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Global handlers */ + + AcpiGbl_SystemNotify.Handler = NULL; + AcpiGbl_DeviceNotify.Handler = NULL; + AcpiGbl_ExceptionHandler = NULL; + AcpiGbl_InitHandler = NULL; + AcpiGbl_TableHandler = NULL; + AcpiGbl_InterfaceHandler = NULL; + + /* Global Lock support */ + + AcpiGbl_GlobalLockSemaphore = NULL; + AcpiGbl_GlobalLockMutex = NULL; + AcpiGbl_GlobalLockAcquired = FALSE; + AcpiGbl_GlobalLockHandle = 0; + AcpiGbl_GlobalLockPresent = FALSE; + + /* Miscellaneous variables */ + + AcpiGbl_DSDT = NULL; + AcpiGbl_CmSingleStep = FALSE; + AcpiGbl_DbTerminateThreads = FALSE; + AcpiGbl_Shutdown = FALSE; + AcpiGbl_NsLookupCount = 0; + AcpiGbl_PsFindCount = 0; + AcpiGbl_AcpiHardwarePresent = TRUE; + AcpiGbl_LastOwnerIdIndex = 0; + AcpiGbl_NextOwnerIdOffset = 0; + AcpiGbl_TraceMethodName = 0; + AcpiGbl_TraceDbgLevel = 0; + AcpiGbl_TraceDbgLayer = 0; + AcpiGbl_DebuggerConfiguration = DEBUGGER_THREADING; + AcpiGbl_DbOutputFlags = ACPI_DB_CONSOLE_OUTPUT; + AcpiGbl_OsiData = 0; + AcpiGbl_OsiMutex = NULL; + AcpiGbl_RegMethodsExecuted = FALSE; + + /* Hardware oriented */ + + AcpiGbl_EventsInitialized = FALSE; + AcpiGbl_SystemAwakeAndRunning = TRUE; + + /* Namespace */ + + AcpiGbl_ModuleCodeList = NULL; + AcpiGbl_RootNode = NULL; + AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME; + AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED; + AcpiGbl_RootNodeStruct.Type = ACPI_TYPE_DEVICE; + AcpiGbl_RootNodeStruct.Parent = NULL; + AcpiGbl_RootNodeStruct.Child = NULL; + AcpiGbl_RootNodeStruct.Peer = NULL; + AcpiGbl_RootNodeStruct.Object = NULL; + + +#ifdef ACPI_DISASSEMBLER + AcpiGbl_ExternalList = NULL; +#endif + +#ifdef ACPI_DEBUG_OUTPUT + AcpiGbl_LowestStackPointer = ACPI_CAST_PTR (ACPI_SIZE, ACPI_SIZE_MAX); +#endif + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + AcpiGbl_DisplayFinalMemStats = FALSE; + AcpiGbl_DisableMemTracking = FALSE; +#endif + + return_ACPI_STATUS (AE_OK); +} + +/* Public globals */ + +ACPI_EXPORT_SYMBOL (AcpiGbl_FADT) +ACPI_EXPORT_SYMBOL (AcpiDbgLevel) +ACPI_EXPORT_SYMBOL (AcpiDbgLayer) +ACPI_EXPORT_SYMBOL (AcpiGpeCount) +ACPI_EXPORT_SYMBOL (AcpiCurrentGpeCount) diff --git a/source/components/utilities/utids.c b/source/components/utilities/utids.c new file mode 100644 index 0000000..226d8c1 --- /dev/null +++ b/source/components/utilities/utids.c @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Module Name: utids - support for device IDs - HID, UID, CID + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTIDS_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utids") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_HID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the string HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. The HID is either an 32-bit encoded EISAID + * Integer or a String. A string is always returned. An EISAID + * is converted to a string. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_HID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID *Hid; + UINT32 Length; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_HID); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__HID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + Length = ACPI_EISAID_STRING_SIZE; + } + else + { + Length = ObjDesc->String.Length + 1; + } + + /* Allocate a buffer for the HID */ + + Hid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Hid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after DEVICE_ID struct */ + + Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_DEVICE_ID)); + + /* Convert EISAID to a string or simply copy existing string */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + AcpiExEisaIdToString (Hid->String, ObjDesc->Integer.Value); + } + else + { + ACPI_STRCPY (Hid->String, ObjDesc->String.Pointer); + } + + Hid->Length = Length; + *ReturnId = Hid; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_UID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the string UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the unique + * ID of the device. The UID is either a 64-bit Integer (NOT an + * EISAID) or a string. Always returns a string. A 64-bit integer + * is converted to a decimal string. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_UID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID *Uid; + UINT32 Length; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtExecute_UID); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__UID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + Length = ACPI_MAX64_DECIMAL_DIGITS + 1; + } + else + { + Length = ObjDesc->String.Length + 1; + } + + /* Allocate a buffer for the UID */ + + Uid = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Uid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after DEVICE_ID struct */ + + Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_DEVICE_ID)); + + /* Convert an Integer to string, or just copy an existing string */ + + if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) + { + AcpiExIntegerToString (Uid->String, ObjDesc->Integer.Value); + } + else + { + ACPI_STRCPY (Uid->String, ObjDesc->String.Pointer); + } + + Uid->Length = Length; + *ReturnId = Uid; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_CID + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnCidList - Where the CID list is returned + * + * RETURN: Status, list of CID strings + * + * DESCRIPTION: Executes the _CID control method that returns one or more + * compatible hardware IDs for the device. + * + * NOTE: Internal function, no parameter validation + * + * A _CID method can return either a single compatible ID or a package of + * compatible IDs. Each compatible ID can be one of the following: + * 1) Integer (32 bit compressed EISA ID) or + * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") + * + * The Integer CIDs are converted to string format by this function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_CID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_DEVICE_ID_LIST **ReturnCidList) +{ + ACPI_OPERAND_OBJECT **CidObjects; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_DEVICE_ID_LIST *CidList; + char *NextIdString; + UINT32 StringAreaSize; + UINT32 Length; + UINT32 CidListSize; + ACPI_STATUS Status; + UINT32 Count; + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtExecute_CID); + + + /* Evaluate the _CID method for this device */ + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING | ACPI_BTYPE_PACKAGE, + &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Get the count and size of the returned _CIDs. _CID can return either + * a Package of Integers/Strings or a single Integer or String. + * Note: This section also validates that all CID elements are of the + * correct type (Integer or String). + */ + if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + Count = ObjDesc->Package.Count; + CidObjects = ObjDesc->Package.Elements; + } + else /* Single Integer or String CID */ + { + Count = 1; + CidObjects = &ObjDesc; + } + + StringAreaSize = 0; + for (i = 0; i < Count; i++) + { + /* String lengths include null terminator */ + + switch (CidObjects[i]->Common.Type) + { + case ACPI_TYPE_INTEGER: + StringAreaSize += ACPI_EISAID_STRING_SIZE; + break; + + case ACPI_TYPE_STRING: + StringAreaSize += CidObjects[i]->String.Length + 1; + break; + + default: + Status = AE_TYPE; + goto Cleanup; + } + } + + /* + * Now that we know the length of the CIDs, allocate return buffer: + * 1) Size of the base structure + + * 2) Size of the CID DEVICE_ID array + + * 3) Size of the actual CID strings + */ + CidListSize = sizeof (ACPI_DEVICE_ID_LIST) + + ((Count - 1) * sizeof (ACPI_DEVICE_ID)) + + StringAreaSize; + + CidList = ACPI_ALLOCATE_ZEROED (CidListSize); + if (!CidList) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for CID strings starts after the CID DEVICE_ID array */ + + NextIdString = ACPI_CAST_PTR (char, CidList->Ids) + + ((ACPI_SIZE) Count * sizeof (ACPI_DEVICE_ID)); + + /* Copy/convert the CIDs to the return buffer */ + + for (i = 0; i < Count; i++) + { + if (CidObjects[i]->Common.Type == ACPI_TYPE_INTEGER) + { + /* Convert the Integer (EISAID) CID to a string */ + + AcpiExEisaIdToString (NextIdString, CidObjects[i]->Integer.Value); + Length = ACPI_EISAID_STRING_SIZE; + } + else /* ACPI_TYPE_STRING */ + { + /* Copy the String CID from the returned object */ + + ACPI_STRCPY (NextIdString, CidObjects[i]->String.Pointer); + Length = CidObjects[i]->String.Length + 1; + } + + CidList->Ids[i].String = NextIdString; + CidList->Ids[i].Length = Length; + NextIdString += Length; + } + + /* Finish the CID list */ + + CidList->Count = Count; + CidList->ListSize = CidListSize; + *ReturnCidList = CidList; + + +Cleanup: + + /* On exit, we must delete the _CID return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} + diff --git a/source/components/utilities/utinit.c b/source/components/utilities/utinit.c new file mode 100644 index 0000000..6831595 --- /dev/null +++ b/source/components/utilities/utinit.c @@ -0,0 +1,192 @@ +/****************************************************************************** + * + * Module Name: utinit - Common ACPI subsystem initialization + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTINIT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" +#include "actables.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utinit") + +/* Local prototypes */ + +static void AcpiUtTerminate ( + void); + +#if (!ACPI_REDUCED_HARDWARE) + +static void +AcpiUtFreeGpeLists ( + void); + +#else + +#define AcpiUtFreeGpeLists() +#endif /* !ACPI_REDUCED_HARDWARE */ + + +#if (!ACPI_REDUCED_HARDWARE) +/****************************************************************************** + * + * FUNCTION: AcpiUtFreeGpeLists + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global GPE lists + * + ******************************************************************************/ + +static void +AcpiUtFreeGpeLists ( + void) +{ + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_BLOCK_INFO *NextGpeBlock; + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_XRUPT_INFO *NextGpeXruptInfo; + + + /* Free global GPE blocks and related info structures */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + NextGpeBlock = GpeBlock->Next; + ACPI_FREE (GpeBlock->EventInfo); + ACPI_FREE (GpeBlock->RegisterInfo); + ACPI_FREE (GpeBlock); + + GpeBlock = NextGpeBlock; + } + NextGpeXruptInfo = GpeXruptInfo->Next; + ACPI_FREE (GpeXruptInfo); + GpeXruptInfo = NextGpeXruptInfo; + } +} +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/****************************************************************************** + * + * FUNCTION: AcpiUtTerminate + * + * PARAMETERS: none + * + * RETURN: none + * + * DESCRIPTION: Free global memory + * + ******************************************************************************/ + +static void +AcpiUtTerminate ( + void) +{ + ACPI_FUNCTION_TRACE (UtTerminate); + + AcpiUtFreeGpeLists (); + AcpiUtDeleteAddressLists (); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtSubsystemShutdown + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Shutdown the various components. Do not delete the mutex + * objects here, because the AML debugger may be still running. + * + ******************************************************************************/ + +void +AcpiUtSubsystemShutdown ( + void) +{ + ACPI_FUNCTION_TRACE (UtSubsystemShutdown); + + +#ifndef ACPI_ASL_COMPILER + + /* Close the AcpiEvent Handling */ + + AcpiEvTerminate (); + + /* Delete any dynamic _OSI interfaces */ + + AcpiUtInterfaceTerminate (); +#endif + + /* Close the Namespace */ + + AcpiNsTerminate (); + + /* Delete the ACPI tables */ + + AcpiTbTerminate (); + + /* Close the globals */ + + AcpiUtTerminate (); + + /* Purge the local caches */ + + (void) AcpiUtDeleteCaches (); + return_VOID; +} + + diff --git a/source/components/utilities/utlock.c b/source/components/utilities/utlock.c new file mode 100644 index 0000000..61585ad --- /dev/null +++ b/source/components/utilities/utlock.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Module Name: utlock - Reader/Writer lock interfaces + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTLOCK_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utlock") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateRwLock + * AcpiUtDeleteRwLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader/writer lock creation and deletion interfaces. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateRwLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Lock->NumReaders = 0; + Status = AcpiOsCreateMutex (&Lock->ReaderMutex); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiOsCreateMutex (&Lock->WriterMutex); + return (Status); +} + + +void +AcpiUtDeleteRwLock ( + ACPI_RW_LOCK *Lock) +{ + + AcpiOsDeleteMutex (Lock->ReaderMutex); + AcpiOsDeleteMutex (Lock->WriterMutex); + + Lock->NumReaders = 0; + Lock->ReaderMutex = NULL; + Lock->WriterMutex = NULL; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireReadLock + * AcpiUtReleaseReadLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Reader interfaces for reader/writer locks. On acquisition, + * only the first reader acquires the write mutex. On release, + * only the last reader releases the write mutex. Although this + * algorithm can in theory starve writers, this should not be a + * problem with ACPICA since the subsystem is infrequently used + * in comparison to (for example) an I/O system. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireReadLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Acquire the write lock only for the first reader */ + + Lock->NumReaders++; + if (Lock->NumReaders == 1) + { + Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER); + } + + AcpiOsReleaseMutex (Lock->ReaderMutex); + return (Status); +} + + +ACPI_STATUS +AcpiUtReleaseReadLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->ReaderMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Release the write lock only for the very last reader */ + + Lock->NumReaders--; + if (Lock->NumReaders == 0) + { + AcpiOsReleaseMutex (Lock->WriterMutex); + } + + AcpiOsReleaseMutex (Lock->ReaderMutex); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireWriteLock + * AcpiUtReleaseWriteLock + * + * PARAMETERS: Lock - Pointer to a valid RW lock + * + * RETURN: Status + * + * DESCRIPTION: Writer interfaces for reader/writer locks. Simply acquire or + * release the writer mutex associated with the lock. Acquisition + * of the lock is fully exclusive and will block all readers and + * writers until it is released. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireWriteLock ( + ACPI_RW_LOCK *Lock) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (Lock->WriterMutex, ACPI_WAIT_FOREVER); + return (Status); +} + + +void +AcpiUtReleaseWriteLock ( + ACPI_RW_LOCK *Lock) +{ + + AcpiOsReleaseMutex (Lock->WriterMutex); +} + diff --git a/source/components/utilities/utmath.c b/source/components/utilities/utmath.c new file mode 100644 index 0000000..d0fad7c --- /dev/null +++ b/source/components/utilities/utmath.c @@ -0,0 +1,379 @@ +/******************************************************************************* + * + * Module Name: utmath - Integer math support routines + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMATH_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmath") + +/* + * Optional support for 64-bit double-precision integer divide. This code + * is configurable and is implemented in order to support 32-bit kernel + * environments where a 64-bit double-precision math library is not available. + * + * Support for a more normal 64-bit divide/modulo (with check for a divide- + * by-zero) appears after this optional section of code. + */ +#ifndef ACPI_USE_NATIVE_DIVIDE + +/* Structures used only for 64-bit divide */ + +typedef struct uint64_struct +{ + UINT32 Lo; + UINT32 Hi; + +} UINT64_STRUCT; + +typedef union uint64_overlay +{ + UINT64 Full; + UINT64_STRUCT Part; + +} UINT64_OVERLAY; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortDivide + * + * PARAMETERS: Dividend - 64-bit dividend + * Divisor - 32-bit divisor + * OutQuotient - Pointer to where the quotient is returned + * OutRemainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a short (maximum 64 bits divided by 32 bits) + * divide and modulo. The result is a 64-bit quotient and a + * 32-bit remainder. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortDivide ( + UINT64 Dividend, + UINT32 Divisor, + UINT64 *OutQuotient, + UINT32 *OutRemainder) +{ + UINT64_OVERLAY DividendOvl; + UINT64_OVERLAY Quotient; + UINT32 Remainder32; + + + ACPI_FUNCTION_TRACE (UtShortDivide); + + + /* Always check for a zero divisor */ + + if (Divisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + DividendOvl.Full = Dividend; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32 (0, DividendOvl.Part.Hi, Divisor, + Quotient.Part.Hi, Remainder32); + ACPI_DIV_64_BY_32 (Remainder32, DividendOvl.Part.Lo, Divisor, + Quotient.Part.Lo, Remainder32); + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = Quotient.Full; + } + if (OutRemainder) + { + *OutRemainder = Remainder32; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDivide + * + * PARAMETERS: InDividend - Dividend + * InDivisor - Divisor + * OutQuotient - Pointer to where the quotient is returned + * OutRemainder - Pointer to where the remainder is returned + * + * RETURN: Status (Checks for divide-by-zero) + * + * DESCRIPTION: Perform a divide and modulo. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtDivide ( + UINT64 InDividend, + UINT64 InDivisor, + UINT64 *OutQuotient, + UINT64 *OutRemainder) +{ + UINT64_OVERLAY Dividend; + UINT64_OVERLAY Divisor; + UINT64_OVERLAY Quotient; + UINT64_OVERLAY Remainder; + UINT64_OVERLAY NormalizedDividend; + UINT64_OVERLAY NormalizedDivisor; + UINT32 Partial1; + UINT64_OVERLAY Partial2; + UINT64_OVERLAY Partial3; + + + ACPI_FUNCTION_TRACE (UtDivide); + + + /* Always check for a zero divisor */ + + if (InDivisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + Divisor.Full = InDivisor; + Dividend.Full = InDividend; + if (Divisor.Part.Hi == 0) + { + /* + * 1) Simplest case is where the divisor is 32 bits, we can + * just do two divides + */ + Remainder.Part.Hi = 0; + + /* + * The quotient is 64 bits, the remainder is always 32 bits, + * and is generated by the second divide. + */ + ACPI_DIV_64_BY_32 (0, Dividend.Part.Hi, Divisor.Part.Lo, + Quotient.Part.Hi, Partial1); + ACPI_DIV_64_BY_32 (Partial1, Dividend.Part.Lo, Divisor.Part.Lo, + Quotient.Part.Lo, Remainder.Part.Lo); + } + + else + { + /* + * 2) The general case where the divisor is a full 64 bits + * is more difficult + */ + Quotient.Part.Hi = 0; + NormalizedDividend = Dividend; + NormalizedDivisor = Divisor; + + /* Normalize the operands (shift until the divisor is < 32 bits) */ + + do + { + ACPI_SHIFT_RIGHT_64 (NormalizedDivisor.Part.Hi, + NormalizedDivisor.Part.Lo); + ACPI_SHIFT_RIGHT_64 (NormalizedDividend.Part.Hi, + NormalizedDividend.Part.Lo); + + } while (NormalizedDivisor.Part.Hi != 0); + + /* Partial divide */ + + ACPI_DIV_64_BY_32 (NormalizedDividend.Part.Hi, + NormalizedDividend.Part.Lo, + NormalizedDivisor.Part.Lo, + Quotient.Part.Lo, Partial1); + + /* + * The quotient is always 32 bits, and simply requires adjustment. + * The 64-bit remainder must be generated. + */ + Partial1 = Quotient.Part.Lo * Divisor.Part.Hi; + Partial2.Full = (UINT64) Quotient.Part.Lo * Divisor.Part.Lo; + Partial3.Full = (UINT64) Partial2.Part.Hi + Partial1; + + Remainder.Part.Hi = Partial3.Part.Lo; + Remainder.Part.Lo = Partial2.Part.Lo; + + if (Partial3.Part.Hi == 0) + { + if (Partial3.Part.Lo >= Dividend.Part.Hi) + { + if (Partial3.Part.Lo == Dividend.Part.Hi) + { + if (Partial2.Part.Lo > Dividend.Part.Lo) + { + Quotient.Part.Lo--; + Remainder.Full -= Divisor.Full; + } + } + else + { + Quotient.Part.Lo--; + Remainder.Full -= Divisor.Full; + } + } + + Remainder.Full = Remainder.Full - Dividend.Full; + Remainder.Part.Hi = (UINT32) -((INT32) Remainder.Part.Hi); + Remainder.Part.Lo = (UINT32) -((INT32) Remainder.Part.Lo); + + if (Remainder.Part.Lo) + { + Remainder.Part.Hi--; + } + } + } + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = Quotient.Full; + } + if (OutRemainder) + { + *OutRemainder = Remainder.Full; + } + + return_ACPI_STATUS (AE_OK); +} + +#else + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortDivide, AcpiUtDivide + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native versions of the UtDivide functions. Use these if either + * 1) The target is a 64-bit platform and therefore 64-bit + * integer math is supported directly by the machine. + * 2) The target is a 32-bit or 16-bit platform, and the + * double-precision integer math library is available to + * perform the divide. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortDivide ( + UINT64 InDividend, + UINT32 Divisor, + UINT64 *OutQuotient, + UINT32 *OutRemainder) +{ + + ACPI_FUNCTION_TRACE (UtShortDivide); + + + /* Always check for a zero divisor */ + + if (Divisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = InDividend / Divisor; + } + if (OutRemainder) + { + *OutRemainder = (UINT32) (InDividend % Divisor); + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_STATUS +AcpiUtDivide ( + UINT64 InDividend, + UINT64 InDivisor, + UINT64 *OutQuotient, + UINT64 *OutRemainder) +{ + ACPI_FUNCTION_TRACE (UtDivide); + + + /* Always check for a zero divisor */ + + if (InDivisor == 0) + { + ACPI_ERROR ((AE_INFO, "Divide by zero")); + return_ACPI_STATUS (AE_AML_DIVIDE_BY_ZERO); + } + + + /* Return only what was requested */ + + if (OutQuotient) + { + *OutQuotient = InDividend / InDivisor; + } + if (OutRemainder) + { + *OutRemainder = InDividend % InDivisor; + } + + return_ACPI_STATUS (AE_OK); +} + +#endif + + diff --git a/source/components/utilities/utmisc.c b/source/components/utilities/utmisc.c new file mode 100644 index 0000000..062c768 --- /dev/null +++ b/source/components/utilities/utmisc.c @@ -0,0 +1,1299 @@ +/******************************************************************************* + * + * Module Name: utmisc - common utility procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMISC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmisc") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateException + * + * PARAMETERS: Status - The ACPI_STATUS code to be formatted + * + * RETURN: A string containing the exception text. NULL if exception is + * not valid. + * + * DESCRIPTION: This function validates and translates an ACPI exception into + * an ASCII string. + * + ******************************************************************************/ + +const char * +AcpiUtValidateException ( + ACPI_STATUS Status) +{ + UINT32 SubStatus; + const char *Exception = NULL; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Status is composed of two parts, a "type" and an actual code + */ + SubStatus = (Status & ~AE_CODE_MASK); + + switch (Status & AE_CODE_MASK) + { + case AE_CODE_ENVIRONMENTAL: + + if (SubStatus <= AE_CODE_ENV_MAX) + { + Exception = AcpiGbl_ExceptionNames_Env [SubStatus]; + } + break; + + case AE_CODE_PROGRAMMER: + + if (SubStatus <= AE_CODE_PGM_MAX) + { + Exception = AcpiGbl_ExceptionNames_Pgm [SubStatus]; + } + break; + + case AE_CODE_ACPI_TABLES: + + if (SubStatus <= AE_CODE_TBL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Tbl [SubStatus]; + } + break; + + case AE_CODE_AML: + + if (SubStatus <= AE_CODE_AML_MAX) + { + Exception = AcpiGbl_ExceptionNames_Aml [SubStatus]; + } + break; + + case AE_CODE_CONTROL: + + if (SubStatus <= AE_CODE_CTRL_MAX) + { + Exception = AcpiGbl_ExceptionNames_Ctrl [SubStatus]; + } + break; + + default: + break; + } + + return (ACPI_CAST_PTR (const char, Exception)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtIsPciRootBridge + * + * PARAMETERS: Id - The HID/CID in string format + * + * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtIsPciRootBridge ( + char *Id) +{ + + /* + * Check if this is a PCI root bridge. + * ACPI 3.0+: check for a PCI Express root also. + */ + if (!(ACPI_STRCMP (Id, + PCI_ROOT_HID_STRING)) || + + !(ACPI_STRCMP (Id, + PCI_EXPRESS_ROOT_HID_STRING))) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtIsAmlTable + * + * PARAMETERS: Table - An ACPI table + * + * RETURN: TRUE if table contains executable AML; FALSE otherwise + * + * DESCRIPTION: Check ACPI Signature for a table that contains AML code. + * Currently, these are DSDT,SSDT,PSDT. All other table types are + * data tables that do not contain AML code. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtIsAmlTable ( + ACPI_TABLE_HEADER *Table) +{ + + /* These are the only tables that contain executable AML */ + + if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_PSDT) || + ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT)) + { + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateOwnerId + * + * PARAMETERS: OwnerId - Where the new owner ID is returned + * + * RETURN: Status + * + * DESCRIPTION: Allocate a table or method owner ID. The owner ID is used to + * track objects created by the table or method, to be deleted + * when the method exits or the table is unloaded. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAllocateOwnerId ( + ACPI_OWNER_ID *OwnerId) +{ + UINT32 i; + UINT32 j; + UINT32 k; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtAllocateOwnerId); + + + /* Guard against multiple allocations of ID to the same location */ + + if (*OwnerId) + { + ACPI_ERROR ((AE_INFO, "Owner ID [0x%2.2X] already exists", *OwnerId)); + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + /* Mutex for the global ID mask */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Find a free owner ID, cycle through all possible IDs on repeated + * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have + * to be scanned twice. + */ + for (i = 0, j = AcpiGbl_LastOwnerIdIndex; + i < (ACPI_NUM_OWNERID_MASKS + 1); + i++, j++) + { + if (j >= ACPI_NUM_OWNERID_MASKS) + { + j = 0; /* Wraparound to start of mask array */ + } + + for (k = AcpiGbl_NextOwnerIdOffset; k < 32; k++) + { + if (AcpiGbl_OwnerIdMask[j] == ACPI_UINT32_MAX) + { + /* There are no free IDs in this mask */ + + break; + } + + if (!(AcpiGbl_OwnerIdMask[j] & (1 << k))) + { + /* + * Found a free ID. The actual ID is the bit index plus one, + * making zero an invalid Owner ID. Save this as the last ID + * allocated and update the global ID mask. + */ + AcpiGbl_OwnerIdMask[j] |= (1 << k); + + AcpiGbl_LastOwnerIdIndex = (UINT8) j; + AcpiGbl_NextOwnerIdOffset = (UINT8) (k + 1); + + /* + * Construct encoded ID from the index and bit position + * + * Note: Last [j].k (bit 255) is never used and is marked + * permanently allocated (prevents +1 overflow) + */ + *OwnerId = (ACPI_OWNER_ID) ((k + 1) + ACPI_MUL_32 (j)); + + ACPI_DEBUG_PRINT ((ACPI_DB_VALUES, + "Allocated OwnerId: %2.2X\n", (unsigned int) *OwnerId)); + goto Exit; + } + } + + AcpiGbl_NextOwnerIdOffset = 0; + } + + /* + * All OwnerIds have been allocated. This typically should + * not happen since the IDs are reused after deallocation. The IDs are + * allocated upon table load (one per table) and method execution, and + * they are released when a table is unloaded or a method completes + * execution. + * + * If this error happens, there may be very deep nesting of invoked control + * methods, or there may be a bug where the IDs are not released. + */ + Status = AE_OWNER_ID_LIMIT; + ACPI_ERROR ((AE_INFO, + "Could not allocate new OwnerId (255 max), AE_OWNER_ID_LIMIT")); + +Exit: + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtReleaseOwnerId + * + * PARAMETERS: OwnerIdPtr - Pointer to a previously allocated OwnerID + * + * RETURN: None. No error is returned because we are either exiting a + * control method or unloading a table. Either way, we would + * ignore any error anyway. + * + * DESCRIPTION: Release a table or method owner ID. Valid IDs are 1 - 255 + * + ******************************************************************************/ + +void +AcpiUtReleaseOwnerId ( + ACPI_OWNER_ID *OwnerIdPtr) +{ + ACPI_OWNER_ID OwnerId = *OwnerIdPtr; + ACPI_STATUS Status; + UINT32 Index; + UINT32 Bit; + + + ACPI_FUNCTION_TRACE_U32 (UtReleaseOwnerId, OwnerId); + + + /* Always clear the input OwnerId (zero is an invalid ID) */ + + *OwnerIdPtr = 0; + + /* Zero is not a valid OwnerID */ + + if (OwnerId == 0) + { + ACPI_ERROR ((AE_INFO, "Invalid OwnerId: 0x%2.2X", OwnerId)); + return_VOID; + } + + /* Mutex for the global ID mask */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + /* Normalize the ID to zero */ + + OwnerId--; + + /* Decode ID to index/offset pair */ + + Index = ACPI_DIV_32 (OwnerId); + Bit = 1 << ACPI_MOD_32 (OwnerId); + + /* Free the owner ID only if it is valid */ + + if (AcpiGbl_OwnerIdMask[Index] & Bit) + { + AcpiGbl_OwnerIdMask[Index] ^= Bit; + } + else + { + ACPI_ERROR ((AE_INFO, + "Release of non-allocated OwnerId: 0x%2.2X", OwnerId + 1)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrupr (strupr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to uppercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void +AcpiUtStrupr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, uppercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) ACPI_TOUPPER (*String); + } + + return; +} + + +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlwr (strlwr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert string to lowercase + * + * NOTE: This is not a POSIX function, so it appears here, not in utclib.c + * + ******************************************************************************/ + +void +AcpiUtStrlwr ( + char *SrcString) +{ + char *String; + + + ACPI_FUNCTION_ENTRY (); + + + if (!SrcString) + { + return; + } + + /* Walk entire string, lowercasing the letters */ + + for (String = SrcString; *String; String++) + { + *String = (char) ACPI_TOLOWER (*String); + } + + return; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiUtStricmp + * + * PARAMETERS: String1 - first string to compare + * String2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Implementation of the non-ANSI stricmp function (compare + * strings with no case sensitivity) + * + ******************************************************************************/ + +int +AcpiUtStricmp ( + char *String1, + char *String2) +{ + int c1; + int c2; + + + do + { + c1 = tolower ((int) *String1); + c2 = tolower ((int) *String2); + + String1++; + String2++; + } + while ((c1 == c2) && (c1)); + + return (c1 - c2); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPrintString + * + * PARAMETERS: String - Null terminated ASCII string + * MaxLength - Maximum output length + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void +AcpiUtPrintString ( + char *String, + UINT8 MaxLength) +{ + UINT32 i; + + + if (!String) + { + AcpiOsPrintf ("<\"NULL STRING PTR\">"); + return; + } + + AcpiOsPrintf ("\""); + for (i = 0; String[i] && (i < MaxLength); i++) + { + /* Escape sequences */ + + switch (String[i]) + { + case 0x07: + AcpiOsPrintf ("\\a"); /* BELL */ + break; + + case 0x08: + AcpiOsPrintf ("\\b"); /* BACKSPACE */ + break; + + case 0x0C: + AcpiOsPrintf ("\\f"); /* FORMFEED */ + break; + + case 0x0A: + AcpiOsPrintf ("\\n"); /* LINEFEED */ + break; + + case 0x0D: + AcpiOsPrintf ("\\r"); /* CARRIAGE RETURN*/ + break; + + case 0x09: + AcpiOsPrintf ("\\t"); /* HORIZONTAL TAB */ + break; + + case 0x0B: + AcpiOsPrintf ("\\v"); /* VERTICAL TAB */ + break; + + case '\'': /* Single Quote */ + case '\"': /* Double Quote */ + case '\\': /* Backslash */ + AcpiOsPrintf ("\\%c", (int) String[i]); + break; + + default: + + /* Check for printable character or hex escape */ + + if (ACPI_IS_PRINT (String[i])) + { + /* This is a normal character */ + + AcpiOsPrintf ("%c", (int) String[i]); + } + else + { + /* All others will be Hex escapes */ + + AcpiOsPrintf ("\\x%2.2X", (INT32) String[i]); + } + break; + } + } + AcpiOsPrintf ("\""); + + if (i == MaxLength && String[i]) + { + AcpiOsPrintf ("..."); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDwordByteSwap + * + * PARAMETERS: Value - Value to be converted + * + * RETURN: UINT32 integer with bytes swapped + * + * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes) + * + ******************************************************************************/ + +UINT32 +AcpiUtDwordByteSwap ( + UINT32 Value) +{ + union + { + UINT32 Value; + UINT8 Bytes[4]; + } Out; + union + { + UINT32 Value; + UINT8 Bytes[4]; + } In; + + + ACPI_FUNCTION_ENTRY (); + + + In.Value = Value; + + Out.Bytes[0] = In.Bytes[3]; + Out.Bytes[1] = In.Bytes[2]; + Out.Bytes[2] = In.Bytes[1]; + Out.Bytes[3] = In.Bytes[0]; + + return (Out.Value); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtSetIntegerWidth + * + * PARAMETERS: Revision From DSDT header + * + * RETURN: None + * + * DESCRIPTION: Set the global integer bit width based upon the revision + * of the DSDT. For Revision 1 and 0, Integers are 32 bits. + * For Revision 2 and above, Integers are 64 bits. Yes, this + * makes a difference. + * + ******************************************************************************/ + +void +AcpiUtSetIntegerWidth ( + UINT8 Revision) +{ + + if (Revision < 2) + { + /* 32-bit case */ + + AcpiGbl_IntegerBitWidth = 32; + AcpiGbl_IntegerNybbleWidth = 8; + AcpiGbl_IntegerByteWidth = 4; + } + else + { + /* 64-bit case (ACPI 2.0+) */ + + AcpiGbl_IntegerBitWidth = 64; + AcpiGbl_IntegerNybbleWidth = 16; + AcpiGbl_IntegerByteWidth = 8; + } +} + + +#ifdef ACPI_DEBUG_OUTPUT +/******************************************************************************* + * + * FUNCTION: AcpiUtDisplayInitPathname + * + * PARAMETERS: Type - Object type of the node + * ObjHandle - Handle whose pathname will be displayed + * Path - Additional path string to be appended. + * (NULL if no extra path) + * + * RETURN: ACPI_STATUS + * + * DESCRIPTION: Display full pathname of an object, DEBUG ONLY + * + ******************************************************************************/ + +void +AcpiUtDisplayInitPathname ( + UINT8 Type, + ACPI_NAMESPACE_NODE *ObjHandle, + char *Path) +{ + ACPI_STATUS Status; + ACPI_BUFFER Buffer; + + + ACPI_FUNCTION_ENTRY (); + + + /* Only print the path if the appropriate debug level is enabled */ + + if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) + { + return; + } + + /* Get the full pathname to the node */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiNsHandleToPathname (ObjHandle, &Buffer); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* Print what we're doing */ + + switch (Type) + { + case ACPI_TYPE_METHOD: + AcpiOsPrintf ("Executing "); + break; + + default: + AcpiOsPrintf ("Initializing "); + break; + } + + /* Print the object type and pathname */ + + AcpiOsPrintf ("%-12s %s", + AcpiUtGetTypeName (Type), (char *) Buffer.Pointer); + + /* Extra path is used to append names like _STA, _INI, etc. */ + + if (Path) + { + AcpiOsPrintf (".%s", Path); + } + AcpiOsPrintf ("\n"); + + ACPI_FREE (Buffer.Pointer); +} +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidAcpiChar + * + * PARAMETERS: Char - The character to be examined + * Position - Byte position (0-3) + * + * RETURN: TRUE if the character is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI character. Must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + * We allow a '!' as the last character because of the ASF! table + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidAcpiChar ( + char Character, + UINT32 Position) +{ + + if (!((Character >= 'A' && Character <= 'Z') || + (Character >= '0' && Character <= '9') || + (Character == '_'))) + { + /* Allow a '!' in the last position */ + + if (Character == '!' && Position == 3) + { + return (TRUE); + } + + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidAcpiName + * + * PARAMETERS: Name - The name to be examined + * + * RETURN: TRUE if the name is valid, FALSE otherwise + * + * DESCRIPTION: Check for a valid ACPI name. Each character must be one of: + * 1) Upper case alpha + * 2) numeric + * 3) underscore + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidAcpiName ( + UINT32 Name) +{ + UINT32 i; + + + ACPI_FUNCTION_ENTRY (); + + + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (!AcpiUtValidAcpiChar ((ACPI_CAST_PTR (char, &Name))[i], i)) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRepairName + * + * PARAMETERS: Name - The ACPI name to be repaired + * + * RETURN: Repaired version of the name + * + * DESCRIPTION: Repair an ACPI name: Change invalid characters to '*' and + * return the new name. NOTE: the Name parameter must reside in + * read/write memory, cannot be a const. + * + * An ACPI Name must consist of valid ACPI characters. We will repair the name + * if necessary because we don't want to abort because of this, but we want + * all namespace names to be printable. A warning message is appropriate. + * + * This issue came up because there are in fact machines that exhibit + * this problem, and we want to be able to enable ACPI support for them, + * even though there are a few bad names. + * + ******************************************************************************/ + +void +AcpiUtRepairName ( + char *Name) +{ + UINT32 i; + BOOLEAN FoundBadChar = FALSE; + + + ACPI_FUNCTION_NAME (UtRepairName); + + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAME_SIZE; i++) + { + if (AcpiUtValidAcpiChar (Name[i], i)) + { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * still invalid. This prevents any collisions with existing "good" + * names in the namespace. + */ + Name[i] = '*'; + FoundBadChar = TRUE; + } + + if (FoundBadChar) + { + /* Report warning only if in strict mode or debug mode */ + + if (!AcpiGbl_EnableInterpreterSlack) + { + ACPI_WARNING ((AE_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", Name)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Found bad character(s) in name, repaired: [%4.4s]\n", Name)); + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul64 + * + * PARAMETERS: String - Null terminated string + * Base - Radix of the string: 16 or ACPI_ANY_BASE; + * ACPI_ANY_BASE means 'in behalf of ToInteger' + * RetInteger - Where the converted integer is returned + * + * RETURN: Status and Converted value + * + * DESCRIPTION: Convert a string into an unsigned value. Performs either a + * 32-bit or 64-bit conversion, depending on the current mode + * of the interpreter. + * NOTE: Does not support Octal strings, not needed. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT32 Base, + UINT64 *RetInteger) +{ + UINT32 ThisDigit = 0; + UINT64 ReturnValue = 0; + UINT64 Quotient; + UINT64 Dividend; + UINT32 ToIntegerOp = (Base == ACPI_ANY_BASE); + UINT32 Mode32 = (AcpiGbl_IntegerByteWidth == 4); + UINT8 ValidDigits = 0; + UINT8 SignOf0x = 0; + UINT8 Term = 0; + + + ACPI_FUNCTION_TRACE_STR (UtStroul64, String); + + + switch (Base) + { + case ACPI_ANY_BASE: + case 16: + break; + + default: + /* Invalid Base */ + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!String) + { + goto ErrorExit; + } + + /* Skip over any white space in the buffer */ + + while ((*String) && (ACPI_IS_SPACE (*String) || *String == '\t')) + { + String++; + } + + if (ToIntegerOp) + { + /* + * Base equal to ACPI_ANY_BASE means 'ToInteger operation case'. + * We need to determine if it is decimal or hexadecimal. + */ + if ((*String == '0') && (ACPI_TOLOWER (*(String + 1)) == 'x')) + { + SignOf0x = 1; + Base = 16; + + /* Skip over the leading '0x' */ + String += 2; + } + else + { + Base = 10; + } + } + + /* Any string left? Check that '0x' is not followed by white space. */ + + if (!(*String) || ACPI_IS_SPACE (*String) || *String == '\t') + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + goto AllDone; + } + } + + /* + * Perform a 32-bit or 64-bit conversion, depending upon the current + * execution mode of the interpreter + */ + Dividend = (Mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX; + + /* Main loop: convert the string to a 32- or 64-bit integer */ + + while (*String) + { + if (ACPI_IS_DIGIT (*String)) + { + /* Convert ASCII 0-9 to Decimal value */ + + ThisDigit = ((UINT8) *String) - '0'; + } + else if (Base == 10) + { + /* Digit is out of range; possible in ToInteger case only */ + + Term = 1; + } + else + { + ThisDigit = (UINT8) ACPI_TOUPPER (*String); + if (ACPI_IS_XDIGIT ((char) ThisDigit)) + { + /* Convert ASCII Hex char to value */ + + ThisDigit = ThisDigit - 'A' + 10; + } + else + { + Term = 1; + } + } + + if (Term) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + else if ((ValidDigits == 0) && (ThisDigit == 0) && !SignOf0x) + { + /* Skip zeros */ + String++; + continue; + } + + ValidDigits++; + + if (SignOf0x && ((ValidDigits > 16) || ((ValidDigits > 8) && Mode32))) + { + /* + * This is ToInteger operation case. + * No any restrictions for string-to-integer conversion, + * see ACPI spec. + */ + goto ErrorExit; + } + + /* Divide the digit into the correct position */ + + (void) AcpiUtShortDivide ((Dividend - (UINT64) ThisDigit), + Base, &Quotient, NULL); + + if (ReturnValue > Quotient) + { + if (ToIntegerOp) + { + goto ErrorExit; + } + else + { + break; + } + } + + ReturnValue *= Base; + ReturnValue += ThisDigit; + String++; + } + + /* All done, normal exit */ + +AllDone: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Converted value: %8.8X%8.8X\n", + ACPI_FORMAT_UINT64 (ReturnValue))); + + *RetInteger = ReturnValue; + return_ACPI_STATUS (AE_OK); + + +ErrorExit: + /* Base was set/validated above */ + + if (Base == 10) + { + return_ACPI_STATUS (AE_BAD_DECIMAL_CONSTANT); + } + else + { + return_ACPI_STATUS (AE_BAD_HEX_CONSTANT); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateUpdateStateAndPush + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * StateList - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateUpdateStateAndPush ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action, + ACPI_GENERIC_STATE **StateList) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + /* Ignore null objects; these are expected */ + + if (!Object) + { + return (AE_OK); + } + + State = AcpiUtCreateUpdateState (Object, Action); + if (!State) + { + return (AE_NO_MEMORY); + } + + AcpiUtPushGenericState (StateList, State); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtWalkPackageTree + * + * PARAMETERS: SourceObject - The package to walk + * TargetObject - Target object (if package is being copied) + * WalkCallback - Called once for each package element + * Context - Passed to the callback function + * + * RETURN: Status + * + * DESCRIPTION: Walk through a package + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtWalkPackageTree ( + ACPI_OPERAND_OBJECT *SourceObject, + void *TargetObject, + ACPI_PKG_CALLBACK WalkCallback, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_GENERIC_STATE *StateList = NULL; + ACPI_GENERIC_STATE *State; + UINT32 ThisIndex; + ACPI_OPERAND_OBJECT *ThisSourceObj; + + + ACPI_FUNCTION_TRACE (UtWalkPackageTree); + + + State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0); + if (!State) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + while (State) + { + /* Get one element of the package */ + + ThisIndex = State->Pkg.Index; + ThisSourceObj = (ACPI_OPERAND_OBJECT *) + State->Pkg.SourceObject->Package.Elements[ThisIndex]; + + /* + * Check for: + * 1) An uninitialized package element. It is completely + * legal to declare a package and leave it uninitialized + * 2) Not an internal object - can be a namespace node instead + * 3) Any type other than a package. Packages are handled in else + * case below. + */ + if ((!ThisSourceObj) || + (ACPI_GET_DESCRIPTOR_TYPE (ThisSourceObj) != ACPI_DESC_TYPE_OPERAND) || + (ThisSourceObj->Common.Type != ACPI_TYPE_PACKAGE)) + { + Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj, + State, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + State->Pkg.Index++; + while (State->Pkg.Index >= State->Pkg.SourceObject->Package.Count) + { + /* + * We've handled all of the objects at this level, This means + * that we have just completed a package. That package may + * have contained one or more packages itself. + * + * Delete this state and pop the previous state (package). + */ + AcpiUtDeleteGenericState (State); + State = AcpiUtPopGenericState (&StateList); + + /* Finished when there are no more states */ + + if (!State) + { + /* + * We have handled all of the objects in the top level + * package just add the length of the package objects + * and exit + */ + return_ACPI_STATUS (AE_OK); + } + + /* + * Go back up a level and move the index past the just + * completed package object. + */ + State->Pkg.Index++; + } + } + else + { + /* This is a subobject of type package */ + + Status = WalkCallback (ACPI_COPY_TYPE_PACKAGE, ThisSourceObj, + State, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Push the current state and create a new one + * The callback above returned a new target package object. + */ + AcpiUtPushGenericState (&StateList, State); + State = AcpiUtCreatePkgState (ThisSourceObj, + State->Pkg.ThisTargetObj, 0); + if (!State) + { + /* Free any stacked Update State objects */ + + while (StateList) + { + State = AcpiUtPopGenericState (&StateList); + AcpiUtDeleteGenericState (State); + } + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + } + + /* We should never get here */ + + return_ACPI_STATUS (AE_AML_INTERNAL); +} + + diff --git a/source/components/utilities/utmutex.c b/source/components/utilities/utmutex.c new file mode 100644 index 0000000..f1cdb018 --- /dev/null +++ b/source/components/utilities/utmutex.c @@ -0,0 +1,397 @@ +/******************************************************************************* + * + * Module Name: utmutex - local mutex support + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTMUTEX_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmutex") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtCreateMutex ( + ACPI_MUTEX_HANDLE MutexId); + +static void +AcpiUtDeleteMutex ( + ACPI_MUTEX_HANDLE MutexId); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMutexInitialize + * + * PARAMETERS: None. + * + * RETURN: Status + * + * DESCRIPTION: Create the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtMutexInitialize ( + void) +{ + UINT32 i; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtMutexInitialize); + + + /* Create each of the predefined mutex objects */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + Status = AcpiUtCreateMutex (i); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Create the spinlocks for use at interrupt level */ + + Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Mutex for _OSI support */ + Status = AcpiOsCreateMutex (&AcpiGbl_OsiMutex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create the reader/writer lock for namespace access */ + + Status = AcpiUtCreateRwLock (&AcpiGbl_NamespaceRwLock); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMutexTerminate + * + * PARAMETERS: None. + * + * RETURN: None. + * + * DESCRIPTION: Delete all of the system mutex objects. This includes mutexes, + * spin locks, and reader/writer locks. + * + ******************************************************************************/ + +void +AcpiUtMutexTerminate ( + void) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE (UtMutexTerminate); + + + /* Delete each predefined mutex object */ + + for (i = 0; i < ACPI_NUM_MUTEX; i++) + { + AcpiUtDeleteMutex (i); + } + + AcpiOsDeleteMutex (AcpiGbl_OsiMutex); + + /* Delete the spinlocks */ + + AcpiOsDeleteLock (AcpiGbl_GpeLock); + AcpiOsDeleteLock (AcpiGbl_HardwareLock); + + /* Delete the reader/writer lock */ + + AcpiUtDeleteRwLock (&AcpiGbl_NamespaceRwLock); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateMutex + * + * PARAMETERS: MutexID - ID of the mutex to be created + * + * RETURN: Status + * + * DESCRIPTION: Create a mutex object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtCreateMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateMutex, MutexId); + + + if (!AcpiGbl_MutexInfo[MutexId].Mutex) + { + Status = AcpiOsCreateMutex (&AcpiGbl_MutexInfo[MutexId].Mutex); + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + AcpiGbl_MutexInfo[MutexId].UseCount = 0; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteMutex + * + * PARAMETERS: MutexID - ID of the mutex to be deleted + * + * RETURN: Status + * + * DESCRIPTION: Delete a mutex object. + * + ******************************************************************************/ + +static void +AcpiUtDeleteMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + + ACPI_FUNCTION_TRACE_U32 (UtDeleteMutex, MutexId); + + + AcpiOsDeleteMutex (AcpiGbl_MutexInfo[MutexId].Mutex); + + AcpiGbl_MutexInfo[MutexId].Mutex = NULL; + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAcquireMutex + * + * PARAMETERS: MutexID - ID of the mutex to be acquired + * + * RETURN: Status + * + * DESCRIPTION: Acquire a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAcquireMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_STATUS Status; + ACPI_THREAD_ID ThisThreadId; + + + ACPI_FUNCTION_NAME (UtAcquireMutex); + + + if (MutexId > ACPI_MAX_MUTEX) + { + return (AE_BAD_PARAMETER); + } + + ThisThreadId = AcpiOsGetThreadId (); + +#ifdef ACPI_MUTEX_DEBUG + { + UINT32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than or equal to this one. If so, the thread has violated + * the mutex ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = MutexId; i < ACPI_NUM_MUTEX; i++) + { + if (AcpiGbl_MutexInfo[i].ThreadId == ThisThreadId) + { + if (i == MutexId) + { + ACPI_ERROR ((AE_INFO, + "Mutex [%s] already acquired by this thread [%u]", + AcpiUtGetMutexName (MutexId), + (UINT32) ThisThreadId)); + + return (AE_ALREADY_ACQUIRED); + } + + ACPI_ERROR ((AE_INFO, + "Invalid acquire order: Thread %u owns [%s], wants [%s]", + (UINT32) ThisThreadId, AcpiUtGetMutexName (i), + AcpiUtGetMutexName (MutexId))); + + return (AE_ACQUIRE_DEADLOCK); + } + } + } +#endif + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, + "Thread %u attempting to acquire Mutex [%s]\n", + (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); + + Status = AcpiOsAcquireMutex (AcpiGbl_MutexInfo[MutexId].Mutex, + ACPI_WAIT_FOREVER); + if (ACPI_SUCCESS (Status)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u acquired Mutex [%s]\n", + (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId))); + + AcpiGbl_MutexInfo[MutexId].UseCount++; + AcpiGbl_MutexInfo[MutexId].ThreadId = ThisThreadId; + } + else + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Thread %u could not acquire Mutex [0x%X]", + (UINT32) ThisThreadId, MutexId)); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtReleaseMutex + * + * PARAMETERS: MutexID - ID of the mutex to be released + * + * RETURN: Status + * + * DESCRIPTION: Release a mutex object. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtReleaseMutex ( + ACPI_MUTEX_HANDLE MutexId) +{ + ACPI_FUNCTION_NAME (UtReleaseMutex); + + ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n", + (UINT32) AcpiOsGetThreadId (), AcpiUtGetMutexName (MutexId))); + + if (MutexId > ACPI_MAX_MUTEX) + { + return (AE_BAD_PARAMETER); + } + + /* + * Mutex must be acquired in order to release it! + */ + if (AcpiGbl_MutexInfo[MutexId].ThreadId == ACPI_MUTEX_NOT_ACQUIRED) + { + ACPI_ERROR ((AE_INFO, + "Mutex [0x%X] is not acquired, cannot release", MutexId)); + + return (AE_NOT_ACQUIRED); + } + +#ifdef ACPI_MUTEX_DEBUG + { + UINT32 i; + /* + * Mutex debug code, for internal debugging only. + * + * Deadlock prevention. Check if this thread owns any mutexes of value + * greater than this one. If so, the thread has violated the mutex + * ordering rule. This indicates a coding error somewhere in + * the ACPI subsystem code. + */ + for (i = MutexId; i < ACPI_NUM_MUTEX; i++) + { + if (AcpiGbl_MutexInfo[i].ThreadId == AcpiOsGetThreadId ()) + { + if (i == MutexId) + { + continue; + } + + ACPI_ERROR ((AE_INFO, + "Invalid release order: owns [%s], releasing [%s]", + AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); + + return (AE_RELEASE_DEADLOCK); + } + } + } +#endif + + /* Mark unlocked FIRST */ + + AcpiGbl_MutexInfo[MutexId].ThreadId = ACPI_MUTEX_NOT_ACQUIRED; + + AcpiOsReleaseMutex (AcpiGbl_MutexInfo[MutexId].Mutex); + return (AE_OK); +} + + diff --git a/source/components/utilities/utobject.c b/source/components/utilities/utobject.c new file mode 100644 index 0000000..fea1409 --- /dev/null +++ b/source/components/utilities/utobject.c @@ -0,0 +1,787 @@ +/****************************************************************************** + * + * Module Name: utobject - ACPI object create/delete/size/cache routines + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTOBJECT_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utobject") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtGetSimpleObjectSize ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_SIZE *ObjLength); + +static ACPI_STATUS +AcpiUtGetPackageObjectSize ( + ACPI_OPERAND_OBJECT *Obj, + ACPI_SIZE *ObjLength); + +static ACPI_STATUS +AcpiUtGetElementLength ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateInternalObjectDbg + * + * PARAMETERS: ModuleName - Source file name of caller + * LineNumber - Line number of caller + * ComponentId - Component type of caller + * Type - ACPI Type of the new object + * + * RETURN: A new internal object, null on failure + * + * DESCRIPTION: Create and initialize a new internal object. + * + * NOTE: We always allocate the worst-case object descriptor because + * these objects are cached, and we want them to be + * one-size-satisifies-any-request. This in itself may not be + * the most memory efficient, but the efficiency of the object + * cache should more than make up for this! + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateInternalObjectDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId, + ACPI_OBJECT_TYPE Type) +{ + ACPI_OPERAND_OBJECT *Object; + ACPI_OPERAND_OBJECT *SecondObject; + + + ACPI_FUNCTION_TRACE_STR (UtCreateInternalObjectDbg, + AcpiUtGetTypeName (Type)); + + + /* Allocate the raw object descriptor */ + + Object = AcpiUtAllocateObjectDescDbg (ModuleName, LineNumber, ComponentId); + if (!Object) + { + return_PTR (NULL); + } + + switch (Type) + { + case ACPI_TYPE_REGION: + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* These types require a secondary object */ + + SecondObject = AcpiUtAllocateObjectDescDbg (ModuleName, + LineNumber, ComponentId); + if (!SecondObject) + { + AcpiUtDeleteObjectDesc (Object); + return_PTR (NULL); + } + + SecondObject->Common.Type = ACPI_TYPE_LOCAL_EXTRA; + SecondObject->Common.ReferenceCount = 1; + + /* Link the second object to the first */ + + Object->Common.NextObject = SecondObject; + break; + + default: + /* All others have no secondary object */ + break; + } + + /* Save the object type in the object descriptor */ + + Object->Common.Type = (UINT8) Type; + + /* Init the reference count */ + + Object->Common.ReferenceCount = 1; + + /* Any per-type initialization should go here */ + + return_PTR (Object); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePackageObject + * + * PARAMETERS: Count - Number of package elements + * + * RETURN: Pointer to a new Package object, null on failure + * + * DESCRIPTION: Create a fully initialized package object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreatePackageObject ( + UINT32 Count) +{ + ACPI_OPERAND_OBJECT *PackageDesc; + ACPI_OPERAND_OBJECT **PackageElements; + + + ACPI_FUNCTION_TRACE_U32 (UtCreatePackageObject, Count); + + + /* Create a new Package object */ + + PackageDesc = AcpiUtCreateInternalObject (ACPI_TYPE_PACKAGE); + if (!PackageDesc) + { + return_PTR (NULL); + } + + /* + * Create the element array. Count+1 allows the array to be null + * terminated. + */ + PackageElements = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) Count + 1) * sizeof (void *)); + if (!PackageElements) + { + ACPI_FREE (PackageDesc); + return_PTR (NULL); + } + + PackageDesc->Package.Count = Count; + PackageDesc->Package.Elements = PackageElements; + return_PTR (PackageDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateIntegerObject + * + * PARAMETERS: InitialValue - Initial value for the integer + * + * RETURN: Pointer to a new Integer object, null on failure + * + * DESCRIPTION: Create an initialized integer object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateIntegerObject ( + UINT64 InitialValue) +{ + ACPI_OPERAND_OBJECT *IntegerDesc; + + + ACPI_FUNCTION_TRACE (UtCreateIntegerObject); + + + /* Create and initialize a new integer object */ + + IntegerDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!IntegerDesc) + { + return_PTR (NULL); + } + + IntegerDesc->Integer.Value = InitialValue; + return_PTR (IntegerDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateBufferObject + * + * PARAMETERS: BufferSize - Size of buffer to be created + * + * RETURN: Pointer to a new Buffer object, null on failure + * + * DESCRIPTION: Create a fully initialized buffer object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateBufferObject ( + ACPI_SIZE BufferSize) +{ + ACPI_OPERAND_OBJECT *BufferDesc; + UINT8 *Buffer = NULL; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateBufferObject, BufferSize); + + + /* Create a new Buffer object */ + + BufferDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER); + if (!BufferDesc) + { + return_PTR (NULL); + } + + /* Create an actual buffer only if size > 0 */ + + if (BufferSize > 0) + { + /* Allocate the actual buffer */ + + Buffer = ACPI_ALLOCATE_ZEROED (BufferSize); + if (!Buffer) + { + ACPI_ERROR ((AE_INFO, "Could not allocate size %u", + (UINT32) BufferSize)); + AcpiUtRemoveReference (BufferDesc); + return_PTR (NULL); + } + } + + /* Complete buffer object initialization */ + + BufferDesc->Buffer.Flags |= AOPOBJ_DATA_VALID; + BufferDesc->Buffer.Pointer = Buffer; + BufferDesc->Buffer.Length = (UINT32) BufferSize; + + /* Return the new buffer descriptor */ + + return_PTR (BufferDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateStringObject + * + * PARAMETERS: StringSize - Size of string to be created. Does not + * include NULL terminator, this is added + * automatically. + * + * RETURN: Pointer to a new String object + * + * DESCRIPTION: Create a fully initialized string object + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiUtCreateStringObject ( + ACPI_SIZE StringSize) +{ + ACPI_OPERAND_OBJECT *StringDesc; + char *String; + + + ACPI_FUNCTION_TRACE_U32 (UtCreateStringObject, StringSize); + + + /* Create a new String object */ + + StringDesc = AcpiUtCreateInternalObject (ACPI_TYPE_STRING); + if (!StringDesc) + { + return_PTR (NULL); + } + + /* + * Allocate the actual string buffer -- (Size + 1) for NULL terminator. + * NOTE: Zero-length strings are NULL terminated + */ + String = ACPI_ALLOCATE_ZEROED (StringSize + 1); + if (!String) + { + ACPI_ERROR ((AE_INFO, "Could not allocate size %u", + (UINT32) StringSize)); + AcpiUtRemoveReference (StringDesc); + return_PTR (NULL); + } + + /* Complete string object initialization */ + + StringDesc->String.Pointer = String; + StringDesc->String.Length = (UINT32) StringSize; + + /* Return the new string descriptor */ + + return_PTR (StringDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidInternalObject + * + * PARAMETERS: Object - Object to be validated + * + * RETURN: TRUE if object is valid, FALSE otherwise + * + * DESCRIPTION: Validate a pointer to be an ACPI_OPERAND_OBJECT + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidInternalObject ( + void *Object) +{ + + ACPI_FUNCTION_NAME (UtValidInternalObject); + + + /* Check for a null pointer */ + + if (!Object) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "**** Null Object Ptr\n")); + return (FALSE); + } + + /* Check the descriptor type field */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (Object)) + { + case ACPI_DESC_TYPE_OPERAND: + + /* The object appears to be a valid ACPI_OPERAND_OBJECT */ + + return (TRUE); + + default: + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%p is not not an ACPI operand obj [%s]\n", + Object, AcpiUtGetDescriptorName (Object))); + break; + } + + return (FALSE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateObjectDescDbg + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * ComponentId - Caller's component ID (for error output) + * + * RETURN: Pointer to newly allocated object descriptor. Null on error + * + * DESCRIPTION: Allocate a new object descriptor. Gracefully handle + * error conditions. + * + ******************************************************************************/ + +void * +AcpiUtAllocateObjectDescDbg ( + const char *ModuleName, + UINT32 LineNumber, + UINT32 ComponentId) +{ + ACPI_OPERAND_OBJECT *Object; + + + ACPI_FUNCTION_TRACE (UtAllocateObjectDescDbg); + + + Object = AcpiOsAcquireObject (AcpiGbl_OperandCache); + if (!Object) + { + ACPI_ERROR ((ModuleName, LineNumber, + "Could not allocate an object descriptor")); + + return_PTR (NULL); + } + + /* Mark the descriptor type */ + + ACPI_SET_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_OPERAND); + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p Size %X\n", + Object, (UINT32) sizeof (ACPI_OPERAND_OBJECT))); + + return_PTR (Object); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteObjectDesc + * + * PARAMETERS: Object - An Acpi internal object to be deleted + * + * RETURN: None. + * + * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache + * + ******************************************************************************/ + +void +AcpiUtDeleteObjectDesc ( + ACPI_OPERAND_OBJECT *Object) +{ + ACPI_FUNCTION_TRACE_PTR (UtDeleteObjectDesc, Object); + + + /* Object must be an ACPI_OPERAND_OBJECT */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) != ACPI_DESC_TYPE_OPERAND) + { + ACPI_ERROR ((AE_INFO, + "%p is not an ACPI Operand object [%s]", Object, + AcpiUtGetDescriptorName (Object))); + return_VOID; + } + + (void) AcpiOsReleaseObject (AcpiGbl_OperandCache, Object); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetSimpleObjectSize + * + * PARAMETERS: InternalObject - An ACPI operand object + * ObjLength - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a simple object for return to an external user. + * + * The length includes the object structure plus any additional + * needed space. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetSimpleObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_SIZE Length; + ACPI_SIZE Size; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (UtGetSimpleObjectSize, InternalObject); + + + /* Start with the length of the (external) Acpi object */ + + Length = sizeof (ACPI_OBJECT); + + /* A NULL object is allowed, can be a legal uninitialized package element */ + + if (!InternalObject) + { + /* + * Object is NULL, just return the length of ACPI_OBJECT + * (A NULL ACPI_OBJECT is an object of all zeroes.) + */ + *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); + return_ACPI_STATUS (AE_OK); + } + + /* A Namespace Node should never appear here */ + + if (ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_NAMED) + { + /* A namespace node should never get here */ + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + /* + * The final length depends on the object type + * Strings and Buffers are packed right up against the parent object and + * must be accessed bytewise or there may be alignment problems on + * certain processors + */ + switch (InternalObject->Common.Type) + { + case ACPI_TYPE_STRING: + + Length += (ACPI_SIZE) InternalObject->String.Length + 1; + break; + + + case ACPI_TYPE_BUFFER: + + Length += (ACPI_SIZE) InternalObject->Buffer.Length; + break; + + + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_POWER: + + /* No extra data for these types */ + + break; + + + case ACPI_TYPE_LOCAL_REFERENCE: + + switch (InternalObject->Reference.Class) + { + case ACPI_REFCLASS_NAME: + + /* + * Get the actual length of the full pathname to this object. + * The reference will be converted to the pathname to the object + */ + Size = AcpiNsGetPathnameLength (InternalObject->Reference.Node); + if (!Size) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Length += ACPI_ROUND_UP_TO_NATIVE_WORD (Size); + break; + + default: + + /* + * No other reference opcodes are supported. + * Notably, Locals and Args are not supported, but this may be + * required eventually. + */ + ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " + "unsupported Reference Class [%s] 0x%X in object %p", + AcpiUtGetReferenceName (InternalObject), + InternalObject->Reference.Class, InternalObject)); + Status = AE_TYPE; + break; + } + break; + + + default: + + ACPI_ERROR ((AE_INFO, "Cannot convert to external object - " + "unsupported type [%s] 0x%X in object %p", + AcpiUtGetObjectTypeName (InternalObject), + InternalObject->Common.Type, InternalObject)); + Status = AE_TYPE; + break; + } + + /* + * Account for the space required by the object rounded up to the next + * multiple of the machine word size. This keeps each object aligned + * on a machine word boundary. (preventing alignment faults on some + * machines.) + */ + *ObjLength = ACPI_ROUND_UP_TO_NATIVE_WORD (Length); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetElementLength + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Get the length of one package element. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetElementLength ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_PKG_INFO *Info = (ACPI_PKG_INFO *) Context; + ACPI_SIZE ObjectSpace; + + + switch (ObjectType) + { + case ACPI_COPY_TYPE_SIMPLE: + + /* + * Simple object - just get the size (Null object/entry is handled + * here also) and sum it into the running package length + */ + Status = AcpiUtGetSimpleObjectSize (SourceObject, &ObjectSpace); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Info->Length += ObjectSpace; + break; + + + case ACPI_COPY_TYPE_PACKAGE: + + /* Package object - nothing much to do here, let the walk handle it */ + + Info->NumPackages++; + State->Pkg.ThisTargetObj = NULL; + break; + + + default: + + /* No other types allowed */ + + return (AE_BAD_PARAMETER); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetPackageObjectSize + * + * PARAMETERS: InternalObject - An ACPI internal object + * ObjLength - Where the length is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain a package object for return to an external user. + * + * This is moderately complex since a package contains other + * objects including packages. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetPackageObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_STATUS Status; + ACPI_PKG_INFO Info; + + + ACPI_FUNCTION_TRACE_PTR (UtGetPackageObjectSize, InternalObject); + + + Info.Length = 0; + Info.ObjectSpace = 0; + Info.NumPackages = 1; + + Status = AcpiUtWalkPackageTree (InternalObject, NULL, + AcpiUtGetElementLength, &Info); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * We have handled all of the objects in all levels of the package. + * just add the length of the package objects themselves. + * Round up to the next machine word. + */ + Info.Length += ACPI_ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) * + (ACPI_SIZE) Info.NumPackages; + + /* Return the total package length */ + + *ObjLength = Info.Length; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetObjectSize + * + * PARAMETERS: InternalObject - An ACPI internal object + * ObjLength - Where the length will be returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to determine the space required to + * contain an object for return to an API user. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtGetObjectSize ( + ACPI_OPERAND_OBJECT *InternalObject, + ACPI_SIZE *ObjLength) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_ENTRY (); + + + if ((ACPI_GET_DESCRIPTOR_TYPE (InternalObject) == ACPI_DESC_TYPE_OPERAND) && + (InternalObject->Common.Type == ACPI_TYPE_PACKAGE)) + { + Status = AcpiUtGetPackageObjectSize (InternalObject, ObjLength); + } + else + { + Status = AcpiUtGetSimpleObjectSize (InternalObject, ObjLength); + } + + return (Status); +} + + diff --git a/source/components/utilities/utosi.c b/source/components/utilities/utosi.c new file mode 100644 index 0000000..dcce8a9 --- /dev/null +++ b/source/components/utilities/utosi.c @@ -0,0 +1,422 @@ +/****************************************************************************** + * + * Module Name: utosi - Support for the _OSI predefined control method + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTOSI_C__ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utosi") + +/* + * Strings supported by the _OSI predefined control method (which is + * implemented internally within this module.) + * + * March 2009: Removed "Linux" as this host no longer wants to respond true + * for this string. Basically, the only safe OS strings are windows-related + * and in many or most cases represent the only test path within the + * BIOS-provided ASL code. + * + * The last element of each entry is used to track the newest version of + * Windows that the BIOS has requested. + */ +static ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] = +{ + /* Operating System Vendor Strings */ + + {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ + {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ + {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ + {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ + {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ + {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ + {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ + {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ + {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ + {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ + {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ + + /* Feature Group Strings */ + + {"Extended Address Space Descriptor", NULL, 0, 0} + + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be dynamically added by the host via + * AcpiInstallInterface and should not be manually added here. + * + * Examples of optional feature group strings: + * + * "Module Device" + * "Processor Device" + * "3.0 Thermal Model" + * "3.0 _SCP Extensions" + * "Processor Aggregator Device" + */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitializeInterfaces + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the global _OSI supported interfaces list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitializeInterfaces ( + void) +{ + UINT32 i; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces; + + /* Link the static list of supported interfaces */ + + for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++) + { + AcpiDefaultSupportedInterfaces[i].Next = + &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1]; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInterfaceTerminate + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Delete all interfaces in the global list. Sets + * AcpiGbl_SupportedInterfaces to NULL. + * + ******************************************************************************/ + +void +AcpiUtInterfaceTerminate ( + void) +{ + ACPI_INTERFACE_INFO *NextInterface; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + NextInterface = AcpiGbl_SupportedInterfaces; + + while (NextInterface) + { + AcpiGbl_SupportedInterfaces = NextInterface->Next; + + /* Only interfaces added at runtime can be freed */ + + if (NextInterface->Flags & ACPI_OSI_DYNAMIC) + { + ACPI_FREE (NextInterface->Name); + ACPI_FREE (NextInterface); + } + + NextInterface = AcpiGbl_SupportedInterfaces; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInstallInterface + * + * PARAMETERS: InterfaceName - The interface to install + * + * RETURN: Status + * + * DESCRIPTION: Install the interface into the global interface list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInstallInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *InterfaceInfo; + + + /* Allocate info block and space for the name string */ + + InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO)); + if (!InterfaceInfo) + { + return (AE_NO_MEMORY); + } + + InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1); + if (!InterfaceInfo->Name) + { + ACPI_FREE (InterfaceInfo); + return (AE_NO_MEMORY); + } + + /* Initialize new info and insert at the head of the global list */ + + ACPI_STRCPY (InterfaceInfo->Name, InterfaceName); + InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; + InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; + + AcpiGbl_SupportedInterfaces = InterfaceInfo; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveInterface + * + * PARAMETERS: InterfaceName - The interface to remove + * + * RETURN: Status + * + * DESCRIPTION: Remove the interface from the global interface list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtRemoveInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *PreviousInterface; + ACPI_INTERFACE_INFO *NextInterface; + + + PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + { + /* Found: name is in either the static list or was added at runtime */ + + if (NextInterface->Flags & ACPI_OSI_DYNAMIC) + { + /* Interface was added dynamically, remove and free it */ + + if (PreviousInterface == NextInterface) + { + AcpiGbl_SupportedInterfaces = NextInterface->Next; + } + else + { + PreviousInterface->Next = NextInterface->Next; + } + + ACPI_FREE (NextInterface->Name); + ACPI_FREE (NextInterface); + } + else + { + /* + * Interface is in static list. If marked invalid, then it + * does not actually exist. Else, mark it invalid. + */ + if (NextInterface->Flags & ACPI_OSI_INVALID) + { + return (AE_NOT_EXIST); + } + + NextInterface->Flags |= ACPI_OSI_INVALID; + } + + return (AE_OK); + } + + PreviousInterface = NextInterface; + NextInterface = NextInterface->Next; + } + + /* Interface was not found */ + + return (AE_NOT_EXIST); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetInterface + * + * PARAMETERS: InterfaceName - The interface to find + * + * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found. + * + * DESCRIPTION: Search for the specified interface name in the global list. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_INTERFACE_INFO * +AcpiUtGetInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_INTERFACE_INFO *NextInterface; + + + NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) + { + return (NextInterface); + } + + NextInterface = NextInterface->Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtOsiImplementation + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: Implementation of the _OSI predefined control method. When + * an invocation of _OSI is encountered in the system AML, + * control is transferred to this function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtOsiImplementation ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *StringDesc; + ACPI_OPERAND_OBJECT *ReturnDesc; + ACPI_INTERFACE_INFO *InterfaceInfo; + ACPI_INTERFACE_HANDLER InterfaceHandler; + UINT32 ReturnValue; + + + ACPI_FUNCTION_TRACE (UtOsiImplementation); + + + /* Validate the string input argument (from the AML caller) */ + + StringDesc = WalkState->Arguments[0].Object; + if (!StringDesc || + (StringDesc->Common.Type != ACPI_TYPE_STRING)) + { + return_ACPI_STATUS (AE_TYPE); + } + + /* Create a return object */ + + ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); + if (!ReturnDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Default return value is 0, NOT SUPPORTED */ + + ReturnValue = 0; + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + /* Lookup the interface in the global _OSI list */ + + InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer); + if (InterfaceInfo && + !(InterfaceInfo->Flags & ACPI_OSI_INVALID)) + { + /* + * The interface is supported. + * Update the OsiData if necessary. We keep track of the latest + * version of Windows that has been requested by the BIOS. + */ + if (InterfaceInfo->Value > AcpiGbl_OsiData) + { + AcpiGbl_OsiData = InterfaceInfo->Value; + } + + ReturnValue = ACPI_UINT32_MAX; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + + /* + * Invoke an optional _OSI interface handler. The host OS may wish + * to do some interface-specific handling. For example, warn about + * certain interfaces or override the true/false support value. + */ + InterfaceHandler = AcpiGbl_InterfaceHandler; + if (InterfaceHandler) + { + ReturnValue = InterfaceHandler ( + StringDesc->String.Pointer, ReturnValue); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", + StringDesc->String.Pointer, ReturnValue == 0 ? "not " : "")); + + /* Complete the return object */ + + ReturnDesc->Integer.Value = ReturnValue; + WalkState->ReturnDesc = ReturnDesc; + return_ACPI_STATUS (AE_OK); +} diff --git a/source/components/utilities/utresrc.c b/source/components/utilities/utresrc.c new file mode 100644 index 0000000..c2c135b --- /dev/null +++ b/source/components/utilities/utresrc.c @@ -0,0 +1,923 @@ +/******************************************************************************* + * + * Module Name: utresrc - Resource managment utilities + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTRESRC_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utresrc") + + +#if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) + +/* + * Strings used to decode resource descriptors. + * Used by both the disasssembler and the debugger resource dump routines + */ +const char *AcpiGbl_BmDecode[] = +{ + "NotBusMaster", + "BusMaster" +}; + +const char *AcpiGbl_ConfigDecode[] = +{ + "0 - Good Configuration", + "1 - Acceptable Configuration", + "2 - Suboptimal Configuration", + "3 - ***Invalid Configuration***", +}; + +const char *AcpiGbl_ConsumeDecode[] = +{ + "ResourceProducer", + "ResourceConsumer" +}; + +const char *AcpiGbl_DecDecode[] = +{ + "PosDecode", + "SubDecode" +}; + +const char *AcpiGbl_HeDecode[] = +{ + "Level", + "Edge" +}; + +const char *AcpiGbl_IoDecode[] = +{ + "Decode10", + "Decode16" +}; + +const char *AcpiGbl_LlDecode[] = +{ + "ActiveHigh", + "ActiveLow" +}; + +const char *AcpiGbl_MaxDecode[] = +{ + "MaxNotFixed", + "MaxFixed" +}; + +const char *AcpiGbl_MemDecode[] = +{ + "NonCacheable", + "Cacheable", + "WriteCombining", + "Prefetchable" +}; + +const char *AcpiGbl_MinDecode[] = +{ + "MinNotFixed", + "MinFixed" +}; + +const char *AcpiGbl_MtpDecode[] = +{ + "AddressRangeMemory", + "AddressRangeReserved", + "AddressRangeACPI", + "AddressRangeNVS" +}; + +const char *AcpiGbl_RngDecode[] = +{ + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" +}; + +const char *AcpiGbl_RwDecode[] = +{ + "ReadOnly", + "ReadWrite" +}; + +const char *AcpiGbl_ShrDecode[] = +{ + "Exclusive", + "Shared" +}; + +const char *AcpiGbl_SizDecode[] = +{ + "Transfer8", + "Transfer8_16", + "Transfer16", + "InvalidSize" +}; + +const char *AcpiGbl_TrsDecode[] = +{ + "DenseTranslation", + "SparseTranslation" +}; + +const char *AcpiGbl_TtpDecode[] = +{ + "TypeStatic", + "TypeTranslation" +}; + +const char *AcpiGbl_TypDecode[] = +{ + "Compatibility", + "TypeA", + "TypeB", + "TypeF" +}; + +const char *AcpiGbl_PpcDecode[] = +{ + "PullDefault", + "PullUp", + "PullDown", + "PullNone" +}; + +const char *AcpiGbl_IorDecode[] = +{ + "IoRestrictionNone", + "IoRestrictionInputOnly", + "IoRestrictionOutputOnly", + "IoRestrictionNoneAndPreserve" +}; + +const char *AcpiGbl_DtsDecode[] = +{ + "Width8bit", + "Width16bit", + "Width32bit", + "Width64bit", + "Width128bit", + "Width256bit", +}; + +/* GPIO connection type */ + +const char *AcpiGbl_CtDecode[] = +{ + "Interrupt", + "I/O" +}; + +/* Serial bus type */ + +const char *AcpiGbl_SbtDecode[] = +{ + "/* UNKNOWN serial bus type */", + "I2C", + "SPI", + "UART" +}; + +/* I2C serial bus access mode */ + +const char *AcpiGbl_AmDecode[] = +{ + "AddressingMode7Bit", + "AddressingMode10Bit" +}; + +/* I2C serial bus slave mode */ + +const char *AcpiGbl_SmDecode[] = +{ + "ControllerInitiated", + "DeviceInitiated" +}; + +/* SPI serial bus wire mode */ + +const char *AcpiGbl_WmDecode[] = +{ + "FourWireMode", + "ThreeWireMode" +}; + +/* SPI serial clock phase */ + +const char *AcpiGbl_CphDecode[] = +{ + "ClockPhaseFirst", + "ClockPhaseSecond" +}; + +/* SPI serial bus clock polarity */ + +const char *AcpiGbl_CpoDecode[] = +{ + "ClockPolarityLow", + "ClockPolarityHigh" +}; + +/* SPI serial bus device polarity */ + +const char *AcpiGbl_DpDecode[] = +{ + "PolarityLow", + "PolarityHigh" +}; + +/* UART serial bus endian */ + +const char *AcpiGbl_EdDecode[] = +{ + "LittleEndian", + "BigEndian" +}; + +/* UART serial bus bits per byte */ + +const char *AcpiGbl_BpbDecode[] = +{ + "DataBitsFive", + "DataBitsSix", + "DataBitsSeven", + "DataBitsEight", + "DataBitsNine", + "/* UNKNOWN Bits per byte */", + "/* UNKNOWN Bits per byte */", + "/* UNKNOWN Bits per byte */" +}; + +/* UART serial bus stop bits */ + +const char *AcpiGbl_SbDecode[] = +{ + "StopBitsNone", + "StopBitsOne", + "StopBitsOnePlusHalf", + "StopBitsTwo" +}; + +/* UART serial bus flow control */ + +const char *AcpiGbl_FcDecode[] = +{ + "FlowControlNone", + "FlowControlHardware", + "FlowControlXON", + "/* UNKNOWN flow control keyword */" +}; + +/* UART serial bus parity type */ + +const char *AcpiGbl_PtDecode[] = +{ + "ParityTypeNone", + "ParityTypeEven", + "ParityTypeOdd", + "ParityTypeMark", + "ParityTypeSpace", + "/* UNKNOWN parity keyword */", + "/* UNKNOWN parity keyword */", + "/* UNKNOWN parity keyword */" +}; + +#endif + + +/* + * Base sizes of the raw AML resource descriptors, indexed by resource type. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +const UINT8 AcpiGbl_ResourceAmlSizes[] = +{ + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL (AML_RESOURCE_IRQ), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_DMA), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_START_DEPENDENT), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_DEPENDENT), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_IO), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_IO), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_FIXED_DMA), + 0, + 0, + 0, + ACPI_AML_SIZE_SMALL (AML_RESOURCE_VENDOR_SMALL), + ACPI_AML_SIZE_SMALL (AML_RESOURCE_END_TAG), + + /* Large descriptors */ + + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY24), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_GENERIC_REGISTER), + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_VENDOR_LARGE), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_MEMORY32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_FIXED_MEMORY32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS32), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS16), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_IRQ), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_ADDRESS64), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_EXTENDED_ADDRESS64), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_GPIO), + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS), +}; + +const UINT8 AcpiGbl_ResourceAmlSerialBusSizes[] = +{ + 0, + ACPI_AML_SIZE_LARGE (AML_RESOURCE_I2C_SERIALBUS), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_SPI_SERIALBUS), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_UART_SERIALBUS), +}; + + +/* + * Resource types, used to validate the resource length field. + * The length of fixed-length types must match exactly, variable + * lengths must meet the minimum required length, etc. + * Zero indicates a reserved (and therefore invalid) resource type. + */ +static const UINT8 AcpiGbl_ResourceTypes[] = +{ + /* Small descriptors */ + + 0, + 0, + 0, + 0, + ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ + ACPI_FIXED_LENGTH, /* 05 DMA */ + ACPI_SMALL_VARIABLE_LENGTH, /* 06 StartDependentFunctions */ + ACPI_FIXED_LENGTH, /* 07 EndDependentFunctions */ + ACPI_FIXED_LENGTH, /* 08 IO */ + ACPI_FIXED_LENGTH, /* 09 FixedIO */ + ACPI_FIXED_LENGTH, /* 0A FixedDMA */ + 0, + 0, + 0, + ACPI_VARIABLE_LENGTH, /* 0E VendorShort */ + ACPI_FIXED_LENGTH, /* 0F EndTag */ + + /* Large descriptors */ + + 0, + ACPI_FIXED_LENGTH, /* 01 Memory24 */ + ACPI_FIXED_LENGTH, /* 02 GenericRegister */ + 0, + ACPI_VARIABLE_LENGTH, /* 04 VendorLong */ + ACPI_FIXED_LENGTH, /* 05 Memory32 */ + ACPI_FIXED_LENGTH, /* 06 Memory32Fixed */ + ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ + ACPI_VARIABLE_LENGTH, /* 08 Word* address */ + ACPI_VARIABLE_LENGTH, /* 09 ExtendedIRQ */ + ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ + ACPI_FIXED_LENGTH, /* 0B Extended* address */ + ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ + 0, + ACPI_VARIABLE_LENGTH /* 0E *SerialBus */ +}; + +/* + * For the iASL compiler/disassembler, we don't want any error messages + * because the disassembler uses the resource validation code to determine + * if Buffer objects are actually Resource Templates. + */ +#ifdef ACPI_ASL_COMPILER +#define ACPI_RESOURCE_ERROR(plist) +#else +#define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiUtWalkAmlResources + * + * PARAMETERS: Aml - Pointer to the raw AML resource template + * AmlLength - Length of the entire template + * UserFunction - Called once for each descriptor found. If + * NULL, a pointer to the EndTag is returned + * Context - Passed to UserFunction + * + * RETURN: Status + * + * DESCRIPTION: Walk a raw AML resource list(buffer). User function called + * once for each resource found. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtWalkAmlResources ( + UINT8 *Aml, + ACPI_SIZE AmlLength, + ACPI_WALK_AML_CALLBACK UserFunction, + void *Context) +{ + ACPI_STATUS Status; + UINT8 *EndAml; + UINT8 ResourceIndex; + UINT32 Length; + UINT32 Offset = 0; + UINT8 EndTag[2] = {0x79, 0x00}; + + + ACPI_FUNCTION_TRACE (UtWalkAmlResources); + + + /* The absolute minimum resource template is one EndTag descriptor */ + + if (AmlLength < sizeof (AML_RESOURCE_END_TAG)) + { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); + } + + /* Point to the end of the resource template buffer */ + + EndAml = Aml + AmlLength; + + /* Walk the byte list, abort on any invalid descriptor type or length */ + + while (Aml < EndAml) + { + /* Validate the Resource Type and Resource Length */ + + Status = AcpiUtValidateResource (Aml, &ResourceIndex); + if (ACPI_FAILURE (Status)) + { + /* + * Exit on failure. Cannot continue because the descriptor length + * may be bogus also. + */ + return_ACPI_STATUS (Status); + } + + /* Get the length of this descriptor */ + + Length = AcpiUtGetDescriptorLength (Aml); + + /* Invoke the user function */ + + if (UserFunction) + { + Status = UserFunction (Aml, Length, Offset, ResourceIndex, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* An EndTag descriptor terminates this resource template */ + + if (AcpiUtGetResourceType (Aml) == ACPI_RESOURCE_NAME_END_TAG) + { + /* + * There must be at least one more byte in the buffer for + * the 2nd byte of the EndTag + */ + if ((Aml + 1) >= EndAml) + { + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); + } + + /* Return the pointer to the EndTag if requested */ + + if (!UserFunction) + { + *(void **) Context = Aml; + } + + /* Normal exit */ + + return_ACPI_STATUS (AE_OK); + } + + Aml += Length; + Offset += Length; + } + + /* Did not find an EndTag descriptor */ + + if (UserFunction) + { + /* Insert an EndTag anyway. AcpiRsGetListLength always leaves room */ + + (void) AcpiUtValidateResource (EndTag, &ResourceIndex); + Status = UserFunction (EndTag, 2, Offset, ResourceIndex, Context); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + return_ACPI_STATUS (AE_AML_NO_RESOURCE_END_TAG); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidateResource + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * ReturnIndex - Where the resource index is returned. NULL + * if the index is not required. + * + * RETURN: Status, and optionally the Index into the global resource tables + * + * DESCRIPTION: Validate an AML resource descriptor by checking the Resource + * Type and Resource Length. Returns an index into the global + * resource information/dispatch tables for later use. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtValidateResource ( + void *Aml, + UINT8 *ReturnIndex) +{ + AML_RESOURCE *AmlResource; + UINT8 ResourceType; + UINT8 ResourceIndex; + ACPI_RS_LENGTH ResourceLength; + ACPI_RS_LENGTH MinimumResourceLength; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * 1) Validate the ResourceType field (Byte 0) + */ + ResourceType = ACPI_GET8 (Aml); + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ResourceType & ACPI_RESOURCE_NAME_LARGE) + { + /* Verify the large resource type (name) against the max */ + + if (ResourceType > ACPI_RESOURCE_NAME_LARGE_MAX) + { + goto InvalidResource; + } + + /* + * Large Resource Type -- bits 6:0 contain the name + * Translate range 0x80-0x8B to index range 0x10-0x1B + */ + ResourceIndex = (UINT8) (ResourceType - 0x70); + } + else + { + /* + * Small Resource Type -- bits 6:3 contain the name + * Shift range to index range 0x00-0x0F + */ + ResourceIndex = (UINT8) + ((ResourceType & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); + } + + /* + * Check validity of the resource type, via AcpiGbl_ResourceTypes. Zero + * indicates an invalid resource. + */ + if (!AcpiGbl_ResourceTypes[ResourceIndex]) + { + goto InvalidResource; + } + + /* + * Validate the ResourceLength field. This ensures that the length + * is at least reasonable, and guarantees that it is non-zero. + */ + ResourceLength = AcpiUtGetResourceLength (Aml); + MinimumResourceLength = AcpiGbl_ResourceAmlSizes[ResourceIndex]; + + /* Validate based upon the type of resource - fixed length or variable */ + + switch (AcpiGbl_ResourceTypes[ResourceIndex]) + { + case ACPI_FIXED_LENGTH: + + /* Fixed length resource, length must match exactly */ + + if (ResourceLength != MinimumResourceLength) + { + goto BadResourceLength; + } + break; + + case ACPI_VARIABLE_LENGTH: + + /* Variable length resource, length must be at least the minimum */ + + if (ResourceLength < MinimumResourceLength) + { + goto BadResourceLength; + } + break; + + case ACPI_SMALL_VARIABLE_LENGTH: + + /* Small variable length resource, length can be (Min) or (Min-1) */ + + if ((ResourceLength > MinimumResourceLength) || + (ResourceLength < (MinimumResourceLength - 1))) + { + goto BadResourceLength; + } + break; + + default: + + /* Shouldn't happen (because of validation earlier), but be sure */ + + goto InvalidResource; + } + + AmlResource = ACPI_CAST_PTR (AML_RESOURCE, Aml); + if (ResourceType == ACPI_RESOURCE_NAME_SERIAL_BUS) + { + /* Validate the BusType field */ + + if ((AmlResource->CommonSerialBus.Type == 0) || + (AmlResource->CommonSerialBus.Type > AML_RESOURCE_MAX_SERIALBUSTYPE)) + { + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", + AmlResource->CommonSerialBus.Type)); + return (AE_AML_INVALID_RESOURCE_TYPE); + } + } + + /* Optionally return the resource table index */ + + if (ReturnIndex) + { + *ReturnIndex = ResourceIndex; + } + + return (AE_OK); + + +InvalidResource: + + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + ResourceType)); + return (AE_AML_INVALID_RESOURCE_TYPE); + +BadResourceLength: + + ACPI_RESOURCE_ERROR ((AE_INFO, + "Invalid resource descriptor length: Type " + "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", + ResourceType, ResourceLength, MinimumResourceLength)); + return (AE_AML_BAD_RESOURCE_LENGTH); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceType + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: The Resource Type with no extraneous bits (except the + * Large/Small descriptor bit -- this is left alone) + * + * DESCRIPTION: Extract the Resource Type/Name from the first byte of + * a resource descriptor. + * + ******************************************************************************/ + +UINT8 +AcpiUtGetResourceType ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + /* Large Resource Type -- bits 6:0 contain the name */ + + return (ACPI_GET8 (Aml)); + } + else + { + /* Small Resource Type -- bits 6:3 contain the name */ + + return ((UINT8) (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte Length + * + * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By + * definition, this does not include the size of the descriptor + * header or the length field itself. + * + ******************************************************************************/ + +UINT16 +AcpiUtGetResourceLength ( + void *Aml) +{ + ACPI_RS_LENGTH ResourceLength; + + + ACPI_FUNCTION_ENTRY (); + + + /* + * Byte 0 contains the descriptor name (Resource Type) + * Examine the large/small bit in the resource header + */ + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + /* Large Resource type -- bytes 1-2 contain the 16-bit length */ + + ACPI_MOVE_16_TO_16 (&ResourceLength, ACPI_ADD_PTR (UINT8, Aml, 1)); + + } + else + { + /* Small Resource type -- bits 2:0 of byte 0 contain the length */ + + ResourceLength = (UINT16) (ACPI_GET8 (Aml) & + ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); + } + + return (ResourceLength); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceHeaderLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Length of the AML header (depends on large/small descriptor) + * + * DESCRIPTION: Get the length of the header for this resource. + * + ******************************************************************************/ + +UINT8 +AcpiUtGetResourceHeaderLength ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Examine the large/small bit in the resource header */ + + if (ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) + { + return (sizeof (AML_RESOURCE_LARGE_HEADER)); + } + else + { + return (sizeof (AML_RESOURCE_SMALL_HEADER)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetDescriptorLength + * + * PARAMETERS: Aml - Pointer to the raw AML resource descriptor + * + * RETURN: Byte length + * + * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the + * length of the descriptor header and the length field itself. + * Used to walk descriptor lists. + * + ******************************************************************************/ + +UINT32 +AcpiUtGetDescriptorLength ( + void *Aml) +{ + ACPI_FUNCTION_ENTRY (); + + + /* + * Get the Resource Length (does not include header length) and add + * the header length (depends on if this is a small or large resource) + */ + return (AcpiUtGetResourceLength (Aml) + + AcpiUtGetResourceHeaderLength (Aml)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceEndTag + * + * PARAMETERS: ObjDesc - The resource template buffer object + * EndTag - Where the pointer to the EndTag is returned + * + * RETURN: Status, pointer to the end tag + * + * DESCRIPTION: Find the EndTag resource descriptor in an AML resource template + * Note: allows a buffer length of zero. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtGetResourceEndTag ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT8 **EndTag) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtGetResourceEndTag); + + + /* Allow a buffer length of zero */ + + if (!ObjDesc->Buffer.Length) + { + *EndTag = ObjDesc->Buffer.Pointer; + return_ACPI_STATUS (AE_OK); + } + + /* Validate the template and get a pointer to the EndTag */ + + Status = AcpiUtWalkAmlResources (ObjDesc->Buffer.Pointer, + ObjDesc->Buffer.Length, NULL, EndTag); + + return_ACPI_STATUS (Status); +} + + diff --git a/source/components/utilities/utstate.c b/source/components/utilities/utstate.c new file mode 100644 index 0000000..62a1aef --- /dev/null +++ b/source/components/utilities/utstate.c @@ -0,0 +1,398 @@ +/******************************************************************************* + * + * Module Name: utstate - state object support procedures + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTSTATE_C__ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstate") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePkgStateAndPush + * + * PARAMETERS: Object - Object to be added to the new state + * Action - Increment/Decrement + * StateList - List the state will be added to + * + * RETURN: Status + * + * DESCRIPTION: Create a new state and push it + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreatePkgStateAndPush ( + void *InternalObject, + void *ExternalObject, + UINT16 Index, + ACPI_GENERIC_STATE **StateList) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + State = AcpiUtCreatePkgState (InternalObject, ExternalObject, Index); + if (!State) + { + return (AE_NO_MEMORY); + } + + AcpiUtPushGenericState (StateList, State); + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPushGenericState + * + * PARAMETERS: ListHead - Head of the state stack + * State - State object to push + * + * RETURN: None + * + * DESCRIPTION: Push a state object onto a state stack + * + ******************************************************************************/ + +void +AcpiUtPushGenericState ( + ACPI_GENERIC_STATE **ListHead, + ACPI_GENERIC_STATE *State) +{ + ACPI_FUNCTION_TRACE (UtPushGenericState); + + + /* Push the state object onto the front of the list (stack) */ + + State->Common.Next = *ListHead; + *ListHead = State; + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPopGenericState + * + * PARAMETERS: ListHead - Head of the state stack + * + * RETURN: The popped state object + * + * DESCRIPTION: Pop a state object from a state stack + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtPopGenericState ( + ACPI_GENERIC_STATE **ListHead) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtPopGenericState); + + + /* Remove the state object at the head of the list (stack) */ + + State = *ListHead; + if (State) + { + /* Update the list head */ + + *ListHead = State->Common.Next; + } + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateGenericState + * + * PARAMETERS: None + * + * RETURN: The new state object. NULL on failure. + * + * DESCRIPTION: Create a generic state object. Attempt to obtain one from + * the global state cache; If none available, create a new one. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateGenericState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + State = AcpiOsAcquireObject (AcpiGbl_StateCache); + if (State) + { + /* Initialize */ + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE; + } + + return (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateThreadState + * + * PARAMETERS: None + * + * RETURN: New Thread State. NULL on failure + * + * DESCRIPTION: Create a "Thread State" - a flavor of the generic state used + * to track per-thread info during method execution + * + ******************************************************************************/ + +ACPI_THREAD_STATE * +AcpiUtCreateThreadState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtCreateThreadState); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_THREAD; + State->Thread.ThreadId = AcpiOsGetThreadId (); + + /* Check for invalid thread ID - zero is very bad, it will break things */ + + if (!State->Thread.ThreadId) + { + ACPI_ERROR ((AE_INFO, "Invalid zero ID from AcpiOsGetThreadId")); + State->Thread.ThreadId = (ACPI_THREAD_ID) 1; + } + + return_PTR ((ACPI_THREAD_STATE *) State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateUpdateState + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create an "Update State" - a flavor of the generic state used + * to update reference counts and delete complex objects such + * as packages. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateUpdateState ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE_PTR (UtCreateUpdateState, Object); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_UPDATE; + State->Update.Object = Object; + State->Update.Value = Action; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreatePkgState + * + * PARAMETERS: Object - Initial Object to be installed in the state + * Action - Update action to be performed + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Package State" + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreatePkgState ( + void *InternalObject, + void *ExternalObject, + UINT16 Index) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE_PTR (UtCreatePkgState, InternalObject); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the update struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_PACKAGE; + State->Pkg.SourceObject = (ACPI_OPERAND_OBJECT *) InternalObject; + State->Pkg.DestObject = ExternalObject; + State->Pkg.Index= Index; + State->Pkg.NumPackages = 1; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateControlState + * + * PARAMETERS: None + * + * RETURN: New state object, null on failure + * + * DESCRIPTION: Create a "Control State" - a flavor of the generic state used + * to support nested IF/WHILE constructs in the AML. + * + ******************************************************************************/ + +ACPI_GENERIC_STATE * +AcpiUtCreateControlState ( + void) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_TRACE (UtCreateControlState); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return_PTR (NULL); + } + + /* Init fields specific to the control struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_CONTROL; + State->Common.State = ACPI_CONTROL_CONDITIONAL_EXECUTING; + + return_PTR (State); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDeleteGenericState + * + * PARAMETERS: State - The state object to be deleted + * + * RETURN: None + * + * DESCRIPTION: Release a state object to the state cache. NULL state objects + * are ignored. + * + ******************************************************************************/ + +void +AcpiUtDeleteGenericState ( + ACPI_GENERIC_STATE *State) +{ + ACPI_FUNCTION_TRACE (UtDeleteGenericState); + + + /* Ignore null state */ + + if (State) + { + (void) AcpiOsReleaseObject (AcpiGbl_StateCache, State); + } + return_VOID; +} + + diff --git a/source/components/utilities/uttrack.c b/source/components/utilities/uttrack.c new file mode 100644 index 0000000..106cc24 --- /dev/null +++ b/source/components/utilities/uttrack.c @@ -0,0 +1,711 @@ +/****************************************************************************** + * + * Module Name: uttrack - Memory allocation tracking routines (debug only) + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * These procedures are used for tracking memory leaks in the subsystem, and + * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set. + * + * Each memory allocation is tracked via a doubly linked list. Each + * element contains the caller's component, module name, function name, and + * line number. AcpiUtAllocate and AcpiUtAllocateZeroed call + * AcpiUtTrackAllocation to add an element to the list; deletion + * occurs in the body of AcpiUtFree. + */ + +#define __UTTRACK_C__ + +#include "acpi.h" +#include "accommon.h" + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("uttrack") + +/* Local prototypes */ + +static ACPI_DEBUG_MEM_BLOCK * +AcpiUtFindAllocation ( + void *Allocation); + +static ACPI_STATUS +AcpiUtTrackAllocation ( + ACPI_DEBUG_MEM_BLOCK *Address, + ACPI_SIZE Size, + UINT8 AllocType, + UINT32 Component, + const char *Module, + UINT32 Line); + +static ACPI_STATUS +AcpiUtRemoveAllocation ( + ACPI_DEBUG_MEM_BLOCK *Address, + UINT32 Component, + const char *Module, + UINT32 Line); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtCreateList + * + * PARAMETERS: CacheName - Ascii name for the cache + * ObjectSize - Size of each cached object + * ReturnCache - Where the new cache object is returned + * + * RETURN: Status + * + * DESCRIPTION: Create a local memory list for tracking purposed + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtCreateList ( + char *ListName, + UINT16 ObjectSize, + ACPI_MEMORY_LIST **ReturnCache) +{ + ACPI_MEMORY_LIST *Cache; + + + Cache = AcpiOsAllocate (sizeof (ACPI_MEMORY_LIST)); + if (!Cache) + { + return (AE_NO_MEMORY); + } + + ACPI_MEMSET (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + + Cache->ListName = ListName; + Cache->ObjectSize = ObjectSize; + + *ReturnCache = Cache; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateAndTrack + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: The subsystem's equivalent of malloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocateAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *Allocation; + ACPI_STATUS Status; + + + Allocation = AcpiUtAllocate (Size + sizeof (ACPI_DEBUG_MEM_HEADER), + Component, Module, Line); + if (!Allocation) + { + return (NULL); + } + + Status = AcpiUtTrackAllocation (Allocation, Size, + ACPI_MEM_MALLOC, Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + AcpiOsFree (Allocation); + return (NULL); + } + + AcpiGbl_GlobalList->TotalAllocated++; + AcpiGbl_GlobalList->TotalSize += (UINT32) Size; + AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; + if (AcpiGbl_GlobalList->CurrentTotalSize > AcpiGbl_GlobalList->MaxOccupied) + { + AcpiGbl_GlobalList->MaxOccupied = AcpiGbl_GlobalList->CurrentTotalSize; + } + + return ((void *) &Allocation->UserSpace); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAllocateZeroedAndTrack + * + * PARAMETERS: Size - Size of the allocation + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. + * + ******************************************************************************/ + +void * +AcpiUtAllocateZeroedAndTrack ( + ACPI_SIZE Size, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *Allocation; + ACPI_STATUS Status; + + + Allocation = AcpiUtAllocateZeroed (Size + sizeof (ACPI_DEBUG_MEM_HEADER), + Component, Module, Line); + if (!Allocation) + { + /* Report allocation error */ + + ACPI_ERROR ((Module, Line, + "Could not allocate size %u", (UINT32) Size)); + return (NULL); + } + + Status = AcpiUtTrackAllocation (Allocation, Size, + ACPI_MEM_CALLOC, Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + AcpiOsFree (Allocation); + return (NULL); + } + + AcpiGbl_GlobalList->TotalAllocated++; + AcpiGbl_GlobalList->TotalSize += (UINT32) Size; + AcpiGbl_GlobalList->CurrentTotalSize += (UINT32) Size; + if (AcpiGbl_GlobalList->CurrentTotalSize > AcpiGbl_GlobalList->MaxOccupied) + { + AcpiGbl_GlobalList->MaxOccupied = AcpiGbl_GlobalList->CurrentTotalSize; + } + + return ((void *) &Allocation->UserSpace); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFreeAndTrack + * + * PARAMETERS: Allocation - Address of the memory to deallocate + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None + * + * DESCRIPTION: Frees the memory at Allocation + * + ******************************************************************************/ + +void +AcpiUtFreeAndTrack ( + void *Allocation, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_DEBUG_MEM_BLOCK *DebugBlock; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (UtFree, Allocation); + + + if (NULL == Allocation) + { + ACPI_ERROR ((Module, Line, + "Attempt to delete a NULL address")); + + return_VOID; + } + + DebugBlock = ACPI_CAST_PTR (ACPI_DEBUG_MEM_BLOCK, + (((char *) Allocation) - sizeof (ACPI_DEBUG_MEM_HEADER))); + + AcpiGbl_GlobalList->TotalFreed++; + AcpiGbl_GlobalList->CurrentTotalSize -= DebugBlock->Size; + + Status = AcpiUtRemoveAllocation (DebugBlock, + Component, Module, Line); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "Could not free memory")); + } + + AcpiOsFree (DebugBlock); + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "%p freed\n", Allocation)); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFindAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * + * RETURN: A list element if found; NULL otherwise. + * + * DESCRIPTION: Searches for an element in the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_DEBUG_MEM_BLOCK * +AcpiUtFindAllocation ( + void *Allocation) +{ + ACPI_DEBUG_MEM_BLOCK *Element; + + + ACPI_FUNCTION_ENTRY (); + + + Element = AcpiGbl_GlobalList->ListHead; + + /* Search for the address. */ + + while (Element) + { + if (Element == Allocation) + { + return (Element); + } + + Element = Element->Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrackAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * Size - Size of the allocation + * AllocType - MEM_MALLOC or MEM_CALLOC + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: None. + * + * DESCRIPTION: Inserts an element into the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtTrackAllocation ( + ACPI_DEBUG_MEM_BLOCK *Allocation, + ACPI_SIZE Size, + UINT8 AllocType, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_MEMORY_LIST *MemList; + ACPI_DEBUG_MEM_BLOCK *Element; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); + + + if (AcpiGbl_DisableMemTracking) + { + return_ACPI_STATUS (AE_OK); + } + + MemList = AcpiGbl_GlobalList; + Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Search list for this address to make sure it is not already on the list. + * This will catch several kinds of problems. + */ + Element = AcpiUtFindAllocation (Allocation); + if (Element) + { + ACPI_ERROR ((AE_INFO, + "UtTrackAllocation: Allocation already present in list! (%p)", + Allocation)); + + ACPI_ERROR ((AE_INFO, "Element %p Address %p", + Element, Allocation)); + + goto UnlockAndExit; + } + + /* Fill in the instance data. */ + + Allocation->Size = (UINT32) Size; + Allocation->AllocType = AllocType; + Allocation->Component = Component; + Allocation->Line = Line; + + ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); + Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; + + /* Insert at list head */ + + if (MemList->ListHead) + { + ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation; + } + + Allocation->Next = MemList->ListHead; + Allocation->Previous = NULL; + + MemList->ListHead = Allocation; + + +UnlockAndExit: + Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * Component - Component type of caller + * Module - Source file name of caller + * Line - Line number of caller + * + * RETURN: + * + * DESCRIPTION: Deletes an element from the global allocation tracking list. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtRemoveAllocation ( + ACPI_DEBUG_MEM_BLOCK *Allocation, + UINT32 Component, + const char *Module, + UINT32 Line) +{ + ACPI_MEMORY_LIST *MemList; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (UtRemoveAllocation); + + + if (AcpiGbl_DisableMemTracking) + { + return_ACPI_STATUS (AE_OK); + } + + MemList = AcpiGbl_GlobalList; + if (NULL == MemList->ListHead) + { + /* No allocations! */ + + ACPI_ERROR ((Module, Line, + "Empty allocation list, nothing to free!")); + + return_ACPI_STATUS (AE_OK); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Unlink */ + + if (Allocation->Previous) + { + (Allocation->Previous)->Next = Allocation->Next; + } + else + { + MemList->ListHead = Allocation->Next; + } + + if (Allocation->Next) + { + (Allocation->Next)->Previous = Allocation->Previous; + } + + /* Mark the segment as deleted */ + + ACPI_MEMSET (&Allocation->UserSpace, 0xEA, Allocation->Size); + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing size 0%X\n", + Allocation->Size)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpAllocationInfo + * + * PARAMETERS: + * + * RETURN: None + * + * DESCRIPTION: Print some info about the outstanding allocations. + * + ******************************************************************************/ + +void +AcpiUtDumpAllocationInfo ( + void) +{ +/* + ACPI_MEMORY_LIST *MemList; +*/ + + ACPI_FUNCTION_TRACE (UtDumpAllocationInfo); + +/* + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current allocations", + MemList->CurrentCount, + ROUND_UP_TO_1K (MemList->CurrentSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations", + MemList->MaxConcurrentCount, + ROUND_UP_TO_1K (MemList->MaxConcurrentSize))); + + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects", + RunningObjectCount, + ROUND_UP_TO_1K (RunningObjectSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Total (all) allocations", + RunningAllocCount, + ROUND_UP_TO_1K (RunningAllocSize))); + + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Current Nodes", + AcpiGbl_CurrentNodeCount, + ROUND_UP_TO_1K (AcpiGbl_CurrentNodeSize))); + + ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES, + ("%30s: %4d (%3d Kb)\n", "Max Nodes", + AcpiGbl_MaxConcurrentNodeCount, + ROUND_UP_TO_1K ((AcpiGbl_MaxConcurrentNodeCount * + sizeof (ACPI_NAMESPACE_NODE))))); +*/ + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpAllocations + * + * PARAMETERS: Component - Component(s) to dump info for. + * Module - Module to dump info for. NULL means all. + * + * RETURN: None + * + * DESCRIPTION: Print a list of all outstanding allocations. + * + ******************************************************************************/ + +void +AcpiUtDumpAllocations ( + UINT32 Component, + const char *Module) +{ + ACPI_DEBUG_MEM_BLOCK *Element; + ACPI_DESCRIPTOR *Descriptor; + UINT32 NumOutstanding = 0; + UINT8 DescriptorType; + + + ACPI_FUNCTION_TRACE (UtDumpAllocations); + + + if (AcpiGbl_DisableMemTracking) + { + return; + } + + /* + * Walk the allocation list. + */ + if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) + { + return; + } + + Element = AcpiGbl_GlobalList->ListHead; + while (Element) + { + if ((Element->Component & Component) && + ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) + { + Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); + + if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) + { + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u " + "[Not a Descriptor - too small]\n", + Descriptor, Element->Size, Element->Module, + Element->Line); + } + else + { + /* Ignore allocated objects that are in a cache */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) + { + AcpiOsPrintf ("%p Length 0x%04X %9.9s-%u [%s] ", + Descriptor, Element->Size, Element->Module, + Element->Line, AcpiUtGetDescriptorName (Descriptor)); + + /* Validate the descriptor type using Type field and length */ + + DescriptorType = 0; /* Not a valid descriptor type */ + + switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) + { + case ACPI_DESC_TYPE_OPERAND: + if (Element->Size == sizeof (ACPI_DESC_TYPE_OPERAND)) + { + DescriptorType = ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + if (Element->Size == sizeof (ACPI_DESC_TYPE_PARSER)) + { + DescriptorType = ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + if (Element->Size == sizeof (ACPI_DESC_TYPE_NAMED)) + { + DescriptorType = ACPI_DESC_TYPE_NAMED; + } + break; + + default: + break; + } + + /* Display additional info for the major descriptor types */ + + switch (DescriptorType) + { + case ACPI_DESC_TYPE_OPERAND: + AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", + AcpiUtGetTypeName (Descriptor->Object.Common.Type), + Descriptor->Object.Common.ReferenceCount); + break; + + case ACPI_DESC_TYPE_PARSER: + AcpiOsPrintf ("AmlOpcode 0x%04hX\n", + Descriptor->Op.Asl.AmlOpcode); + break; + + case ACPI_DESC_TYPE_NAMED: + AcpiOsPrintf ("%4.4s\n", + AcpiUtGetNodeName (&Descriptor->Node)); + break; + + default: + AcpiOsPrintf ( "\n"); + break; + } + } + } + + NumOutstanding++; + } + + Element = Element->Next; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + + /* Print summary */ + + if (!NumOutstanding) + { + ACPI_INFO ((AE_INFO, "No outstanding allocations")); + } + else + { + ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations", + NumOutstanding, NumOutstanding)); + } + + return_VOID; +} + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + diff --git a/source/components/utilities/utxface.c b/source/components/utilities/utxface.c new file mode 100644 index 0000000..3e858c9 --- /dev/null +++ b/source/components/utilities/utxface.c @@ -0,0 +1,837 @@ +/****************************************************************************** + * + * Module Name: utxface - External interfaces for "global" ACPI functions + * + *****************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + + +#define __UTXFACE_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acdebug.h" +#include "actables.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxface") + + +#ifndef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiInitializeSubsystem + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initializes all global variables. This is the first function + * called, so any early initialization belongs here. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInitializeSubsystem ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInitializeSubsystem); + + + AcpiGbl_StartupFlags = ACPI_SUBSYSTEM_INITIALIZE; + ACPI_DEBUG_EXEC (AcpiUtInitStackPtrTrace ()); + + /* Initialize the OS-Dependent layer */ + + Status = AcpiOsInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During OSL initialization")); + return_ACPI_STATUS (Status); + } + + /* Initialize all globals used by the subsystem */ + + Status = AcpiUtInitGlobals (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During initialization of globals")); + return_ACPI_STATUS (Status); + } + + /* Create the default mutex objects */ + + Status = AcpiUtMutexInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During Global Mutex creation")); + return_ACPI_STATUS (Status); + } + + /* + * Initialize the namespace manager and + * the root of the namespace tree + */ + Status = AcpiNsRootInitialize (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During Namespace initialization")); + return_ACPI_STATUS (Status); + } + + /* Initialize the global OSI interfaces list with the static names */ + + Status = AcpiUtInitializeInterfaces (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During OSI interfaces initialization")); + return_ACPI_STATUS (Status); + } + + /* If configured, initialize the AML debugger */ + + ACPI_DEBUGGER_EXEC (Status = AcpiDbInitialize ()); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInitializeSubsystem) + + +/******************************************************************************* + * + * FUNCTION: AcpiEnableSubsystem + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes the subsystem initialization including hardware. + * Puts system into ACPI mode if it isn't already. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableSubsystem ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiEnableSubsystem); + + +#if (!ACPI_REDUCED_HARDWARE) + + /* Enable ACPI mode */ + + if (!(Flags & ACPI_NO_ACPI_ENABLE)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Init] Going into ACPI mode\n")); + + AcpiGbl_OriginalMode = AcpiHwGetMode(); + + Status = AcpiEnable (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "AcpiEnable failed")); + return_ACPI_STATUS (Status); + } + } + + /* + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ + Status = AcpiTbInitializeFacs (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS (Status); + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* + * Install the default OpRegion handlers. These are installed unless + * other handlers have already been installed via the + * InstallAddressSpaceHandler interface. + */ + if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Installing default address space handlers\n")); + + Status = AcpiEvInstallRegionHandlers (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + +#if (!ACPI_REDUCED_HARDWARE) + /* + * Initialize ACPI Event handling (Fixed and General Purpose) + * + * Note1: We must have the hardware and events initialized before we can + * execute any control methods safely. Any control method can require + * ACPI hardware support, so the hardware must be fully initialized before + * any method execution! + * + * Note2: Fixed events are initialized and enabled here. GPEs are + * initialized, but cannot be enabled until after the hardware is + * completely initialized (SCI and GlobalLock activated) and the various + * initialization control methods are run (_REG, _STA, _INI) on the + * entire namespace. + */ + if (!(Flags & ACPI_NO_EVENT_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Initializing ACPI events\n")); + + Status = AcpiEvInitializeEvents (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Install the SCI handler and Global Lock handler. This completes the + * hardware initialization. + */ + if (!(Flags & ACPI_NO_HANDLER_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Installing SCI/GL handlers\n")); + + Status = AcpiEvInstallXruptHandlers (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + +#endif /* !ACPI_REDUCED_HARDWARE */ + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableSubsystem) + + +/******************************************************************************* + * + * FUNCTION: AcpiInitializeObjects + * + * PARAMETERS: Flags - Init/enable Options + * + * RETURN: Status + * + * DESCRIPTION: Completes namespace initialization by initializing device + * objects and executing AML code for Regions, buffers, etc. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInitializeObjects ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiInitializeObjects); + + + /* + * Run all _REG methods + * + * Note: Any objects accessed by the _REG methods will be automatically + * initialized, even if they contain executable AML (see the call to + * AcpiNsInitializeObjects below). + */ + if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Executing _REG OpRegion methods\n")); + + Status = AcpiEvInitializeOpRegions (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Execute any module-level code that was detected during the table load + * phase. Although illegal since ACPI 2.0, there are many machines that + * contain this type of code. Each block of detected executable AML code + * outside of any control method is wrapped with a temporary control + * method object and placed on a global list. The methods on this list + * are executed below. + */ + AcpiNsExecModuleCodeList (); + + /* + * Initialize the objects that remain uninitialized. This runs the + * executable AML that may be part of the declaration of these objects: + * OperationRegions, BufferFields, Buffers, and Packages. + */ + if (!(Flags & ACPI_NO_OBJECT_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Completing Initialization of ACPI Objects\n")); + + Status = AcpiNsInitializeObjects (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Initialize all device objects in the namespace. This runs the device + * _STA and _INI methods. + */ + if (!(Flags & ACPI_NO_DEVICE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Initializing ACPI Devices\n")); + + Status = AcpiNsInitializeDevices (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* + * Empty the caches (delete the cached objects) on the assumption that + * the table load filled them up more than they will be at runtime -- + * thus wasting non-paged memory. + */ + Status = AcpiPurgeCachedObjects (); + + AcpiGbl_StartupFlags |= ACPI_INITIALIZED_OK; + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInitializeObjects) + + +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTerminate ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiTerminate); + + + /* Just exit if subsystem is already shutdown */ + + if (AcpiGbl_Shutdown) + { + ACPI_ERROR ((AE_INFO, "ACPI Subsystem is already terminated")); + return_ACPI_STATUS (AE_OK); + } + + /* Subsystem appears active, go ahead and shut it down */ + + AcpiGbl_Shutdown = TRUE; + AcpiGbl_StartupFlags = 0; + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); + + /* Terminate the AML Debugger if present */ + + ACPI_DEBUGGER_EXEC (AcpiGbl_DbTerminateThreads = TRUE); + + /* Shutdown and free all resources */ + + AcpiUtSubsystemShutdown (); + + /* Free the mutex objects */ + + AcpiUtMutexTerminate (); + + +#ifdef ACPI_DEBUGGER + + /* Shut down the debugger */ + + AcpiDbTerminate (); +#endif + + /* Now we can shutdown the OS-dependent layer */ + + Status = AcpiOsTerminate (); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiTerminate) + + +#ifndef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiSubsystemStatus + * + * PARAMETERS: None + * + * RETURN: Status of the ACPI subsystem + * + * DESCRIPTION: Other drivers that use the ACPI subsystem should call this + * before making any other calls, to ensure the subsystem + * initialized successfully. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSubsystemStatus ( + void) +{ + + if (AcpiGbl_StartupFlags & ACPI_INITIALIZED_OK) + { + return (AE_OK); + } + else + { + return (AE_ERROR); + } +} + +ACPI_EXPORT_SYMBOL (AcpiSubsystemStatus) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetSystemInfo + * + * PARAMETERS: OutBuffer - A buffer to receive the resources for the + * device + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: This function is called to get information about the current + * state of the ACPI subsystem. It will return system information + * in the OutBuffer. + * + * If the function fails an appropriate status will be returned + * and the value of OutBuffer is undefined. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetSystemInfo ( + ACPI_BUFFER *OutBuffer) +{ + ACPI_SYSTEM_INFO *InfoPtr; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetSystemInfo); + + + /* Parameter validation */ + + Status = AcpiUtValidateBuffer (OutBuffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (OutBuffer, sizeof (ACPI_SYSTEM_INFO)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * Populate the return buffer + */ + InfoPtr = (ACPI_SYSTEM_INFO *) OutBuffer->Pointer; + + InfoPtr->AcpiCaVersion = ACPI_CA_VERSION; + + /* System flags (ACPI capabilities) */ + + InfoPtr->Flags = ACPI_SYS_MODE_ACPI; + + /* Timer resolution - 24 or 32 bits */ + + if (AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) + { + InfoPtr->TimerResolution = 24; + } + else + { + InfoPtr->TimerResolution = 32; + } + + /* Clear the reserved fields */ + + InfoPtr->Reserved1 = 0; + InfoPtr->Reserved2 = 0; + + /* Current debug levels */ + + InfoPtr->DebugLayer = AcpiDbgLayer; + InfoPtr->DebugLevel = AcpiDbgLevel; + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetSystemInfo) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetStatistics + * + * PARAMETERS: Stats - Where the statistics are returned + * + * RETURN: Status - the status of the call + * + * DESCRIPTION: Get the contents of the various system counters + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetStatistics ( + ACPI_STATISTICS *Stats) +{ + ACPI_FUNCTION_TRACE (AcpiGetStatistics); + + + /* Parameter validation */ + + if (!Stats) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Various interrupt-based event counters */ + + Stats->SciCount = AcpiSciCount; + Stats->GpeCount = AcpiGpeCount; + + ACPI_MEMCPY (Stats->FixedEventCount, AcpiFixedEventCount, + sizeof (AcpiFixedEventCount)); + + + /* Other counters */ + + Stats->MethodCount = AcpiMethodCount; + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetStatistics) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInitializationHandler + * + * PARAMETERS: Handler - Callback procedure + * Function - Not (currently) used, see below + * + * RETURN: Status + * + * DESCRIPTION: Install an initialization handler + * + * TBD: When a second function is added, must save the Function also. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInitializationHandler ( + ACPI_INIT_HANDLER Handler, + UINT32 Function) +{ + + if (!Handler) + { + return (AE_BAD_PARAMETER); + } + + if (AcpiGbl_InitHandler) + { + return (AE_ALREADY_EXISTS); + } + + AcpiGbl_InitHandler = Handler; + return AE_OK; +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInitializationHandler) + + +/***************************************************************************** + * + * FUNCTION: AcpiPurgeCachedObjects + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Empty all caches (delete the cached objects) + * + ****************************************************************************/ + +ACPI_STATUS +AcpiPurgeCachedObjects ( + void) +{ + ACPI_FUNCTION_TRACE (AcpiPurgeCachedObjects); + + (void) AcpiOsPurgeCache (AcpiGbl_StateCache); + (void) AcpiOsPurgeCache (AcpiGbl_OperandCache); + (void) AcpiOsPurgeCache (AcpiGbl_PsNodeCache); + (void) AcpiOsPurgeCache (AcpiGbl_PsNodeExtCache); + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiPurgeCachedObjects) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInterface + * + * PARAMETERS: InterfaceName - The interface to install + * + * RETURN: Status + * + * DESCRIPTION: Install an _OSI interface to the global list + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_STATUS Status; + ACPI_INTERFACE_INFO *InterfaceInfo; + + + /* Parameter validation */ + + if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + /* Check if the interface name is already in the global list */ + + InterfaceInfo = AcpiUtGetInterface (InterfaceName); + if (InterfaceInfo) + { + /* + * The interface already exists in the list. This is OK if the + * interface has been marked invalid -- just clear the bit. + */ + if (InterfaceInfo->Flags & ACPI_OSI_INVALID) + { + InterfaceInfo->Flags &= ~ACPI_OSI_INVALID; + Status = AE_OK; + } + else + { + Status = AE_ALREADY_EXISTS; + } + } + else + { + /* New interface name, install into the global list */ + + Status = AcpiUtInstallInterface (InterfaceName); + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInterface) + + +/***************************************************************************** + * + * FUNCTION: AcpiRemoveInterface + * + * PARAMETERS: InterfaceName - The interface to remove + * + * RETURN: Status + * + * DESCRIPTION: Remove an _OSI interface from the global list + * + ****************************************************************************/ + +ACPI_STATUS +AcpiRemoveInterface ( + ACPI_STRING InterfaceName) +{ + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!InterfaceName || (ACPI_STRLEN (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + Status = AcpiUtRemoveInterface (InterfaceName); + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveInterface) + + +/***************************************************************************** + * + * FUNCTION: AcpiInstallInterfaceHandler + * + * PARAMETERS: Handler - The _OSI interface handler to install + * NULL means "remove existing handler" + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for the predefined _OSI ACPI method. + * invoked during execution of the internal implementation of + * _OSI. A NULL handler simply removes any existing handler. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiInstallInterfaceHandler ( + ACPI_INTERFACE_HANDLER Handler) +{ + ACPI_STATUS Status = AE_OK; + + + (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + + if (Handler && AcpiGbl_InterfaceHandler) + { + Status = AE_ALREADY_EXISTS; + } + else + { + AcpiGbl_InterfaceHandler = Handler; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInterfaceHandler) + + +/***************************************************************************** + * + * FUNCTION: AcpiCheckAddressRange + * + * PARAMETERS: SpaceId - Address space ID + * Address - Start address + * Length - Length + * Warn - TRUE if warning on overlap desired + * + * RETURN: Count of the number of conflicts detected. + * + * DESCRIPTION: Check if the input address range overlaps any of the + * ASL operation region address ranges. + * + ****************************************************************************/ + +UINT32 +AcpiCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + ACPI_SIZE Length, + BOOLEAN Warn) +{ + UINT32 Overlaps; + ACPI_STATUS Status; + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (0); + } + + Overlaps = AcpiUtCheckAddressRange (SpaceId, Address, + (UINT32) Length, Warn); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Overlaps); +} + +ACPI_EXPORT_SYMBOL (AcpiCheckAddressRange) + +#endif /* !ACPI_ASL_COMPILER */ diff --git a/source/components/utilities/utxferror.c b/source/components/utilities/utxferror.c new file mode 100644 index 0000000..8ffb274 --- /dev/null +++ b/source/components/utilities/utxferror.c @@ -0,0 +1,478 @@ +/******************************************************************************* + * + * Module Name: utxferror - Various error/warning output functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTXFERROR_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxferror") + +/* + * This module is used for the in-kernel ACPICA as well as the ACPICA + * tools/applications. + * + * For the iASL compiler case, the output is redirected to stderr so that + * any of the various ACPI errors and warnings do not appear in the output + * files, for either the compiler or disassembler portions of the tool. + */ +#ifdef ACPI_ASL_COMPILER +#include <stdio.h> + +extern FILE *AcpiGbl_OutputFile; + +#define ACPI_MSG_REDIRECT_BEGIN \ + FILE *OutputFile = AcpiGbl_OutputFile; \ + AcpiOsRedirectOutput (stderr); + +#define ACPI_MSG_REDIRECT_END \ + AcpiOsRedirectOutput (OutputFile); + +#else +/* + * non-iASL case - no redirection, nothing to do + */ +#define ACPI_MSG_REDIRECT_BEGIN +#define ACPI_MSG_REDIRECT_END +#endif + +/* + * Common message prefixes + */ +#define ACPI_MSG_ERROR "ACPI Error: " +#define ACPI_MSG_EXCEPTION "ACPI Exception: " +#define ACPI_MSG_WARNING "ACPI Warning: " +#define ACPI_MSG_INFO "ACPI: " + +/* + * Common message suffix + */ +#define ACPI_MSG_SUFFIX \ + AcpiOsPrintf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, ModuleName, LineNumber) + + +/******************************************************************************* + * + * FUNCTION: AcpiError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Error" message with module/line/version info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiError) + + +/******************************************************************************* + * + * FUNCTION: AcpiException + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Status - Status to be formatted + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Exception" message with module/line/version info + * and decoded ACPI_STATUS. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_EXCEPTION "%s, ", AcpiFormatException (Status)); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiException) + + +/******************************************************************************* + * + * FUNCTION: AcpiWarning + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Warning" message with module/line/version info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_WARNING); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiWarning) + + +/******************************************************************************* + * + * FUNCTION: AcpiInfo + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print generic "ACPI:" information message. There is no + * module/line/version info in order to keep the message simple. + * + * TBD: ModuleName and LineNumber args are not needed, should be removed. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiInfo ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_INFO); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + AcpiOsPrintf ("\n"); + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiInfo) + + +/* + * The remainder of this module contains internal error functions that may + * be configured out. + */ +#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP) + +/******************************************************************************* + * + * FUNCTION: AcpiUtPredefinedWarning + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Pathname - Full pathname to the node + * NodeFlags - From Namespace node for the method/object + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Warnings for the predefined validation module. Messages are + * only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of error + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedWarning ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...) +{ + va_list ArgList; + + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (NodeFlags & ANOBJ_EVALUATED) + { + return; + } + + AcpiOsPrintf (ACPI_MSG_WARNING "For %s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPredefinedInfo + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Pathname - Full pathname to the node + * NodeFlags - From Namespace node for the method/object + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Info messages for the predefined validation module. Messages + * are only emitted the first time a problem with a particular + * method/object is detected. This prevents a flood of + * messages for methods that are repeatedly evaluated. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedInfo ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT8 NodeFlags, + const char *Format, + ...) +{ + va_list ArgList; + + + /* + * Warning messages for this method/object will be disabled after the + * first time a validation fails or an object is successfully repaired. + */ + if (NodeFlags & ANOBJ_EVALUATED) + { + return; + } + + AcpiOsPrintf (ACPI_MSG_INFO "For %s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtNamespaceError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * InternalName - Name or path of the namespace node + * LookupStatus - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the NS node. + * + ******************************************************************************/ + +void +AcpiUtNamespaceError ( + const char *ModuleName, + UINT32 LineNumber, + const char *InternalName, + ACPI_STATUS LookupStatus) +{ + ACPI_STATUS Status; + UINT32 BadName; + char *Name = NULL; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + if (LookupStatus == AE_BAD_CHARACTER) + { + /* There is a non-ascii character in the name */ + + ACPI_MOVE_32_TO_32 (&BadName, ACPI_CAST_PTR (UINT32, InternalName)); + AcpiOsPrintf ("[0x%4.4X] (NON-ASCII)", BadName); + } + else + { + /* Convert path to external format */ + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, + InternalName, NULL, &Name); + + /* Print target name */ + + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf ("[%s]", Name); + } + else + { + AcpiOsPrintf ("[COULD NOT EXTERNALIZE NAME]"); + } + + if (Name) + { + ACPI_FREE (Name); + } + } + + AcpiOsPrintf (" Namespace lookup failure, %s", + AcpiFormatException (LookupStatus)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMethodError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Message - Error message to use on failure + * PrefixNode - Prefix relative to the path + * Path - Path to the node (optional) + * MethodStatus - Execution status + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname for the method. + * + ******************************************************************************/ + +void +AcpiUtMethodError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Message, + ACPI_NAMESPACE_NODE *PrefixNode, + const char *Path, + ACPI_STATUS MethodStatus) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node = PrefixNode; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_ERROR); + + if (Path) + { + Status = AcpiNsGetNode (PrefixNode, Path, ACPI_NS_NO_UPSEARCH, + &Node); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf ("[Could not get node by pathname]"); + } + } + + AcpiNsPrintNodePathname (Node, Message); + AcpiOsPrintf (", %s", AcpiFormatException (MethodStatus)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/source/components/utilities/utxfmutex.c b/source/components/utilities/utxfmutex.c new file mode 100644 index 0000000..c478431 --- /dev/null +++ b/source/components/utilities/utxfmutex.c @@ -0,0 +1,213 @@ +/******************************************************************************* + * + * Module Name: utxfmutex - external AML mutex access functions + * + ******************************************************************************/ + +/* + * Copyright (C) 2000 - 2012, Intel Corp. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGES. + */ + +#define __UTXFMUTEX_C__ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxfmutex") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtGetMutexObject ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OPERAND_OBJECT **RetObj); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetMutexObject + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * RetObj - Where the mutex object is returned + * + * RETURN: Status + * + * DESCRIPTION: Get an AML mutex object. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtGetMutexObject ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + ACPI_OPERAND_OBJECT **RetObj) +{ + ACPI_NAMESPACE_NODE *MutexNode; + ACPI_OPERAND_OBJECT *MutexObj; + ACPI_STATUS Status; + + + /* Parameter validation */ + + if (!RetObj || (!Handle && !Pathname)) + { + return (AE_BAD_PARAMETER); + } + + /* Get a the namespace node for the mutex */ + + MutexNode = Handle; + if (Pathname != NULL) + { + Status = AcpiGetHandle (Handle, Pathname, + ACPI_CAST_PTR (ACPI_HANDLE, &MutexNode)); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + /* Ensure that we actually have a Mutex object */ + + if (!MutexNode || + (MutexNode->Type != ACPI_TYPE_MUTEX)) + { + return (AE_TYPE); + } + + /* Get the low-level mutex object */ + + MutexObj = AcpiNsGetAttachedObject (MutexNode); + if (!MutexObj) + { + return (AE_NULL_OBJECT); + } + + *RetObj = MutexObj; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiAcquireMutex + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * Timeout - Max time to wait for the lock (millisec) + * + * RETURN: Status + * + * DESCRIPTION: Acquire an AML mutex. This is a device driver interface to + * AML mutex objects, and allows for transaction locking between + * drivers and AML code. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiAcquireMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + UINT16 Timeout) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *MutexObj; + + + /* Get the low-level mutex associated with Handle:Pathname */ + + Status = AcpiUtGetMutexObject (Handle, Pathname, &MutexObj); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Acquire the OS mutex */ + + Status = AcpiOsAcquireMutex (MutexObj->Mutex.OsMutex, Timeout); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiReleaseMutex + * + * PARAMETERS: Handle - Mutex or prefix handle (optional) + * Pathname - Mutex pathname (optional) + * + * RETURN: Status + * + * DESCRIPTION: Release an AML mutex. This is a device driver interface to + * AML mutex objects, and allows for transaction locking between + * drivers and AML code. The mutex node is pointed to by + * Handle:Pathname. Either Handle or Pathname can be NULL, but + * not both. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiReleaseMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *MutexObj; + + + /* Get the low-level mutex associated with Handle:Pathname */ + + Status = AcpiUtGetMutexObject (Handle, Pathname, &MutexObj); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Release the OS mutex */ + + AcpiOsReleaseMutex (MutexObj->Mutex.OsMutex); + return (AE_OK); +} |