mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 05:31:08 -04:00
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
This commit is contained in:
commit
1da177e4c3
17291 files changed
+6718755
No files matched your search
@@ -0,0 +1,10 @@
|
||||
#
|
||||
# Makefile for all Linux ACPI interpreter subdirectories
|
||||
#
|
||||
|
||||
obj-y := exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\
|
||||
exconvrt.o exfldio.o exoparg1.o exprep.o exresop.o exsystem.o\
|
||||
excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \
|
||||
exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o
|
||||
|
||||
EXTRA_CFLAGS += $(ACPI_CFLAGS)
|
||||
@@ -0,0 +1,487 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/actables.h>
|
||||
#include <acpi/acdispat.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exconfig")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_add_table
|
||||
*
|
||||
* PARAMETERS: Table - Pointer to raw table
|
||||
* parent_node - Where to load the table (scope)
|
||||
* ddb_handle - Where to return the table handle.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Common function to Install and Load an ACPI table with a
|
||||
* returned table handle.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_add_table (
|
||||
struct acpi_table_header *table,
|
||||
struct acpi_namespace_node *parent_node,
|
||||
union acpi_operand_object **ddb_handle)
|
||||
{
|
||||
acpi_status status;
|
||||
struct acpi_table_desc table_info;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_add_table");
|
||||
|
||||
|
||||
/* Create an object to be the table handle */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Install the new table into the local data structures */
|
||||
|
||||
ACPI_MEMSET (&table_info, 0, sizeof (struct acpi_table_desc));
|
||||
|
||||
table_info.type = ACPI_TABLE_SSDT;
|
||||
table_info.pointer = table;
|
||||
table_info.length = (acpi_size) table->length;
|
||||
table_info.allocation = ACPI_MEM_ALLOCATED;
|
||||
|
||||
status = acpi_tb_install_table (&table_info);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Add the table to the namespace */
|
||||
|
||||
status = acpi_ns_load_table (table_info.installed_desc, parent_node);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
/* Uninstall table on error */
|
||||
|
||||
(void) acpi_tb_uninstall_table (table_info.installed_desc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Init the table handle */
|
||||
|
||||
obj_desc->reference.opcode = AML_LOAD_OP;
|
||||
obj_desc->reference.object = table_info.installed_desc;
|
||||
*ddb_handle = obj_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
|
||||
|
||||
cleanup:
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_load_table_op
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state with operands
|
||||
* return_desc - Where to store the return object
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Load an ACPI table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_load_table_op (
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object **return_desc)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
struct acpi_table_header *table;
|
||||
struct acpi_namespace_node *parent_node;
|
||||
struct acpi_namespace_node *start_node;
|
||||
struct acpi_namespace_node *parameter_node = NULL;
|
||||
union acpi_operand_object *ddb_handle;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_load_table_op");
|
||||
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Make sure that the signature does not match one of the tables that
|
||||
* is already loaded.
|
||||
*/
|
||||
status = acpi_tb_match_signature (operand[0]->string.pointer, NULL);
|
||||
if (status == AE_OK) {
|
||||
/* Signature matched -- don't allow override */
|
||||
|
||||
return_ACPI_STATUS (AE_ALREADY_EXISTS);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find the ACPI table */
|
||||
|
||||
status = acpi_tb_find_table (operand[0]->string.pointer,
|
||||
operand[1]->string.pointer,
|
||||
operand[2]->string.pointer, &table);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status != AE_NOT_FOUND) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Table not found, return an Integer=0 and AE_OK */
|
||||
|
||||
ddb_handle = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!ddb_handle) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
ddb_handle->integer.value = 0;
|
||||
*return_desc = ddb_handle;
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
/* Default nodes */
|
||||
|
||||
start_node = walk_state->scope_info->scope.node;
|
||||
parent_node = acpi_gbl_root_node;
|
||||
|
||||
/* root_path (optional parameter) */
|
||||
|
||||
if (operand[3]->string.length > 0) {
|
||||
/*
|
||||
* Find the node referenced by the root_path_string. This is the
|
||||
* location within the namespace where the table will be loaded.
|
||||
*/
|
||||
status = acpi_ns_get_node_by_path (operand[3]->string.pointer, start_node,
|
||||
ACPI_NS_SEARCH_PARENT, &parent_node);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
/* parameter_path (optional parameter) */
|
||||
|
||||
if (operand[4]->string.length > 0) {
|
||||
if ((operand[4]->string.pointer[0] != '\\') &&
|
||||
(operand[4]->string.pointer[0] != '^')) {
|
||||
/*
|
||||
* Path is not absolute, so it will be relative to the node
|
||||
* referenced by the root_path_string (or the NS root if omitted)
|
||||
*/
|
||||
start_node = parent_node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the node referenced by the parameter_path_string
|
||||
*/
|
||||
status = acpi_ns_get_node_by_path (operand[4]->string.pointer, start_node,
|
||||
ACPI_NS_SEARCH_PARENT, ¶meter_node);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Load the table into the namespace */
|
||||
|
||||
status = acpi_ex_add_table (table, parent_node, &ddb_handle);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Parameter Data (optional) */
|
||||
|
||||
if (parameter_node) {
|
||||
/* Store the parameter data into the optional parameter object */
|
||||
|
||||
status = acpi_ex_store (operand[5], ACPI_CAST_PTR (union acpi_operand_object, parameter_node),
|
||||
walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
(void) acpi_ex_unload_table (ddb_handle);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
*return_desc = ddb_handle;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_load_op
|
||||
*
|
||||
* PARAMETERS: obj_desc - Region or Field where the table will be
|
||||
* obtained
|
||||
* Target - Where a handle to the table will be stored
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Load an ACPI table from a field or operation region
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_load_op (
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object *target,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *ddb_handle;
|
||||
union acpi_operand_object *buffer_desc = NULL;
|
||||
struct acpi_table_header *table_ptr = NULL;
|
||||
acpi_physical_address address;
|
||||
struct acpi_table_header table_header;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_load_op");
|
||||
|
||||
|
||||
/* Object can be either an op_region or a Field */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Region %p %s\n",
|
||||
obj_desc, acpi_ut_get_object_type_name (obj_desc)));
|
||||
|
||||
/*
|
||||
* If the Region Address and Length have not been previously evaluated,
|
||||
* evaluate them now and save the results.
|
||||
*/
|
||||
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
status = acpi_ds_get_region_arguments (obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the base physical address of the region */
|
||||
|
||||
address = obj_desc->region.address;
|
||||
|
||||
/* Get the table length from the table header */
|
||||
|
||||
table_header.length = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
|
||||
(acpi_physical_address) (i + address), 8,
|
||||
((u8 *) &table_header) + i);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sanity check the table length */
|
||||
|
||||
if (table_header.length < sizeof (struct acpi_table_header)) {
|
||||
return_ACPI_STATUS (AE_BAD_HEADER);
|
||||
}
|
||||
|
||||
/* Allocate a buffer for the entire table */
|
||||
|
||||
table_ptr = ACPI_MEM_ALLOCATE (table_header.length);
|
||||
if (!table_ptr) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Get the entire table from the op region */
|
||||
|
||||
for (i = 0; i < table_header.length; i++) {
|
||||
status = acpi_ev_address_space_dispatch (obj_desc, ACPI_READ,
|
||||
(acpi_physical_address) (i + address), 8,
|
||||
((u8 *) table_ptr + i));
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load from Field %p %s\n",
|
||||
obj_desc, acpi_ut_get_object_type_name (obj_desc)));
|
||||
|
||||
/*
|
||||
* The length of the field must be at least as large as the table.
|
||||
* Read the entire field and thus the entire table. Buffer is
|
||||
* allocated during the read.
|
||||
*/
|
||||
status = acpi_ex_read_data_from_field (walk_state, obj_desc, &buffer_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
table_ptr = ACPI_CAST_PTR (struct acpi_table_header, buffer_desc->buffer.pointer);
|
||||
|
||||
/* Sanity check the table length */
|
||||
|
||||
if (table_ptr->length < sizeof (struct acpi_table_header)) {
|
||||
return_ACPI_STATUS (AE_BAD_HEADER);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* The table must be either an SSDT or a PSDT */
|
||||
|
||||
if ((!ACPI_STRNCMP (table_ptr->signature,
|
||||
acpi_gbl_table_data[ACPI_TABLE_PSDT].signature,
|
||||
acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) &&
|
||||
(!ACPI_STRNCMP (table_ptr->signature,
|
||||
acpi_gbl_table_data[ACPI_TABLE_SSDT].signature,
|
||||
acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Table has invalid signature [%4.4s], must be SSDT or PSDT\n",
|
||||
table_ptr->signature));
|
||||
status = AE_BAD_SIGNATURE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Install the new table into the local data structures */
|
||||
|
||||
status = acpi_ex_add_table (table_ptr, acpi_gbl_root_node, &ddb_handle);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Store the ddb_handle into the Target operand */
|
||||
|
||||
status = acpi_ex_store (ddb_handle, target, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
(void) acpi_ex_unload_table (ddb_handle);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
if (buffer_desc) {
|
||||
acpi_ut_remove_reference (buffer_desc);
|
||||
}
|
||||
else {
|
||||
ACPI_MEM_FREE (table_ptr);
|
||||
}
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_unload_table
|
||||
*
|
||||
* PARAMETERS: ddb_handle - Handle to a previously loaded table
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Unload an ACPI table
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_unload_table (
|
||||
union acpi_operand_object *ddb_handle)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *table_desc = ddb_handle;
|
||||
struct acpi_table_desc *table_info;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_unload_table");
|
||||
|
||||
|
||||
/*
|
||||
* Validate the handle
|
||||
* Although the handle is partially validated in acpi_ex_reconfiguration(),
|
||||
* when it calls acpi_ex_resolve_operands(), the handle is more completely
|
||||
* validated here.
|
||||
*/
|
||||
if ((!ddb_handle) ||
|
||||
(ACPI_GET_DESCRIPTOR_TYPE (ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
|
||||
(ACPI_GET_OBJECT_TYPE (ddb_handle) != ACPI_TYPE_LOCAL_REFERENCE)) {
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Get the actual table descriptor from the ddb_handle */
|
||||
|
||||
table_info = (struct acpi_table_desc *) table_desc->reference.object;
|
||||
|
||||
/*
|
||||
* Delete the entire namespace under this table Node
|
||||
* (Offset contains the table_id)
|
||||
*/
|
||||
acpi_ns_delete_namespace_by_owner (table_info->table_id);
|
||||
|
||||
/* Delete the table itself */
|
||||
|
||||
(void) acpi_tb_uninstall_table (table_info->installed_desc);
|
||||
|
||||
/* Delete the table descriptor (ddb_handle) */
|
||||
|
||||
acpi_ut_remove_reference (table_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,708 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exconvrt - Object conversion routines
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exconvrt")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_convert_to_integer
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the new Integer object is returned
|
||||
* Flags - Used for string conversion
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Convert an ACPI Object to an integer.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_convert_to_integer (
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **result_desc,
|
||||
u32 flags)
|
||||
{
|
||||
union acpi_operand_object *return_desc;
|
||||
u8 *pointer;
|
||||
acpi_integer result;
|
||||
u32 i;
|
||||
u32 count;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_integer", obj_desc);
|
||||
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* No conversion necessary */
|
||||
|
||||
*result_desc = obj_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* Note: Takes advantage of common buffer/string fields */
|
||||
|
||||
pointer = obj_desc->buffer.pointer;
|
||||
count = obj_desc->buffer.length;
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the buffer/string to an integer. Note that both buffers and
|
||||
* strings are treated as raw data - we don't convert ascii to hex for
|
||||
* strings.
|
||||
*
|
||||
* There are two terminating conditions for the loop:
|
||||
* 1) The size of an integer has been reached, or
|
||||
* 2) The end of the buffer or string has been reached
|
||||
*/
|
||||
result = 0;
|
||||
|
||||
/*
|
||||
* String conversion is different than Buffer conversion
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/*
|
||||
* Convert string to an integer - for most cases, the string must be
|
||||
* hexadecimal as per the ACPI specification. The only exception (as
|
||||
* of ACPI 3.0) is that the to_integer() operator allows both decimal
|
||||
* and hexadecimal strings (hex prefixed with "0x").
|
||||
*/
|
||||
status = acpi_ut_strtoul64 ((char *) pointer, flags, &result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Check for zero-length buffer */
|
||||
|
||||
if (!count) {
|
||||
return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
|
||||
}
|
||||
|
||||
/* Transfer no more than an integer's worth of data */
|
||||
|
||||
if (count > acpi_gbl_integer_byte_width) {
|
||||
count = acpi_gbl_integer_byte_width;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert buffer to an integer - we simply grab enough raw data
|
||||
* from the buffer to fill an integer
|
||||
*/
|
||||
for (i = 0; i < count; i++) {
|
||||
/*
|
||||
* Get next byte and shift it into the Result.
|
||||
* Little endian is used, meaning that the first byte of the buffer
|
||||
* is the LSB of the integer
|
||||
*/
|
||||
result |= (((acpi_integer) pointer[i]) << (i * 8));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* No other types can get here */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new integer
|
||||
*/
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Save the Result */
|
||||
|
||||
return_desc->integer.value = result;
|
||||
acpi_ex_truncate_for32bit_table (return_desc);
|
||||
*result_desc = return_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_convert_to_buffer
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the new buffer object is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Convert an ACPI Object to a Buffer
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_convert_to_buffer (
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **result_desc)
|
||||
{
|
||||
union acpi_operand_object *return_desc;
|
||||
u8 *new_buf;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_buffer", obj_desc);
|
||||
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* No conversion necessary */
|
||||
|
||||
*result_desc = obj_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/*
|
||||
* Create a new Buffer object.
|
||||
* Need enough space for one integer
|
||||
*/
|
||||
return_desc = acpi_ut_create_buffer_object (acpi_gbl_integer_byte_width);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy the integer to the buffer, LSB first */
|
||||
|
||||
new_buf = return_desc->buffer.pointer;
|
||||
ACPI_MEMCPY (new_buf,
|
||||
&obj_desc->integer.value,
|
||||
acpi_gbl_integer_byte_width);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/*
|
||||
* Create a new Buffer object
|
||||
* Size will be the string length
|
||||
*
|
||||
* NOTE: Add one to the string length to include the null terminator.
|
||||
* The ACPI spec is unclear on this subject, but there is existing
|
||||
* ASL/AML code that depends on the null being transferred to the new
|
||||
* buffer.
|
||||
*/
|
||||
return_desc = acpi_ut_create_buffer_object ((acpi_size) obj_desc->string.length + 1);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy the string to the buffer */
|
||||
|
||||
new_buf = return_desc->buffer.pointer;
|
||||
ACPI_STRNCPY ((char *) new_buf, (char *) obj_desc->string.pointer,
|
||||
obj_desc->string.length);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_TYPE);
|
||||
}
|
||||
|
||||
/* Mark buffer initialized */
|
||||
|
||||
return_desc->common.flags |= AOPOBJ_DATA_VALID;
|
||||
*result_desc = return_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_convert_to_ascii
|
||||
*
|
||||
* PARAMETERS: Integer - Value to be converted
|
||||
* Base - ACPI_STRING_DECIMAL or ACPI_STRING_HEX
|
||||
* String - Where the string is returned
|
||||
* data_width - Size of data item to be converted, in bytes
|
||||
*
|
||||
* RETURN: Actual string length
|
||||
*
|
||||
* DESCRIPTION: Convert an ACPI Integer to a hex or decimal string
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32
|
||||
acpi_ex_convert_to_ascii (
|
||||
acpi_integer integer,
|
||||
u16 base,
|
||||
u8 *string,
|
||||
u8 data_width)
|
||||
{
|
||||
acpi_integer digit;
|
||||
acpi_native_uint i;
|
||||
acpi_native_uint j;
|
||||
acpi_native_uint k = 0;
|
||||
acpi_native_uint hex_length;
|
||||
acpi_native_uint decimal_length;
|
||||
u32 remainder;
|
||||
u8 supress_zeros;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
switch (base) {
|
||||
case 10:
|
||||
|
||||
/* Setup max length for the decimal number */
|
||||
|
||||
switch (data_width) {
|
||||
case 1:
|
||||
decimal_length = ACPI_MAX8_DECIMAL_DIGITS;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
decimal_length = ACPI_MAX32_DECIMAL_DIGITS;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
default:
|
||||
decimal_length = ACPI_MAX64_DECIMAL_DIGITS;
|
||||
break;
|
||||
}
|
||||
|
||||
supress_zeros = TRUE; /* No leading zeros */
|
||||
remainder = 0;
|
||||
|
||||
for (i = decimal_length; i > 0; i--) {
|
||||
/* Divide by nth factor of 10 */
|
||||
|
||||
digit = integer;
|
||||
for (j = 0; j < i; j++) {
|
||||
(void) acpi_ut_short_divide (digit, 10, &digit, &remainder);
|
||||
}
|
||||
|
||||
/* Handle leading zeros */
|
||||
|
||||
if (remainder != 0) {
|
||||
supress_zeros = FALSE;
|
||||
}
|
||||
|
||||
if (!supress_zeros) {
|
||||
string[k] = (u8) (ACPI_ASCII_ZERO + remainder);
|
||||
k++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
|
||||
hex_length = ACPI_MUL_2 (data_width); /* 2 ascii hex chars per data byte */
|
||||
|
||||
for (i = 0, j = (hex_length-1); i < hex_length; i++, j--) {
|
||||
/* Get one hex digit, most significant digits first */
|
||||
|
||||
string[k] = (u8) acpi_ut_hex_to_ascii_char (integer, ACPI_MUL_4 (j));
|
||||
k++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Since leading zeros are supressed, we must check for the case where
|
||||
* the integer equals 0
|
||||
*
|
||||
* Finally, null terminate the string and return the length
|
||||
*/
|
||||
if (!k) {
|
||||
string [0] = ACPI_ASCII_ZERO;
|
||||
k = 1;
|
||||
}
|
||||
|
||||
string [k] = 0;
|
||||
return ((u32) k);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_convert_to_string
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be converted. Must be an
|
||||
* Integer, Buffer, or String
|
||||
* result_desc - Where the string object is returned
|
||||
* Type - String flags (base and conversion type)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Convert an ACPI Object to a string
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_convert_to_string (
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **result_desc,
|
||||
u32 type)
|
||||
{
|
||||
union acpi_operand_object *return_desc;
|
||||
u8 *new_buf;
|
||||
u32 i;
|
||||
u32 string_length = 0;
|
||||
u16 base = 16;
|
||||
u8 separator = ',';
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_convert_to_string", obj_desc);
|
||||
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* No conversion necessary */
|
||||
|
||||
*result_desc = obj_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
switch (type) {
|
||||
case ACPI_EXPLICIT_CONVERT_DECIMAL:
|
||||
|
||||
/* Make room for maximum decimal number */
|
||||
|
||||
string_length = ACPI_MAX_DECIMAL_DIGITS;
|
||||
base = 10;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Two hex string characters for each integer byte */
|
||||
|
||||
string_length = ACPI_MUL_2 (acpi_gbl_integer_byte_width);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new String
|
||||
* Need enough space for one ASCII integer (plus null terminator)
|
||||
*/
|
||||
return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
new_buf = return_desc->buffer.pointer;
|
||||
|
||||
/* Convert integer to string */
|
||||
|
||||
string_length = acpi_ex_convert_to_ascii (obj_desc->integer.value, base,
|
||||
new_buf, acpi_gbl_integer_byte_width);
|
||||
|
||||
/* Null terminate at the correct place */
|
||||
|
||||
return_desc->string.length = string_length;
|
||||
new_buf [string_length] = 0;
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Setup string length, base, and separator */
|
||||
|
||||
switch (type) {
|
||||
case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by to_decimal_string operator */
|
||||
/*
|
||||
* From ACPI: "If Data is a buffer, it is converted to a string of
|
||||
* decimal values separated by commas."
|
||||
*/
|
||||
base = 10;
|
||||
|
||||
/*
|
||||
* Calculate the final string length. Individual string values
|
||||
* are variable length (include separator for each)
|
||||
*/
|
||||
for (i = 0; i < obj_desc->buffer.length; i++) {
|
||||
if (obj_desc->buffer.pointer[i] >= 100) {
|
||||
string_length += 4;
|
||||
}
|
||||
else if (obj_desc->buffer.pointer[i] >= 10) {
|
||||
string_length += 3;
|
||||
}
|
||||
else {
|
||||
string_length += 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_IMPLICIT_CONVERT_HEX:
|
||||
/*
|
||||
* From the ACPI spec:
|
||||
*"The entire contents of the buffer are converted to a string of
|
||||
* two-character hexadecimal numbers, each separated by a space."
|
||||
*/
|
||||
separator = ' ';
|
||||
string_length = (obj_desc->buffer.length * 3);
|
||||
break;
|
||||
|
||||
case ACPI_EXPLICIT_CONVERT_HEX: /* Used by to_hex_string operator */
|
||||
/*
|
||||
* From ACPI: "If Data is a buffer, it is converted to a string of
|
||||
* hexadecimal values separated by commas."
|
||||
*/
|
||||
string_length = (obj_desc->buffer.length * 3);
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the conversion.
|
||||
* (-1 because of extra separator included in string_length from above)
|
||||
*/
|
||||
string_length--;
|
||||
if (string_length > ACPI_MAX_STRING_CONVERSION) /* ACPI limit */ {
|
||||
return_ACPI_STATUS (AE_AML_STRING_LIMIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new string object and string buffer
|
||||
*/
|
||||
return_desc = acpi_ut_create_string_object ((acpi_size) string_length);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
new_buf = return_desc->buffer.pointer;
|
||||
|
||||
/*
|
||||
* Convert buffer bytes to hex or decimal values
|
||||
* (separated by commas or spaces)
|
||||
*/
|
||||
for (i = 0; i < obj_desc->buffer.length; i++) {
|
||||
new_buf += acpi_ex_convert_to_ascii (
|
||||
(acpi_integer) obj_desc->buffer.pointer[i], base,
|
||||
new_buf, 1);
|
||||
*new_buf++ = separator; /* each separated by a comma or space */
|
||||
}
|
||||
|
||||
/* Null terminate the string (overwrites final comma/space from above) */
|
||||
|
||||
new_buf--;
|
||||
*new_buf = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_TYPE);
|
||||
}
|
||||
|
||||
*result_desc = return_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_convert_to_target_type
|
||||
*
|
||||
* PARAMETERS: destination_type - Current type of the destination
|
||||
* source_desc - Source object to be converted.
|
||||
* result_desc - Where the converted object is returned
|
||||
* walk_state - Current method state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Implements "implicit conversion" rules for storing an object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_convert_to_target_type (
|
||||
acpi_object_type destination_type,
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object **result_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_convert_to_target_type");
|
||||
|
||||
|
||||
/* Default behavior */
|
||||
|
||||
*result_desc = source_desc;
|
||||
|
||||
/*
|
||||
* If required by the target,
|
||||
* perform implicit conversion on the source before we store it.
|
||||
*/
|
||||
switch (GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)) {
|
||||
case ARGI_SIMPLE_TARGET:
|
||||
case ARGI_FIXED_TARGET:
|
||||
case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */
|
||||
|
||||
switch (destination_type) {
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
/*
|
||||
* Named field can always handle conversions
|
||||
*/
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No conversion allowed for these types */
|
||||
|
||||
if (destination_type != ACPI_GET_OBJECT_TYPE (source_desc)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"Explicit operator, will store (%s) over existing type (%s)\n",
|
||||
acpi_ut_get_object_type_name (source_desc),
|
||||
acpi_ut_get_type_name (destination_type)));
|
||||
status = AE_TYPE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ARGI_TARGETREF:
|
||||
|
||||
switch (destination_type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
/*
|
||||
* These types require an Integer operand. We can convert
|
||||
* a Buffer or a String to an Integer if necessary.
|
||||
*/
|
||||
status = acpi_ex_convert_to_integer (source_desc, result_desc,
|
||||
16);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/*
|
||||
* The operand must be a String. We can convert an
|
||||
* Integer or Buffer if necessary
|
||||
*/
|
||||
status = acpi_ex_convert_to_string (source_desc, result_desc,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/*
|
||||
* The operand must be a Buffer. We can convert an
|
||||
* Integer or String if necessary
|
||||
*/
|
||||
status = acpi_ex_convert_to_buffer (source_desc, result_desc);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ACPI_REPORT_ERROR (("Bad destination type during conversion: %X\n",
|
||||
destination_type));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ARGI_REFERENCE:
|
||||
/*
|
||||
* create_xxxx_field cases - we are storing the field object into the name
|
||||
*/
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Unknown Target type ID 0x%X Op %s dest_type %s\n",
|
||||
GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args),
|
||||
walk_state->op_info->name, acpi_ut_get_type_name (destination_type)));
|
||||
|
||||
ACPI_REPORT_ERROR (("Bad Target Type (ARGI): %X\n",
|
||||
GET_CURRENT_ARG_TYPE (walk_state->op_info->runtime_args)))
|
||||
status = AE_AML_INTERNAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Source-to-Target conversion semantics:
|
||||
*
|
||||
* If conversion to the target type cannot be performed, then simply
|
||||
* overwrite the target with the new object and type.
|
||||
*/
|
||||
if (status == AE_TYPE) {
|
||||
status = AE_OK;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,646 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: excreate - Named object creation
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/actables.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("excreate")
|
||||
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_alias
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state, contains operands
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new named alias
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_alias (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
struct acpi_namespace_node *target_node;
|
||||
struct acpi_namespace_node *alias_node;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_create_alias");
|
||||
|
||||
|
||||
/* Get the source/alias operands (both namespace nodes) */
|
||||
|
||||
alias_node = (struct acpi_namespace_node *) walk_state->operands[0];
|
||||
target_node = (struct acpi_namespace_node *) walk_state->operands[1];
|
||||
|
||||
if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
|
||||
(target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
|
||||
/*
|
||||
* Dereference an existing alias so that we don't create a chain
|
||||
* of aliases. With this code, we guarantee that an alias is
|
||||
* always exactly one level of indirection away from the
|
||||
* actual aliased name.
|
||||
*/
|
||||
target_node = ACPI_CAST_PTR (struct acpi_namespace_node, target_node->object);
|
||||
}
|
||||
|
||||
/*
|
||||
* For objects that can never change (i.e., the NS node will
|
||||
* permanently point to the same object), we can simply attach
|
||||
* the object to the new NS node. For other objects (such as
|
||||
* Integers, buffers, etc.), we have to point the Alias node
|
||||
* to the original Node.
|
||||
*/
|
||||
switch (target_node->type) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
||||
/*
|
||||
* The new alias has the type ALIAS and points to the original
|
||||
* NS node, not the object itself. This is because for these
|
||||
* types, the object can change dynamically via a Store.
|
||||
*/
|
||||
alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
|
||||
alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_METHOD:
|
||||
|
||||
/*
|
||||
* The new alias has the type ALIAS and points to the original
|
||||
* NS node, not the object itself. This is because for these
|
||||
* types, the object can change dynamically via a Store.
|
||||
*/
|
||||
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
|
||||
alias_node->object = ACPI_CAST_PTR (union acpi_operand_object, target_node);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Attach the original source object to the new Alias Node */
|
||||
|
||||
/*
|
||||
* The new alias assumes the type of the target, and it points
|
||||
* to the same object. The reference count of the object has an
|
||||
* additional reference to prevent deletion out from under either the
|
||||
* target node or the alias Node
|
||||
*/
|
||||
status = acpi_ns_attach_object (alias_node,
|
||||
acpi_ns_get_attached_object (target_node),
|
||||
target_node->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Since both operands are Nodes, we don't need to delete them */
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_event
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new event object
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_event (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_create_event");
|
||||
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_EVENT);
|
||||
if (!obj_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the actual OS semaphore, with zero initial units -- meaning
|
||||
* that the event is created in an unsignalled state
|
||||
*/
|
||||
status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0,
|
||||
&obj_desc->event.semaphore);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Attach object to the Node */
|
||||
|
||||
status = acpi_ns_attach_object ((struct acpi_namespace_node *) walk_state->operands[0],
|
||||
obj_desc, ACPI_TYPE_EVENT);
|
||||
|
||||
cleanup:
|
||||
/*
|
||||
* Remove local reference to the object (on error, will cause deletion
|
||||
* of both object and semaphore if present.)
|
||||
*/
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_mutex
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new mutex object
|
||||
*
|
||||
* Mutex (Name[0], sync_level[1])
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_mutex (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_create_mutex", ACPI_WALK_OPERANDS);
|
||||
|
||||
|
||||
/* Create the new mutex object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_MUTEX);
|
||||
if (!obj_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the actual OS semaphore.
|
||||
* One unit max to make it a mutex, with one initial unit to allow
|
||||
* the mutex to be acquired.
|
||||
*/
|
||||
status = acpi_os_create_semaphore (1, 1, &obj_desc->mutex.semaphore);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Init object and attach to NS node */
|
||||
|
||||
obj_desc->mutex.sync_level = (u8) walk_state->operands[1]->integer.value;
|
||||
obj_desc->mutex.node = (struct acpi_namespace_node *) walk_state->operands[0];
|
||||
|
||||
status = acpi_ns_attach_object (obj_desc->mutex.node,
|
||||
obj_desc, ACPI_TYPE_MUTEX);
|
||||
|
||||
|
||||
cleanup:
|
||||
/*
|
||||
* Remove local reference to the object (on error, will cause deletion
|
||||
* of both object and semaphore if present.)
|
||||
*/
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_region
|
||||
*
|
||||
* PARAMETERS: aml_start - Pointer to the region declaration AML
|
||||
* aml_length - Max length of the declaration AML
|
||||
* Operands - List of operands for the opcode
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new operation region object
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_region (
|
||||
u8 *aml_start,
|
||||
u32 aml_length,
|
||||
u8 region_space,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *obj_desc;
|
||||
struct acpi_namespace_node *node;
|
||||
union acpi_operand_object *region_obj2;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_create_region");
|
||||
|
||||
|
||||
/* Get the Namespace Node */
|
||||
|
||||
node = walk_state->op->common.node;
|
||||
|
||||
/*
|
||||
* If the region object is already attached to this node,
|
||||
* just return
|
||||
*/
|
||||
if (acpi_ns_get_attached_object (node)) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Space ID must be one of the predefined IDs, or in the user-defined
|
||||
* range
|
||||
*/
|
||||
if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
|
||||
(region_space < ACPI_USER_REGION_BEGIN)) {
|
||||
ACPI_REPORT_ERROR (("Invalid address_space type %X\n", region_space));
|
||||
return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
|
||||
acpi_ut_get_region_name (region_space), region_space));
|
||||
|
||||
/* Create the region descriptor */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
|
||||
if (!obj_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember location in AML stream of address & length
|
||||
* operands since they need to be evaluated at run time.
|
||||
*/
|
||||
region_obj2 = obj_desc->common.next_object;
|
||||
region_obj2->extra.aml_start = aml_start;
|
||||
region_obj2->extra.aml_length = aml_length;
|
||||
|
||||
/* Init the region from the operands */
|
||||
|
||||
obj_desc->region.space_id = region_space;
|
||||
obj_desc->region.address = 0;
|
||||
obj_desc->region.length = 0;
|
||||
obj_desc->region.node = node;
|
||||
|
||||
/* Install the new region object in the parent Node */
|
||||
|
||||
status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_table_region
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new data_table_region object
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_table_region (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *obj_desc;
|
||||
struct acpi_namespace_node *node;
|
||||
struct acpi_table_header *table;
|
||||
union acpi_operand_object *region_obj2;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_create_table_region");
|
||||
|
||||
|
||||
/* Get the Node from the object stack */
|
||||
|
||||
node = walk_state->op->common.node;
|
||||
|
||||
/*
|
||||
* If the region object is already attached to this node,
|
||||
* just return
|
||||
*/
|
||||
if (acpi_ns_get_attached_object (node)) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
/* Find the ACPI table */
|
||||
|
||||
status = acpi_tb_find_table (operand[1]->string.pointer,
|
||||
operand[2]->string.pointer,
|
||||
operand[3]->string.pointer, &table);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Create the region descriptor */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_REGION);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
region_obj2 = obj_desc->common.next_object;
|
||||
region_obj2->extra.region_context = NULL;
|
||||
|
||||
/* Init the region from the operands */
|
||||
|
||||
obj_desc->region.space_id = REGION_DATA_TABLE;
|
||||
obj_desc->region.address = (acpi_physical_address) ACPI_TO_INTEGER (table);
|
||||
obj_desc->region.length = table->length;
|
||||
obj_desc->region.node = node;
|
||||
obj_desc->region.flags = AOPOBJ_DATA_VALID;
|
||||
|
||||
/* Install the new region object in the parent Node */
|
||||
|
||||
status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_REGION);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = acpi_ev_initialize_region (obj_desc, FALSE);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status == AE_NOT_EXIST) {
|
||||
status = AE_OK;
|
||||
}
|
||||
else {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
obj_desc->region.flags |= AOPOBJ_SETUP_COMPLETE;
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_processor
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new processor object and populate the fields
|
||||
*
|
||||
* Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3])
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_processor (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *obj_desc;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_create_processor", walk_state);
|
||||
|
||||
|
||||
/* Create the processor object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PROCESSOR);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the processor object from the operands
|
||||
*/
|
||||
obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
|
||||
obj_desc->processor.address = (acpi_io_address) operand[2]->integer.value;
|
||||
obj_desc->processor.length = (u8) operand[3]->integer.value;
|
||||
|
||||
/* Install the processor object in the parent Node */
|
||||
|
||||
status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
|
||||
obj_desc, ACPI_TYPE_PROCESSOR);
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_power_resource
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new power_resource object and populate the fields
|
||||
*
|
||||
* power_resource (Name[0], system_level[1], resource_order[2])
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_power_resource (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
acpi_status status;
|
||||
union acpi_operand_object *obj_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_create_power_resource", walk_state);
|
||||
|
||||
|
||||
/* Create the power resource object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_POWER);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Initialize the power object from the operands */
|
||||
|
||||
obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
|
||||
obj_desc->power_resource.resource_order = (u16) operand[2]->integer.value;
|
||||
|
||||
/* Install the power resource object in the parent Node */
|
||||
|
||||
status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
|
||||
obj_desc, ACPI_TYPE_POWER);
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_create_method
|
||||
*
|
||||
* PARAMETERS: aml_start - First byte of the method's AML
|
||||
* aml_length - AML byte count for this method
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Create a new method object
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_create_method (
|
||||
u8 *aml_start,
|
||||
u32 aml_length,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *obj_desc;
|
||||
acpi_status status;
|
||||
u8 method_flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_create_method", walk_state);
|
||||
|
||||
|
||||
/* Create a new method object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_METHOD);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Save the method's AML pointer and length */
|
||||
|
||||
obj_desc->method.aml_start = aml_start;
|
||||
obj_desc->method.aml_length = aml_length;
|
||||
|
||||
/*
|
||||
* Disassemble the method flags. Split off the Arg Count
|
||||
* for efficiency
|
||||
*/
|
||||
method_flags = (u8) operand[1]->integer.value;
|
||||
|
||||
obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
|
||||
obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
|
||||
|
||||
/*
|
||||
* Get the concurrency count. If required, a semaphore will be
|
||||
* created for this method when it is parsed.
|
||||
*/
|
||||
if (acpi_gbl_all_methods_serialized) {
|
||||
obj_desc->method.concurrency = 1;
|
||||
obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
|
||||
}
|
||||
else if (method_flags & AML_METHOD_SERIALIZED) {
|
||||
/*
|
||||
* ACPI 1.0: Concurrency = 1
|
||||
* ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
|
||||
*/
|
||||
obj_desc->method.concurrency = (u8)
|
||||
(((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
|
||||
}
|
||||
else {
|
||||
obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
|
||||
}
|
||||
|
||||
/* Attach the new object to the method Node */
|
||||
|
||||
status = acpi_ns_attach_object ((struct acpi_namespace_node *) operand[0],
|
||||
obj_desc, ACPI_TYPE_METHOD);
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
|
||||
/* Remove a reference to the operand */
|
||||
|
||||
acpi_ut_remove_reference (operand[1]);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,793 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exdump - Interpreter debug output routines
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exdump")
|
||||
|
||||
|
||||
/*
|
||||
* The following routines are used for debug output only
|
||||
*/
|
||||
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_dump_operand
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Pointer to entry to be dumped
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Dump an operand object
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_dump_operand (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u32 depth)
|
||||
{
|
||||
u32 length;
|
||||
u32 index;
|
||||
|
||||
|
||||
ACPI_FUNCTION_NAME ("ex_dump_operand")
|
||||
|
||||
|
||||
if (!((ACPI_LV_EXEC & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!obj_desc) {
|
||||
/*
|
||||
* This could be a null element of a package
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p is a NS Node: ", obj_desc));
|
||||
ACPI_DUMP_ENTRY (obj_desc, ACPI_LV_EXEC);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"%p is not a node or operand object: [%s]\n",
|
||||
obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
|
||||
ACPI_DUMP_BUFFER (obj_desc, sizeof (union acpi_operand_object));
|
||||
return;
|
||||
}
|
||||
|
||||
/* obj_desc is a valid object */
|
||||
|
||||
if (depth > 0) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%*s[%u] %p ",
|
||||
depth, " ", depth, obj_desc));
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p ", obj_desc));
|
||||
}
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_DEBUG_OP:
|
||||
|
||||
acpi_os_printf ("Reference: Debug\n");
|
||||
break;
|
||||
|
||||
|
||||
case AML_NAME_OP:
|
||||
|
||||
ACPI_DUMP_PATHNAME (obj_desc->reference.object,
|
||||
"Reference: Name: ", ACPI_LV_INFO, _COMPONENT);
|
||||
ACPI_DUMP_ENTRY (obj_desc->reference.object, ACPI_LV_INFO);
|
||||
break;
|
||||
|
||||
|
||||
case AML_INDEX_OP:
|
||||
|
||||
acpi_os_printf ("Reference: Index %p\n",
|
||||
obj_desc->reference.object);
|
||||
break;
|
||||
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
|
||||
acpi_os_printf ("Reference: (ref_of) %p\n",
|
||||
obj_desc->reference.object);
|
||||
break;
|
||||
|
||||
|
||||
case AML_ARG_OP:
|
||||
|
||||
acpi_os_printf ("Reference: Arg%d",
|
||||
obj_desc->reference.offset);
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
/* Value is an Integer */
|
||||
|
||||
acpi_os_printf (" value is [%8.8X%8.8x]",
|
||||
ACPI_FORMAT_UINT64 (obj_desc->integer.value));
|
||||
}
|
||||
|
||||
acpi_os_printf ("\n");
|
||||
break;
|
||||
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
|
||||
acpi_os_printf ("Reference: Local%d",
|
||||
obj_desc->reference.offset);
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_INTEGER) {
|
||||
|
||||
/* Value is an Integer */
|
||||
|
||||
acpi_os_printf (" value is [%8.8X%8.8x]",
|
||||
ACPI_FORMAT_UINT64 (obj_desc->integer.value));
|
||||
}
|
||||
|
||||
acpi_os_printf ("\n");
|
||||
break;
|
||||
|
||||
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
|
||||
acpi_os_printf ("Reference.Node->Name %X\n",
|
||||
obj_desc->reference.node->name.integer);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Unknown opcode */
|
||||
|
||||
acpi_os_printf ("Unknown Reference opcode=%X\n",
|
||||
obj_desc->reference.opcode);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
acpi_os_printf ("Buffer len %X @ %p \n",
|
||||
obj_desc->buffer.length, obj_desc->buffer.pointer);
|
||||
|
||||
length = obj_desc->buffer.length;
|
||||
if (length > 64) {
|
||||
length = 64;
|
||||
}
|
||||
|
||||
/* Debug only -- dump the buffer contents */
|
||||
|
||||
if (obj_desc->buffer.pointer) {
|
||||
acpi_os_printf ("Buffer Contents: ");
|
||||
|
||||
for (index = 0; index < length; index++) {
|
||||
acpi_os_printf (" %02x", obj_desc->buffer.pointer[index]);
|
||||
}
|
||||
acpi_os_printf ("\n");
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
acpi_os_printf ("Integer %8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64 (obj_desc->integer.value));
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
acpi_os_printf ("Package [Len %X] element_array %p\n",
|
||||
obj_desc->package.count, obj_desc->package.elements);
|
||||
|
||||
/*
|
||||
* If elements exist, package element pointer is valid,
|
||||
* and debug_level exceeds 1, dump package's elements.
|
||||
*/
|
||||
if (obj_desc->package.count &&
|
||||
obj_desc->package.elements &&
|
||||
acpi_dbg_level > 1) {
|
||||
for (index = 0; index < obj_desc->package.count; index++) {
|
||||
acpi_ex_dump_operand (obj_desc->package.elements[index], depth+1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
acpi_os_printf ("Region %s (%X)",
|
||||
acpi_ut_get_region_name (obj_desc->region.space_id),
|
||||
obj_desc->region.space_id);
|
||||
|
||||
/*
|
||||
* If the address and length have not been evaluated,
|
||||
* don't print them.
|
||||
*/
|
||||
if (!(obj_desc->region.flags & AOPOBJ_DATA_VALID)) {
|
||||
acpi_os_printf ("\n");
|
||||
}
|
||||
else {
|
||||
acpi_os_printf (" base %8.8X%8.8X Length %X\n",
|
||||
ACPI_FORMAT_UINT64 (obj_desc->region.address),
|
||||
obj_desc->region.length);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
acpi_os_printf ("String length %X @ %p ",
|
||||
obj_desc->string.length, obj_desc->string.pointer);
|
||||
acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
|
||||
acpi_os_printf ("\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
|
||||
acpi_os_printf ("bank_field\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
|
||||
acpi_os_printf (
|
||||
"region_field: Bits=%X acc_width=%X Lock=%X Update=%X at byte=%X bit=%X of below:\n",
|
||||
obj_desc->field.bit_length, obj_desc->field.access_byte_width,
|
||||
obj_desc->field.field_flags & AML_FIELD_LOCK_RULE_MASK,
|
||||
obj_desc->field.field_flags & AML_FIELD_UPDATE_RULE_MASK,
|
||||
obj_desc->field.base_byte_offset, obj_desc->field.start_field_bit_offset);
|
||||
acpi_ex_dump_operand (obj_desc->field.region_obj, depth+1);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
acpi_os_printf ("index_field\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
||||
acpi_os_printf (
|
||||
"buffer_field: %X bits at byte %X bit %X of \n",
|
||||
obj_desc->buffer_field.bit_length, obj_desc->buffer_field.base_byte_offset,
|
||||
obj_desc->buffer_field.start_field_bit_offset);
|
||||
|
||||
if (!obj_desc->buffer_field.buffer_obj) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*NULL* \n"));
|
||||
}
|
||||
else if (ACPI_GET_OBJECT_TYPE (obj_desc->buffer_field.buffer_obj) != ACPI_TYPE_BUFFER) {
|
||||
acpi_os_printf ("*not a Buffer* \n");
|
||||
}
|
||||
else {
|
||||
acpi_ex_dump_operand (obj_desc->buffer_field.buffer_obj, depth+1);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_EVENT:
|
||||
|
||||
acpi_os_printf ("Event\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_METHOD:
|
||||
|
||||
acpi_os_printf (
|
||||
"Method(%X) @ %p:%X\n",
|
||||
obj_desc->method.param_count,
|
||||
obj_desc->method.aml_start, obj_desc->method.aml_length);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_MUTEX:
|
||||
|
||||
acpi_os_printf ("Mutex\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_DEVICE:
|
||||
|
||||
acpi_os_printf ("Device\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_POWER:
|
||||
|
||||
acpi_os_printf ("Power\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
|
||||
acpi_os_printf ("Processor\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_THERMAL:
|
||||
|
||||
acpi_os_printf ("Thermal\n");
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
/* Unknown Type */
|
||||
|
||||
acpi_os_printf ("Unknown Type %X\n", ACPI_GET_OBJECT_TYPE (obj_desc));
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_dump_operands
|
||||
*
|
||||
* PARAMETERS: Operands - Operand list
|
||||
* interpreter_mode - Load or Exec
|
||||
* Ident - Identification
|
||||
* num_levels - # of stack entries to dump above line
|
||||
* Note - Output notation
|
||||
* module_name - Caller's module name
|
||||
* line_number - Caller's invocation line number
|
||||
*
|
||||
* DESCRIPTION: Dump the object stack
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_dump_operands (
|
||||
union acpi_operand_object **operands,
|
||||
acpi_interpreter_mode interpreter_mode,
|
||||
char *ident,
|
||||
u32 num_levels,
|
||||
char *note,
|
||||
char *module_name,
|
||||
u32 line_number)
|
||||
{
|
||||
acpi_native_uint i;
|
||||
|
||||
|
||||
ACPI_FUNCTION_NAME ("ex_dump_operands");
|
||||
|
||||
|
||||
if (!ident) {
|
||||
ident = "?";
|
||||
}
|
||||
|
||||
if (!note) {
|
||||
note = "?";
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"************* Operand Stack Contents (Opcode [%s], %d Operands)\n",
|
||||
ident, num_levels));
|
||||
|
||||
if (num_levels == 0) {
|
||||
num_levels = 1;
|
||||
}
|
||||
|
||||
/* Dump the operand stack starting at the top */
|
||||
|
||||
for (i = 0; num_levels > 0; i--, num_levels--) {
|
||||
acpi_ex_dump_operand (operands[i], 0);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"************* Stack dump from %s(%d), %s\n",
|
||||
module_name, line_number, note));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_out*
|
||||
*
|
||||
* PARAMETERS: Title - Descriptive text
|
||||
* Value - Value to be displayed
|
||||
*
|
||||
* DESCRIPTION: Object dump output formatting functions. These functions
|
||||
* reduce the number of format strings required and keeps them
|
||||
* all in one place for easy modification.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_out_string (
|
||||
char *title,
|
||||
char *value)
|
||||
{
|
||||
acpi_os_printf ("%20s : %s\n", title, value);
|
||||
}
|
||||
|
||||
void
|
||||
acpi_ex_out_pointer (
|
||||
char *title,
|
||||
void *value)
|
||||
{
|
||||
acpi_os_printf ("%20s : %p\n", title, value);
|
||||
}
|
||||
|
||||
void
|
||||
acpi_ex_out_integer (
|
||||
char *title,
|
||||
u32 value)
|
||||
{
|
||||
acpi_os_printf ("%20s : %X\n", title, value);
|
||||
}
|
||||
|
||||
void
|
||||
acpi_ex_out_address (
|
||||
char *title,
|
||||
acpi_physical_address value)
|
||||
{
|
||||
|
||||
#if ACPI_MACHINE_WIDTH == 16
|
||||
acpi_os_printf ("%20s : %p\n", title, value);
|
||||
#else
|
||||
acpi_os_printf ("%20s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64 (value));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_dump_node
|
||||
*
|
||||
* PARAMETERS: *Node - Descriptor to dump
|
||||
* Flags - Force display
|
||||
*
|
||||
* DESCRIPTION: Dumps the members of the given.Node
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_dump_node (
|
||||
struct acpi_namespace_node *node,
|
||||
u32 flags)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
if (!flags) {
|
||||
if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
acpi_os_printf ("%20s : %4.4s\n", "Name", acpi_ut_get_node_name (node));
|
||||
acpi_ex_out_string ("Type", acpi_ut_get_type_name (node->type));
|
||||
acpi_ex_out_integer ("Flags", node->flags);
|
||||
acpi_ex_out_integer ("Owner Id", node->owner_id);
|
||||
acpi_ex_out_integer ("Reference Count", node->reference_count);
|
||||
acpi_ex_out_pointer ("Attached Object", acpi_ns_get_attached_object (node));
|
||||
acpi_ex_out_pointer ("child_list", node->child);
|
||||
acpi_ex_out_pointer ("next_peer", node->peer);
|
||||
acpi_ex_out_pointer ("Parent", acpi_ns_get_parent_node (node));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_dump_object_descriptor
|
||||
*
|
||||
* PARAMETERS: *Object - Descriptor to dump
|
||||
* Flags - Force display
|
||||
*
|
||||
* DESCRIPTION: Dumps the members of the object descriptor given.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_dump_object_descriptor (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u32 flags)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor");
|
||||
|
||||
|
||||
if (!flags) {
|
||||
if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) {
|
||||
return_VOID;
|
||||
}
|
||||
}
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) {
|
||||
acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags);
|
||||
acpi_os_printf ("\nAttached Object (%p):\n",
|
||||
((struct acpi_namespace_node *) obj_desc)->object);
|
||||
acpi_ex_dump_object_descriptor (
|
||||
((struct acpi_namespace_node *) obj_desc)->object, flags);
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) {
|
||||
acpi_os_printf (
|
||||
"ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n",
|
||||
obj_desc, acpi_ut_get_descriptor_name (obj_desc));
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* Common Fields */
|
||||
|
||||
acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc));
|
||||
acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count);
|
||||
acpi_ex_out_integer ("Flags", obj_desc->common.flags);
|
||||
|
||||
/* Object-specific Fields */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value",
|
||||
ACPI_FORMAT_UINT64 (obj_desc->integer.value));
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
acpi_ex_out_integer ("Length", obj_desc->string.length);
|
||||
|
||||
acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer);
|
||||
acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX);
|
||||
acpi_os_printf ("\n");
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
acpi_ex_out_integer ("Length", obj_desc->buffer.length);
|
||||
acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer);
|
||||
ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
acpi_ex_out_integer ("Flags", obj_desc->package.flags);
|
||||
acpi_ex_out_integer ("Count", obj_desc->package.count);
|
||||
acpi_ex_out_pointer ("Elements", obj_desc->package.elements);
|
||||
|
||||
/* Dump the package contents */
|
||||
|
||||
if (obj_desc->package.count > 0) {
|
||||
acpi_os_printf ("\nPackage Contents:\n");
|
||||
for (i = 0; i < obj_desc->package.count; i++) {
|
||||
acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]);
|
||||
if (obj_desc->package.elements[i]) {
|
||||
acpi_os_printf (" %s",
|
||||
acpi_ut_get_object_type_name (obj_desc->package.elements[i]));
|
||||
}
|
||||
acpi_os_printf ("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_DEVICE:
|
||||
|
||||
acpi_ex_out_pointer ("Handler", obj_desc->device.handler);
|
||||
acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify);
|
||||
acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_EVENT:
|
||||
|
||||
acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_METHOD:
|
||||
|
||||
acpi_ex_out_integer ("param_count", obj_desc->method.param_count);
|
||||
acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency);
|
||||
acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore);
|
||||
acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id);
|
||||
acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length);
|
||||
acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_MUTEX:
|
||||
|
||||
acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level);
|
||||
acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread);
|
||||
acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth);
|
||||
acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
acpi_ex_out_integer ("space_id", obj_desc->region.space_id);
|
||||
acpi_ex_out_integer ("Flags", obj_desc->region.flags);
|
||||
acpi_ex_out_address ("Address", obj_desc->region.address);
|
||||
acpi_ex_out_integer ("Length", obj_desc->region.length);
|
||||
acpi_ex_out_pointer ("Handler", obj_desc->region.handler);
|
||||
acpi_ex_out_pointer ("Next", obj_desc->region.next);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_POWER:
|
||||
|
||||
acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level);
|
||||
acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order);
|
||||
acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify);
|
||||
acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
|
||||
acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id);
|
||||
acpi_ex_out_integer ("Length", obj_desc->processor.length);
|
||||
acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address);
|
||||
acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify);
|
||||
acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify);
|
||||
acpi_ex_out_pointer ("Handler", obj_desc->processor.handler);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_THERMAL:
|
||||
|
||||
acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify);
|
||||
acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify);
|
||||
acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags);
|
||||
acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width);
|
||||
acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
|
||||
acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
|
||||
acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
|
||||
acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
acpi_ex_out_integer ("Value", obj_desc->bank_field.value);
|
||||
acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj);
|
||||
acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
acpi_ex_out_integer ("Value", obj_desc->index_field.value);
|
||||
acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj);
|
||||
acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* All object types covered above */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
acpi_ex_out_integer ("target_type", obj_desc->reference.target_type);
|
||||
acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name);
|
||||
acpi_ex_out_integer ("Offset", obj_desc->reference.offset);
|
||||
acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object);
|
||||
acpi_ex_out_pointer ("Node", obj_desc->reference.node);
|
||||
acpi_ex_out_pointer ("Where", obj_desc->reference.where);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
|
||||
|
||||
acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id);
|
||||
acpi_ex_out_pointer ("Next", obj_desc->address_space.next);
|
||||
acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list);
|
||||
acpi_ex_out_pointer ("Node", obj_desc->address_space.node);
|
||||
acpi_ex_out_pointer ("Context", obj_desc->address_space.context);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_NOTIFY:
|
||||
|
||||
acpi_ex_out_pointer ("Node", obj_desc->notify.node);
|
||||
acpi_ex_out_pointer ("Context", obj_desc->notify.context);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_ALIAS:
|
||||
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
|
||||
case ACPI_TYPE_LOCAL_EXTRA:
|
||||
case ACPI_TYPE_LOCAL_DATA:
|
||||
default:
|
||||
|
||||
acpi_os_printf (
|
||||
"ex_dump_object_descriptor: Display not implemented for object type %s\n",
|
||||
acpi_ut_get_object_type_name (obj_desc));
|
||||
break;
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
#endif /* ACPI_FUTURE_USAGE */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exfield - ACPI AML (p-code) execution - field manipulation
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exfield")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_read_data_from_field
|
||||
*
|
||||
* PARAMETERS: walk_state - Current execution state
|
||||
* obj_desc - The named field
|
||||
* ret_buffer_desc - Where the return data object is stored
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Read from a named field. Returns either an Integer or a
|
||||
* Buffer, depending on the size of the field.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_read_data_from_field (
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **ret_buffer_desc)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *buffer_desc;
|
||||
acpi_size length;
|
||||
void *buffer;
|
||||
u8 locked;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_read_data_from_field", obj_desc);
|
||||
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
|
||||
/*
|
||||
* If the buffer_field arguments have not been previously evaluated,
|
||||
* evaluate them now and save the results.
|
||||
*/
|
||||
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
status = acpi_ds_get_buffer_field_arguments (obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||
(obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
|
||||
/*
|
||||
* This is an SMBus read. We must create a buffer to hold the data
|
||||
* and directly access the region handler.
|
||||
*/
|
||||
buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
|
||||
if (!buffer_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Lock entire transaction if requested */
|
||||
|
||||
locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
|
||||
|
||||
/*
|
||||
* Perform the read.
|
||||
* Note: Smbus protocol value is passed in upper 16-bits of Function
|
||||
*/
|
||||
status = acpi_ex_access_region (obj_desc, 0,
|
||||
ACPI_CAST_PTR (acpi_integer, buffer_desc->buffer.pointer),
|
||||
ACPI_READ | (obj_desc->field.attribute << 16));
|
||||
acpi_ex_release_global_lock (locked);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a buffer for the contents of the field.
|
||||
*
|
||||
* If the field is larger than the size of an acpi_integer, create
|
||||
* a BUFFER to hold it. Otherwise, use an INTEGER. This allows
|
||||
* the use of arithmetic operators on the returned value if the
|
||||
* field size is equal or smaller than an Integer.
|
||||
*
|
||||
* Note: Field.length is in bits.
|
||||
*/
|
||||
length = (acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->field.bit_length);
|
||||
if (length > acpi_gbl_integer_byte_width) {
|
||||
/* Field is too large for an Integer, create a Buffer instead */
|
||||
|
||||
buffer_desc = acpi_ut_create_buffer_object (length);
|
||||
if (!buffer_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
buffer = buffer_desc->buffer.pointer;
|
||||
}
|
||||
else {
|
||||
/* Field will fit within an Integer (normal case) */
|
||||
|
||||
buffer_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!buffer_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
length = acpi_gbl_integer_byte_width;
|
||||
buffer_desc->integer.value = 0;
|
||||
buffer = &buffer_desc->integer.value;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"field_read [TO]: Obj %p, Type %X, Buf %p, byte_len %X\n",
|
||||
obj_desc, ACPI_GET_OBJECT_TYPE (obj_desc), buffer, (u32) length));
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"field_read [FROM]: bit_len %X, bit_off %X, byte_off %X\n",
|
||||
obj_desc->common_field.bit_length,
|
||||
obj_desc->common_field.start_field_bit_offset,
|
||||
obj_desc->common_field.base_byte_offset));
|
||||
|
||||
/* Lock entire transaction if requested */
|
||||
|
||||
locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
|
||||
|
||||
/* Read from the field */
|
||||
|
||||
status = acpi_ex_extract_from_field (obj_desc, buffer, (u32) length);
|
||||
acpi_ex_release_global_lock (locked);
|
||||
|
||||
|
||||
exit:
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_remove_reference (buffer_desc);
|
||||
}
|
||||
else if (ret_buffer_desc) {
|
||||
*ret_buffer_desc = buffer_desc;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_write_data_to_field
|
||||
*
|
||||
* PARAMETERS: source_desc - Contains data to write
|
||||
* obj_desc - The named field
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Write to a named field
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_write_data_to_field (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **result_desc)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 length;
|
||||
u32 required_length;
|
||||
void *buffer;
|
||||
void *new_buffer;
|
||||
u8 locked;
|
||||
union acpi_operand_object *buffer_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_write_data_to_field", obj_desc);
|
||||
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!source_desc || !obj_desc) {
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
|
||||
/*
|
||||
* If the buffer_field arguments have not been previously evaluated,
|
||||
* evaluate them now and save the results.
|
||||
*/
|
||||
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
status = acpi_ds_get_buffer_field_arguments (obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REGION_FIELD) &&
|
||||
(obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS)) {
|
||||
/*
|
||||
* This is an SMBus write. We will bypass the entire field mechanism
|
||||
* and handoff the buffer directly to the handler.
|
||||
*
|
||||
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
|
||||
*/
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
|
||||
ACPI_REPORT_ERROR (("SMBus write requires Buffer, found type %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
|
||||
ACPI_REPORT_ERROR (("SMBus write requires Buffer of length %X, found length %X\n",
|
||||
ACPI_SMBUS_BUFFER_SIZE, source_desc->buffer.length));
|
||||
return_ACPI_STATUS (AE_AML_BUFFER_LIMIT);
|
||||
}
|
||||
|
||||
buffer_desc = acpi_ut_create_buffer_object (ACPI_SMBUS_BUFFER_SIZE);
|
||||
if (!buffer_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
buffer = buffer_desc->buffer.pointer;
|
||||
ACPI_MEMCPY (buffer, source_desc->buffer.pointer, ACPI_SMBUS_BUFFER_SIZE);
|
||||
|
||||
/* Lock entire transaction if requested */
|
||||
|
||||
locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
|
||||
|
||||
/*
|
||||
* Perform the write (returns status and perhaps data in the same buffer)
|
||||
* Note: SMBus protocol type is passed in upper 16-bits of Function.
|
||||
*/
|
||||
status = acpi_ex_access_region (obj_desc, 0,
|
||||
(acpi_integer *) buffer,
|
||||
ACPI_WRITE | (obj_desc->field.attribute << 16));
|
||||
acpi_ex_release_global_lock (locked);
|
||||
|
||||
*result_desc = buffer_desc;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a pointer to the data to be written
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
buffer = &source_desc->integer.value;
|
||||
length = sizeof (source_desc->integer.value);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
buffer = source_desc->buffer.pointer;
|
||||
length = source_desc->buffer.length;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
buffer = source_desc->string.pointer;
|
||||
length = source_desc->string.length;
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* We must have a buffer that is at least as long as the field
|
||||
* we are writing to. This is because individual fields are
|
||||
* indivisible and partial writes are not supported -- as per
|
||||
* the ACPI specification.
|
||||
*/
|
||||
new_buffer = NULL;
|
||||
required_length = ACPI_ROUND_BITS_UP_TO_BYTES (obj_desc->common_field.bit_length);
|
||||
|
||||
if (length < required_length) {
|
||||
/* We need to create a new buffer */
|
||||
|
||||
new_buffer = ACPI_MEM_CALLOCATE (required_length);
|
||||
if (!new_buffer) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the original data to the new buffer, starting
|
||||
* at Byte zero. All unused (upper) bytes of the
|
||||
* buffer will be 0.
|
||||
*/
|
||||
ACPI_MEMCPY ((char *) new_buffer, (char *) buffer, length);
|
||||
buffer = new_buffer;
|
||||
length = required_length;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"field_write [FROM]: Obj %p (%s:%X), Buf %p, byte_len %X\n",
|
||||
source_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (source_desc)),
|
||||
ACPI_GET_OBJECT_TYPE (source_desc), buffer, length));
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"field_write [TO]: Obj %p (%s:%X), bit_len %X, bit_off %X, byte_off %X\n",
|
||||
obj_desc, acpi_ut_get_type_name (ACPI_GET_OBJECT_TYPE (obj_desc)),
|
||||
ACPI_GET_OBJECT_TYPE (obj_desc),
|
||||
obj_desc->common_field.bit_length,
|
||||
obj_desc->common_field.start_field_bit_offset,
|
||||
obj_desc->common_field.base_byte_offset));
|
||||
|
||||
/* Lock entire transaction if requested */
|
||||
|
||||
locked = acpi_ex_acquire_global_lock (obj_desc->common_field.field_flags);
|
||||
|
||||
/* Write to the field */
|
||||
|
||||
status = acpi_ex_insert_into_field (obj_desc, buffer, length);
|
||||
acpi_ex_release_global_lock (locked);
|
||||
|
||||
/* Free temporary buffer if we used one */
|
||||
|
||||
if (new_buffer) {
|
||||
ACPI_MEM_FREE (new_buffer);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,835 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exfldio - Aml Field I/O
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/acdispat.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exfldio")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_setup_region
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Field to be read or written
|
||||
* field_datum_byte_offset - Byte offset of this datum within the
|
||||
* parent field
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Common processing for acpi_ex_extract_from_field and
|
||||
* acpi_ex_insert_into_field. Initialize the Region if necessary and
|
||||
* validate the request.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_setup_region (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u32 field_datum_byte_offset)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *rgn_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset);
|
||||
|
||||
|
||||
rgn_desc = obj_desc->common_field.region_obj;
|
||||
|
||||
/* We must have a valid region */
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n",
|
||||
ACPI_GET_OBJECT_TYPE (rgn_desc),
|
||||
acpi_ut_get_object_type_name (rgn_desc)));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the Region Address and Length have not been previously evaluated,
|
||||
* evaluate them now and save the results.
|
||||
*/
|
||||
if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
status = acpi_ds_get_region_arguments (rgn_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
|
||||
/* SMBus has a non-linear address space */
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
#ifdef ACPI_UNDER_DEVELOPMENT
|
||||
/*
|
||||
* If the Field access is any_acc, we can now compute the optimal
|
||||
* access (because we know know the length of the parent region)
|
||||
*/
|
||||
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Validate the request. The entire request from the byte offset for a
|
||||
* length of one field datum (access width) must fit within the region.
|
||||
* (Region length is specified in bytes)
|
||||
*/
|
||||
if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset
|
||||
+ field_datum_byte_offset
|
||||
+ obj_desc->common_field.access_byte_width)) {
|
||||
if (acpi_gbl_enable_interpreter_slack) {
|
||||
/*
|
||||
* Slack mode only: We will go ahead and allow access to this
|
||||
* field if it is within the region length rounded up to the next
|
||||
* access width boundary.
|
||||
*/
|
||||
if (ACPI_ROUND_UP (rgn_desc->region.length,
|
||||
obj_desc->common_field.access_byte_width) >=
|
||||
(obj_desc->common_field.base_byte_offset +
|
||||
(acpi_native_uint) obj_desc->common_field.access_byte_width +
|
||||
field_datum_byte_offset)) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) {
|
||||
/*
|
||||
* This is the case where the access_type (acc_word, etc.) is wider
|
||||
* than the region itself. For example, a region of length one
|
||||
* byte, and a field with Dword access specified.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n",
|
||||
acpi_ut_get_node_name (obj_desc->common_field.node),
|
||||
obj_desc->common_field.access_byte_width,
|
||||
acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
|
||||
}
|
||||
|
||||
/*
|
||||
* Offset rounded up to next multiple of field width
|
||||
* exceeds region length, indicate an error
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n",
|
||||
acpi_ut_get_node_name (obj_desc->common_field.node),
|
||||
obj_desc->common_field.base_byte_offset,
|
||||
field_datum_byte_offset, obj_desc->common_field.access_byte_width,
|
||||
acpi_ut_get_node_name (rgn_desc->region.node), rgn_desc->region.length));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_REGION_LIMIT);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_access_region
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Field to be read
|
||||
* field_datum_byte_offset - Byte offset of this datum within the
|
||||
* parent field
|
||||
* *Value - Where to store value (must at least
|
||||
* the size of acpi_integer)
|
||||
* Function - Read or Write flag plus other region-
|
||||
* dependent flags
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Read or Write a single field datum to an Operation Region.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_access_region (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u32 field_datum_byte_offset,
|
||||
acpi_integer *value,
|
||||
u32 function)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_operand_object *rgn_desc;
|
||||
acpi_physical_address address;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_access_region");
|
||||
|
||||
|
||||
/*
|
||||
* Ensure that the region operands are fully evaluated and verify
|
||||
* the validity of the request
|
||||
*/
|
||||
status = acpi_ex_setup_region (obj_desc, field_datum_byte_offset);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* The physical address of this field datum is:
|
||||
*
|
||||
* 1) The base of the region, plus
|
||||
* 2) The base offset of the field, plus
|
||||
* 3) The current offset into the field
|
||||
*/
|
||||
rgn_desc = obj_desc->common_field.region_obj;
|
||||
address = rgn_desc->region.address
|
||||
+ obj_desc->common_field.base_byte_offset
|
||||
+ field_datum_byte_offset;
|
||||
|
||||
if ((function & ACPI_IO_MASK) == ACPI_READ) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[READ]"));
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "[WRITE]"));
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_BFIELD,
|
||||
" Region [%s:%X], Width %X, byte_base %X, Offset %X at %8.8X%8.8X\n",
|
||||
acpi_ut_get_region_name (rgn_desc->region.space_id),
|
||||
rgn_desc->region.space_id,
|
||||
obj_desc->common_field.access_byte_width,
|
||||
obj_desc->common_field.base_byte_offset,
|
||||
field_datum_byte_offset,
|
||||
ACPI_FORMAT_UINT64 (address)));
|
||||
|
||||
/* Invoke the appropriate address_space/op_region handler */
|
||||
|
||||
status = acpi_ev_address_space_dispatch (rgn_desc, function,
|
||||
address, ACPI_MUL_8 (obj_desc->common_field.access_byte_width), value);
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status == AE_NOT_IMPLEMENTED) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Region %s(%X) not implemented\n",
|
||||
acpi_ut_get_region_name (rgn_desc->region.space_id),
|
||||
rgn_desc->region.space_id));
|
||||
}
|
||||
else if (status == AE_NOT_EXIST) {
|
||||
ACPI_REPORT_ERROR ((
|
||||
"Region %s(%X) has no handler\n",
|
||||
acpi_ut_get_region_name (rgn_desc->region.space_id),
|
||||
rgn_desc->region.space_id));
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_register_overflow
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Register(Field) to be written
|
||||
* Value - Value to be stored
|
||||
*
|
||||
* RETURN: TRUE if value overflows the field, FALSE otherwise
|
||||
*
|
||||
* DESCRIPTION: Check if a value is out of range of the field being written.
|
||||
* Used to check if the values written to Index and Bank registers
|
||||
* are out of range. Normally, the value is simply truncated
|
||||
* to fit the field, but this case is most likely a serious
|
||||
* coding error in the ASL.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8
|
||||
acpi_ex_register_overflow (
|
||||
union acpi_operand_object *obj_desc,
|
||||
acpi_integer value)
|
||||
{
|
||||
|
||||
if (obj_desc->common_field.bit_length >= ACPI_INTEGER_BIT_SIZE) {
|
||||
/*
|
||||
* The field is large enough to hold the maximum integer, so we can
|
||||
* never overflow it.
|
||||
*/
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (value >= ((acpi_integer) 1 << obj_desc->common_field.bit_length)) {
|
||||
/*
|
||||
* The Value is larger than the maximum value that can fit into
|
||||
* the register.
|
||||
*/
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* The Value will fit into the field with no truncation */
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_field_datum_io
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Field to be read
|
||||
* field_datum_byte_offset - Byte offset of this datum within the
|
||||
* parent field
|
||||
* *Value - Where to store value (must be 64 bits)
|
||||
* read_write - Read or Write flag
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Read or Write a single datum of a field. The field_type is
|
||||
* demultiplexed here to handle the different types of fields
|
||||
* (buffer_field, region_field, index_field, bank_field)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_field_datum_io (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u32 field_datum_byte_offset,
|
||||
acpi_integer *value,
|
||||
u32 read_write)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_integer local_value;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset);
|
||||
|
||||
|
||||
if (read_write == ACPI_READ) {
|
||||
if (!value) {
|
||||
local_value = 0;
|
||||
value = &local_value; /* To support reads without saving return value */
|
||||
}
|
||||
|
||||
/* Clear the entire return buffer first, [Very Important!] */
|
||||
|
||||
*value = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The four types of fields are:
|
||||
*
|
||||
* buffer_field - Read/write from/to a Buffer
|
||||
* region_field - Read/write from/to a Operation Region.
|
||||
* bank_field - Write to a Bank Register, then read/write from/to an op_region
|
||||
* index_field - Write to an Index Register, then read/write from/to a Data Register
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
/*
|
||||
* If the buffer_field arguments have not been previously evaluated,
|
||||
* evaluate them now and save the results.
|
||||
*/
|
||||
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
|
||||
status = acpi_ds_get_buffer_field_arguments (obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
if (read_write == ACPI_READ) {
|
||||
/*
|
||||
* Copy the data from the source buffer.
|
||||
* Length is the field width in bytes.
|
||||
*/
|
||||
ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer
|
||||
+ obj_desc->buffer_field.base_byte_offset
|
||||
+ field_datum_byte_offset,
|
||||
obj_desc->common_field.access_byte_width);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Copy the data to the target buffer.
|
||||
* Length is the field width in bytes.
|
||||
*/
|
||||
ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer
|
||||
+ obj_desc->buffer_field.base_byte_offset
|
||||
+ field_datum_byte_offset,
|
||||
value, obj_desc->common_field.access_byte_width);
|
||||
}
|
||||
|
||||
status = AE_OK;
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
|
||||
/* Ensure that the bank_value is not beyond the capacity of the register */
|
||||
|
||||
if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj,
|
||||
(acpi_integer) obj_desc->bank_field.value)) {
|
||||
return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
|
||||
}
|
||||
|
||||
/*
|
||||
* For bank_fields, we must write the bank_value to the bank_register
|
||||
* (itself a region_field) before we can access the data.
|
||||
*/
|
||||
status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj,
|
||||
&obj_desc->bank_field.value,
|
||||
sizeof (obj_desc->bank_field.value));
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that the Bank has been selected, fall through to the
|
||||
* region_field case and write the datum to the Operation Region
|
||||
*/
|
||||
|
||||
/*lint -fallthrough */
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
/*
|
||||
* For simple region_fields, we just directly access the owning
|
||||
* Operation Region.
|
||||
*/
|
||||
status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value,
|
||||
read_write);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
|
||||
/* Ensure that the index_value is not beyond the capacity of the register */
|
||||
|
||||
if (acpi_ex_register_overflow (obj_desc->index_field.index_obj,
|
||||
(acpi_integer) obj_desc->index_field.value)) {
|
||||
return_ACPI_STATUS (AE_AML_REGISTER_LIMIT);
|
||||
}
|
||||
|
||||
/* Write the index value to the index_register (itself a region_field) */
|
||||
|
||||
field_datum_byte_offset += obj_desc->index_field.value;
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Write to Index Register: Value %8.8X\n",
|
||||
field_datum_byte_offset));
|
||||
|
||||
status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj,
|
||||
&field_datum_byte_offset,
|
||||
sizeof (field_datum_byte_offset));
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"I/O to Data Register: value_ptr %p\n",
|
||||
value));
|
||||
|
||||
if (read_write == ACPI_READ) {
|
||||
/* Read the datum from the data_register */
|
||||
|
||||
status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj,
|
||||
value, sizeof (acpi_integer));
|
||||
}
|
||||
else {
|
||||
/* Write the datum to the data_register */
|
||||
|
||||
status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj,
|
||||
value, sizeof (acpi_integer));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("Wrong object type in field I/O %X\n",
|
||||
ACPI_GET_OBJECT_TYPE (obj_desc)));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
if (read_write == ACPI_READ) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n",
|
||||
ACPI_FORMAT_UINT64 (*value),
|
||||
obj_desc->common_field.access_byte_width));
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n",
|
||||
ACPI_FORMAT_UINT64 (*value),
|
||||
obj_desc->common_field.access_byte_width));
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_write_with_update_rule
|
||||
*
|
||||
* PARAMETERS: *obj_desc - Field to be set
|
||||
* Value - Value to store
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Apply the field update rule to a field write
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_write_with_update_rule (
|
||||
union acpi_operand_object *obj_desc,
|
||||
acpi_integer mask,
|
||||
acpi_integer field_value,
|
||||
u32 field_datum_byte_offset)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
acpi_integer merged_value;
|
||||
acpi_integer current_value;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32 ("ex_write_with_update_rule", mask);
|
||||
|
||||
|
||||
/* Start with the new bits */
|
||||
|
||||
merged_value = field_value;
|
||||
|
||||
/* If the mask is all ones, we don't need to worry about the update rule */
|
||||
|
||||
if (mask != ACPI_INTEGER_MAX) {
|
||||
/* Decode the update rule */
|
||||
|
||||
switch (obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK) {
|
||||
case AML_FIELD_UPDATE_PRESERVE:
|
||||
/*
|
||||
* Check if update rule needs to be applied (not if mask is all
|
||||
* ones) The left shift drops the bits we want to ignore.
|
||||
*/
|
||||
if ((~mask << (ACPI_MUL_8 (sizeof (mask)) -
|
||||
ACPI_MUL_8 (obj_desc->common_field.access_byte_width))) != 0) {
|
||||
/*
|
||||
* Read the current contents of the byte/word/dword containing
|
||||
* the field, and merge with the new field value.
|
||||
*/
|
||||
status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
|
||||
¤t_value, ACPI_READ);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
merged_value |= (current_value & ~mask);
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_FIELD_UPDATE_WRITE_AS_ONES:
|
||||
|
||||
/* Set positions outside the field to all ones */
|
||||
|
||||
merged_value |= ~mask;
|
||||
break;
|
||||
|
||||
case AML_FIELD_UPDATE_WRITE_AS_ZEROS:
|
||||
|
||||
/* Set positions outside the field to all zeros */
|
||||
|
||||
merged_value &= mask;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"write_with_update_rule: Unknown update_rule setting: %X\n",
|
||||
(obj_desc->common_field.field_flags & AML_FIELD_UPDATE_RULE_MASK)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Mask %8.8X%8.8X, datum_offset %X, Width %X, Value %8.8X%8.8X, merged_value %8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64 (mask),
|
||||
field_datum_byte_offset,
|
||||
obj_desc->common_field.access_byte_width,
|
||||
ACPI_FORMAT_UINT64 (field_value),
|
||||
ACPI_FORMAT_UINT64 (merged_value)));
|
||||
|
||||
/* Write the merged value */
|
||||
|
||||
status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
|
||||
&merged_value, ACPI_WRITE);
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_extract_from_field
|
||||
*
|
||||
* PARAMETERS: obj_desc - Field to be read
|
||||
* Buffer - Where to store the field data
|
||||
* buffer_length - Length of Buffer
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Retrieve the current value of the given field
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_extract_from_field (
|
||||
union acpi_operand_object *obj_desc,
|
||||
void *buffer,
|
||||
u32 buffer_length)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_integer raw_datum;
|
||||
acpi_integer merged_datum;
|
||||
u32 field_offset = 0;
|
||||
u32 buffer_offset = 0;
|
||||
u32 buffer_tail_bits;
|
||||
u32 datum_count;
|
||||
u32 field_datum_count;
|
||||
u32 i;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_extract_from_field");
|
||||
|
||||
|
||||
/* Validate target buffer and clear it */
|
||||
|
||||
if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
|
||||
obj_desc->common_field.bit_length)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Field size %X (bits) is too large for buffer (%X)\n",
|
||||
obj_desc->common_field.bit_length, buffer_length));
|
||||
|
||||
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
|
||||
}
|
||||
ACPI_MEMSET (buffer, 0, buffer_length);
|
||||
|
||||
/* Compute the number of datums (access width data items) */
|
||||
|
||||
datum_count = ACPI_ROUND_UP_TO (
|
||||
obj_desc->common_field.bit_length,
|
||||
obj_desc->common_field.access_bit_width);
|
||||
field_datum_count = ACPI_ROUND_UP_TO (
|
||||
obj_desc->common_field.bit_length +
|
||||
obj_desc->common_field.start_field_bit_offset,
|
||||
obj_desc->common_field.access_bit_width);
|
||||
|
||||
/* Priming read from the field */
|
||||
|
||||
status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
|
||||
|
||||
/* Read the rest of the field */
|
||||
|
||||
for (i = 1; i < field_datum_count; i++) {
|
||||
/* Get next input datum from the field */
|
||||
|
||||
field_offset += obj_desc->common_field.access_byte_width;
|
||||
status = acpi_ex_field_datum_io (obj_desc, field_offset,
|
||||
&raw_datum, ACPI_READ);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Merge with previous datum if necessary */
|
||||
|
||||
merged_datum |= raw_datum <<
|
||||
(obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
|
||||
|
||||
if (i == datum_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write merged datum to target buffer */
|
||||
|
||||
ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
|
||||
ACPI_MIN(obj_desc->common_field.access_byte_width,
|
||||
buffer_length - buffer_offset));
|
||||
|
||||
buffer_offset += obj_desc->common_field.access_byte_width;
|
||||
merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
|
||||
}
|
||||
|
||||
/* Mask off any extra bits in the last datum */
|
||||
|
||||
buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width;
|
||||
if (buffer_tail_bits) {
|
||||
merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
|
||||
}
|
||||
|
||||
/* Write the last datum to the buffer */
|
||||
|
||||
ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
|
||||
ACPI_MIN(obj_desc->common_field.access_byte_width,
|
||||
buffer_length - buffer_offset));
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_insert_into_field
|
||||
*
|
||||
* PARAMETERS: obj_desc - Field to be written
|
||||
* Buffer - Data to be written
|
||||
* buffer_length - Length of Buffer
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Store the Buffer contents into the given field
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_insert_into_field (
|
||||
union acpi_operand_object *obj_desc,
|
||||
void *buffer,
|
||||
u32 buffer_length)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_integer mask;
|
||||
acpi_integer merged_datum;
|
||||
acpi_integer raw_datum = 0;
|
||||
u32 field_offset = 0;
|
||||
u32 buffer_offset = 0;
|
||||
u32 buffer_tail_bits;
|
||||
u32 datum_count;
|
||||
u32 field_datum_count;
|
||||
u32 i;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_insert_into_field");
|
||||
|
||||
|
||||
/* Validate input buffer */
|
||||
|
||||
if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
|
||||
obj_desc->common_field.bit_length)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Field size %X (bits) is too large for buffer (%X)\n",
|
||||
obj_desc->common_field.bit_length, buffer_length));
|
||||
|
||||
return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
|
||||
}
|
||||
|
||||
/* Compute the number of datums (access width data items) */
|
||||
|
||||
mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
|
||||
datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
|
||||
obj_desc->common_field.access_bit_width);
|
||||
field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
|
||||
obj_desc->common_field.start_field_bit_offset,
|
||||
obj_desc->common_field.access_bit_width);
|
||||
|
||||
/* Get initial Datum from the input buffer */
|
||||
|
||||
ACPI_MEMCPY (&raw_datum, buffer,
|
||||
ACPI_MIN(obj_desc->common_field.access_byte_width,
|
||||
buffer_length - buffer_offset));
|
||||
|
||||
merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
|
||||
|
||||
/* Write the entire field */
|
||||
|
||||
for (i = 1; i < field_datum_count; i++) {
|
||||
/* Write merged datum to the target field */
|
||||
|
||||
merged_datum &= mask;
|
||||
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Start new output datum by merging with previous input datum */
|
||||
|
||||
field_offset += obj_desc->common_field.access_byte_width;
|
||||
merged_datum = raw_datum >>
|
||||
(obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
|
||||
mask = ACPI_INTEGER_MAX;
|
||||
|
||||
if (i == datum_count) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get the next input datum from the buffer */
|
||||
|
||||
buffer_offset += obj_desc->common_field.access_byte_width;
|
||||
ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
|
||||
ACPI_MIN(obj_desc->common_field.access_byte_width,
|
||||
buffer_length - buffer_offset));
|
||||
merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
|
||||
}
|
||||
|
||||
/* Mask off any extra bits in the last datum */
|
||||
|
||||
buffer_tail_bits = (obj_desc->common_field.bit_length +
|
||||
obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width;
|
||||
if (buffer_tail_bits) {
|
||||
mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
|
||||
}
|
||||
|
||||
/* Write the last datum to the field */
|
||||
|
||||
merged_datum &= mask;
|
||||
status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,738 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exmisc")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_get_object_reference
|
||||
*
|
||||
* PARAMETERS: obj_desc - Create a reference to this object
|
||||
* return_desc - Where to store the reference
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Obtain and return a "reference" to the target object
|
||||
* Common code for the ref_of_op and the cond_ref_of_op.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_get_object_reference (
|
||||
union acpi_operand_object *obj_desc,
|
||||
union acpi_operand_object **return_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *reference_obj;
|
||||
union acpi_operand_object *referenced_obj;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc);
|
||||
|
||||
|
||||
*return_desc = NULL;
|
||||
|
||||
switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
|
||||
case ACPI_DESC_TYPE_OPERAND:
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be a reference to a Local or Arg
|
||||
*/
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
case AML_DEBUG_OP:
|
||||
|
||||
/* The referenced object is the pseudo-node for the local/arg */
|
||||
|
||||
referenced_obj = obj_desc->reference.object;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("Unknown Reference opcode in get_reference %X\n",
|
||||
obj_desc->reference.opcode));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_DESC_TYPE_NAMED:
|
||||
|
||||
/*
|
||||
* A named reference that has already been resolved to a Node
|
||||
*/
|
||||
referenced_obj = obj_desc;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("Invalid descriptor type in get_reference: %X\n",
|
||||
ACPI_GET_DESCRIPTOR_TYPE (obj_desc)));
|
||||
return_ACPI_STATUS (AE_TYPE);
|
||||
}
|
||||
|
||||
|
||||
/* Create a new reference object */
|
||||
|
||||
reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
|
||||
if (!reference_obj) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
reference_obj->reference.opcode = AML_REF_OF_OP;
|
||||
reference_obj->reference.object = referenced_obj;
|
||||
*return_desc = reference_obj;
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n",
|
||||
obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_concat_template
|
||||
*
|
||||
* PARAMETERS: Operand0 - First source object
|
||||
* Operand1 - Second source object
|
||||
* actual_return_desc - Where to place the return object
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Concatenate two resource templates
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_concat_template (
|
||||
union acpi_operand_object *operand0,
|
||||
union acpi_operand_object *operand1,
|
||||
union acpi_operand_object **actual_return_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *return_desc;
|
||||
u8 *new_buf;
|
||||
u8 *end_tag1;
|
||||
u8 *end_tag2;
|
||||
acpi_size length1;
|
||||
acpi_size length2;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_concat_template");
|
||||
|
||||
|
||||
/* Find the end_tags in each resource template */
|
||||
|
||||
end_tag1 = acpi_ut_get_resource_end_tag (operand0);
|
||||
end_tag2 = acpi_ut_get_resource_end_tag (operand1);
|
||||
if (!end_tag1 || !end_tag2) {
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Compute the length of each part */
|
||||
|
||||
length1 = ACPI_PTR_DIFF (end_tag1, operand0->buffer.pointer);
|
||||
length2 = ACPI_PTR_DIFF (end_tag2, operand1->buffer.pointer) +
|
||||
2; /* Size of END_TAG */
|
||||
|
||||
/* Create a new buffer object for the result */
|
||||
|
||||
return_desc = acpi_ut_create_buffer_object (length1 + length2);
|
||||
if (!return_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Copy the templates to the new descriptor */
|
||||
|
||||
new_buf = return_desc->buffer.pointer;
|
||||
ACPI_MEMCPY (new_buf, operand0->buffer.pointer, length1);
|
||||
ACPI_MEMCPY (new_buf + length1, operand1->buffer.pointer, length2);
|
||||
|
||||
/* Compute the new checksum */
|
||||
|
||||
new_buf[return_desc->buffer.length - 1] =
|
||||
acpi_ut_generate_checksum (return_desc->buffer.pointer,
|
||||
(return_desc->buffer.length - 1));
|
||||
|
||||
/* Return the completed template descriptor */
|
||||
|
||||
*actual_return_desc = return_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_do_concatenate
|
||||
*
|
||||
* PARAMETERS: Operand0 - First source object
|
||||
* Operand1 - Second source object
|
||||
* actual_return_desc - Where to place the return object
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_do_concatenate (
|
||||
union acpi_operand_object *operand0,
|
||||
union acpi_operand_object *operand1,
|
||||
union acpi_operand_object **actual_return_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *local_operand1 = operand1;
|
||||
union acpi_operand_object *return_desc;
|
||||
char *new_buf;
|
||||
acpi_status status;
|
||||
acpi_size new_length;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_do_concatenate");
|
||||
|
||||
|
||||
/*
|
||||
* Convert the second operand if necessary. The first operand
|
||||
* determines the type of the second operand, (See the Data Types
|
||||
* section of the ACPI specification.) Both object types are
|
||||
* guaranteed to be either Integer/String/Buffer by the operand
|
||||
* resolution mechanism.
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (operand0)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
status = acpi_ex_convert_to_string (operand1, &local_operand1,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
|
||||
ACPI_GET_OBJECT_TYPE (operand0)));
|
||||
status = AE_AML_INTERNAL;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Both operands are now known to be the same object type
|
||||
* (Both are Integer, String, or Buffer), and we can now perform the
|
||||
* concatenation.
|
||||
*/
|
||||
|
||||
/*
|
||||
* There are three cases to handle:
|
||||
*
|
||||
* 1) Two Integers concatenated to produce a new Buffer
|
||||
* 2) Two Strings concatenated to produce a new String
|
||||
* 3) Two Buffers concatenated to produce a new Buffer
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (operand0)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* Result of two Integers is a Buffer */
|
||||
/* Need enough buffer space for two integers */
|
||||
|
||||
return_desc = acpi_ut_create_buffer_object (
|
||||
ACPI_MUL_2 (acpi_gbl_integer_byte_width));
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
new_buf = (char *) return_desc->buffer.pointer;
|
||||
|
||||
/* Copy the first integer, LSB first */
|
||||
|
||||
ACPI_MEMCPY (new_buf,
|
||||
&operand0->integer.value,
|
||||
acpi_gbl_integer_byte_width);
|
||||
|
||||
/* Copy the second integer (LSB first) after the first */
|
||||
|
||||
ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width,
|
||||
&local_operand1->integer.value,
|
||||
acpi_gbl_integer_byte_width);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* Result of two Strings is a String */
|
||||
|
||||
new_length = (acpi_size) operand0->string.length +
|
||||
(acpi_size) local_operand1->string.length;
|
||||
if (new_length > ACPI_MAX_STRING_CONVERSION) {
|
||||
status = AE_AML_STRING_LIMIT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc = acpi_ut_create_string_object (new_length);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
new_buf = return_desc->string.pointer;
|
||||
|
||||
/* Concatenate the strings */
|
||||
|
||||
ACPI_STRCPY (new_buf,
|
||||
operand0->string.pointer);
|
||||
ACPI_STRCPY (new_buf + operand0->string.length,
|
||||
local_operand1->string.pointer);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Result of two Buffers is a Buffer */
|
||||
|
||||
return_desc = acpi_ut_create_buffer_object (
|
||||
(acpi_size) operand0->buffer.length +
|
||||
(acpi_size) local_operand1->buffer.length);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
new_buf = (char *) return_desc->buffer.pointer;
|
||||
|
||||
/* Concatenate the buffers */
|
||||
|
||||
ACPI_MEMCPY (new_buf,
|
||||
operand0->buffer.pointer,
|
||||
operand0->buffer.length);
|
||||
ACPI_MEMCPY (new_buf + operand0->buffer.length,
|
||||
local_operand1->buffer.pointer,
|
||||
local_operand1->buffer.length);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Invalid object type, should not happen here */
|
||||
|
||||
ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
|
||||
ACPI_GET_OBJECT_TYPE (operand0)));
|
||||
status =AE_AML_INTERNAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*actual_return_desc = return_desc;
|
||||
|
||||
cleanup:
|
||||
if (local_operand1 != operand1) {
|
||||
acpi_ut_remove_reference (local_operand1);
|
||||
}
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_do_math_op
|
||||
*
|
||||
* PARAMETERS: Opcode - AML opcode
|
||||
* Integer0 - Integer operand #0
|
||||
* Integer1 - Integer operand #1
|
||||
*
|
||||
* RETURN: Integer result of the operation
|
||||
*
|
||||
* DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
|
||||
* math functions here is to prevent a lot of pointer dereferencing
|
||||
* to obtain the operands.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_integer
|
||||
acpi_ex_do_math_op (
|
||||
u16 opcode,
|
||||
acpi_integer integer0,
|
||||
acpi_integer integer1)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case AML_ADD_OP: /* Add (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 + integer1);
|
||||
|
||||
|
||||
case AML_BIT_AND_OP: /* And (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 & integer1);
|
||||
|
||||
|
||||
case AML_BIT_NAND_OP: /* NAnd (Integer0, Integer1, Result) */
|
||||
|
||||
return (~(integer0 & integer1));
|
||||
|
||||
|
||||
case AML_BIT_OR_OP: /* Or (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 | integer1);
|
||||
|
||||
|
||||
case AML_BIT_NOR_OP: /* NOr (Integer0, Integer1, Result) */
|
||||
|
||||
return (~(integer0 | integer1));
|
||||
|
||||
|
||||
case AML_BIT_XOR_OP: /* XOr (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 ^ integer1);
|
||||
|
||||
|
||||
case AML_MULTIPLY_OP: /* Multiply (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 * integer1);
|
||||
|
||||
|
||||
case AML_SHIFT_LEFT_OP: /* shift_left (Operand, shift_count, Result) */
|
||||
|
||||
return (integer0 << integer1);
|
||||
|
||||
|
||||
case AML_SHIFT_RIGHT_OP: /* shift_right (Operand, shift_count, Result) */
|
||||
|
||||
return (integer0 >> integer1);
|
||||
|
||||
|
||||
case AML_SUBTRACT_OP: /* Subtract (Integer0, Integer1, Result) */
|
||||
|
||||
return (integer0 - integer1);
|
||||
|
||||
default:
|
||||
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_do_logical_numeric_op
|
||||
*
|
||||
* PARAMETERS: Opcode - AML opcode
|
||||
* Integer0 - Integer operand #0
|
||||
* Integer1 - Integer operand #1
|
||||
* logical_result - TRUE/FALSE result of the operation
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute a logical "Numeric" AML opcode. For these Numeric
|
||||
* operators (LAnd and LOr), both operands must be integers.
|
||||
*
|
||||
* Note: cleanest machine code seems to be produced by the code
|
||||
* below, rather than using statements of the form:
|
||||
* Result = (Integer0 && Integer1);
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_do_logical_numeric_op (
|
||||
u16 opcode,
|
||||
acpi_integer integer0,
|
||||
acpi_integer integer1,
|
||||
u8 *logical_result)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u8 local_result = FALSE;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_do_logical_numeric_op");
|
||||
|
||||
|
||||
switch (opcode) {
|
||||
case AML_LAND_OP: /* LAnd (Integer0, Integer1) */
|
||||
|
||||
if (integer0 && integer1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_LOR_OP: /* LOr (Integer0, Integer1) */
|
||||
|
||||
if (integer0 || integer1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return the logical result and status */
|
||||
|
||||
*logical_result = local_result;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_do_logical_op
|
||||
*
|
||||
* PARAMETERS: Opcode - AML opcode
|
||||
* Operand0 - operand #0
|
||||
* Operand1 - operand #1
|
||||
* logical_result - TRUE/FALSE result of the operation
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
|
||||
* functions here is to prevent a lot of pointer dereferencing
|
||||
* to obtain the operands and to simplify the generation of the
|
||||
* logical value. For the Numeric operators (LAnd and LOr), both
|
||||
* operands must be integers. For the other logical operators,
|
||||
* operands can be any combination of Integer/String/Buffer. The
|
||||
* first operand determines the type to which the second operand
|
||||
* will be converted.
|
||||
*
|
||||
* Note: cleanest machine code seems to be produced by the code
|
||||
* below, rather than using statements of the form:
|
||||
* Result = (Operand0 == Operand1);
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_do_logical_op (
|
||||
u16 opcode,
|
||||
union acpi_operand_object *operand0,
|
||||
union acpi_operand_object *operand1,
|
||||
u8 *logical_result)
|
||||
{
|
||||
union acpi_operand_object *local_operand1 = operand1;
|
||||
acpi_integer integer0;
|
||||
acpi_integer integer1;
|
||||
u32 length0;
|
||||
u32 length1;
|
||||
acpi_status status = AE_OK;
|
||||
u8 local_result = FALSE;
|
||||
int compare;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_do_logical_op");
|
||||
|
||||
|
||||
/*
|
||||
* Convert the second operand if necessary. The first operand
|
||||
* determines the type of the second operand, (See the Data Types
|
||||
* section of the ACPI 3.0+ specification.) Both object types are
|
||||
* guaranteed to be either Integer/String/Buffer by the operand
|
||||
* resolution mechanism.
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (operand0)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
status = acpi_ex_convert_to_string (operand1, &local_operand1,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Two cases: 1) Both Integers, 2) Both Strings or Buffers
|
||||
*/
|
||||
if (ACPI_GET_OBJECT_TYPE (operand0) == ACPI_TYPE_INTEGER) {
|
||||
/*
|
||||
* 1) Both operands are of type integer
|
||||
* Note: local_operand1 may have changed above
|
||||
*/
|
||||
integer0 = operand0->integer.value;
|
||||
integer1 = local_operand1->integer.value;
|
||||
|
||||
switch (opcode) {
|
||||
case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
|
||||
|
||||
if (integer0 == integer1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
|
||||
|
||||
if (integer0 > integer1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
|
||||
|
||||
if (integer0 < integer1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* 2) Both operands are Strings or both are Buffers
|
||||
* Note: Code below takes advantage of common Buffer/String
|
||||
* object fields. local_operand1 may have changed above. Use
|
||||
* memcmp to handle nulls in buffers.
|
||||
*/
|
||||
length0 = operand0->buffer.length;
|
||||
length1 = local_operand1->buffer.length;
|
||||
|
||||
/* Lexicographic compare: compare the data bytes */
|
||||
|
||||
compare = ACPI_MEMCMP ((const char * ) operand0->buffer.pointer,
|
||||
(const char * ) local_operand1->buffer.pointer,
|
||||
(length0 > length1) ? length1 : length0);
|
||||
|
||||
switch (opcode) {
|
||||
case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
|
||||
|
||||
/* Length and all bytes must be equal */
|
||||
|
||||
if ((length0 == length1) &&
|
||||
(compare == 0)) {
|
||||
/* Length and all bytes match ==> TRUE */
|
||||
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
|
||||
|
||||
if (compare > 0) {
|
||||
local_result = TRUE;
|
||||
goto cleanup; /* TRUE */
|
||||
}
|
||||
if (compare < 0) {
|
||||
goto cleanup; /* FALSE */
|
||||
}
|
||||
|
||||
/* Bytes match (to shortest length), compare lengths */
|
||||
|
||||
if (length0 > length1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
|
||||
|
||||
if (compare > 0) {
|
||||
goto cleanup; /* FALSE */
|
||||
}
|
||||
if (compare < 0) {
|
||||
local_result = TRUE;
|
||||
goto cleanup; /* TRUE */
|
||||
}
|
||||
|
||||
/* Bytes match (to shortest length), compare lengths */
|
||||
|
||||
if (length0 < length1) {
|
||||
local_result = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
/* New object was created if implicit conversion performed - delete */
|
||||
|
||||
if (local_operand1 != operand1) {
|
||||
acpi_ut_remove_reference (local_operand1);
|
||||
}
|
||||
|
||||
/* Return the logical result and status */
|
||||
|
||||
*logical_result = local_result;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,363 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exmutex - ASL Mutex Acquire/Release functions
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exmutex")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_unlink_mutex
|
||||
*
|
||||
* PARAMETERS: obj_desc - The mutex to be unlinked
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Remove a mutex from the "acquired_mutex" list
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_unlink_mutex (
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
struct acpi_thread_state *thread = obj_desc->mutex.owner_thread;
|
||||
|
||||
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Doubly linked list */
|
||||
|
||||
if (obj_desc->mutex.next) {
|
||||
(obj_desc->mutex.next)->mutex.prev = obj_desc->mutex.prev;
|
||||
}
|
||||
|
||||
if (obj_desc->mutex.prev) {
|
||||
(obj_desc->mutex.prev)->mutex.next = obj_desc->mutex.next;
|
||||
}
|
||||
else {
|
||||
thread->acquired_mutex_list = obj_desc->mutex.next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_link_mutex
|
||||
*
|
||||
* PARAMETERS: obj_desc - The mutex to be linked
|
||||
* list_head - head of the "acquired_mutex" list
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Add a mutex to the "acquired_mutex" list for this walk
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_link_mutex (
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_thread_state *thread)
|
||||
{
|
||||
union acpi_operand_object *list_head;
|
||||
|
||||
|
||||
list_head = thread->acquired_mutex_list;
|
||||
|
||||
/* This object will be the first object in the list */
|
||||
|
||||
obj_desc->mutex.prev = NULL;
|
||||
obj_desc->mutex.next = list_head;
|
||||
|
||||
/* Update old first object to point back to this object */
|
||||
|
||||
if (list_head) {
|
||||
list_head->mutex.prev = obj_desc;
|
||||
}
|
||||
|
||||
/* Update list head */
|
||||
|
||||
thread->acquired_mutex_list = obj_desc;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_acquire_mutex
|
||||
*
|
||||
* PARAMETERS: time_desc - The 'time to delay' object descriptor
|
||||
* obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Acquire an AML mutex
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_acquire_mutex (
|
||||
union acpi_operand_object *time_desc,
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_acquire_mutex", obj_desc);
|
||||
|
||||
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Sanity check -- we must have a valid thread ID */
|
||||
|
||||
if (!walk_state->thread) {
|
||||
ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], null thread info\n",
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node)));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current Sync must be less than or equal to the sync level of the
|
||||
* mutex. This mechanism provides some deadlock prevention
|
||||
*/
|
||||
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
|
||||
ACPI_REPORT_ERROR (("Cannot acquire Mutex [%4.4s], incorrect sync_level\n",
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node)));
|
||||
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
|
||||
}
|
||||
|
||||
/* Support for multiple acquires by the owning thread */
|
||||
|
||||
if (obj_desc->mutex.owner_thread) {
|
||||
/* Special case for Global Lock, allow all threads */
|
||||
|
||||
if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) ||
|
||||
(obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) {
|
||||
/*
|
||||
* The mutex is already owned by this thread,
|
||||
* just increment the acquisition depth
|
||||
*/
|
||||
obj_desc->mutex.acquisition_depth++;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Acquire the mutex, wait if necessary */
|
||||
|
||||
status = acpi_ex_system_acquire_mutex (time_desc, obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
/* Includes failure from a timeout on time_desc */
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Have the mutex: update mutex and walk info and save the sync_level */
|
||||
|
||||
obj_desc->mutex.owner_thread = walk_state->thread;
|
||||
obj_desc->mutex.acquisition_depth = 1;
|
||||
obj_desc->mutex.original_sync_level = walk_state->thread->current_sync_level;
|
||||
|
||||
walk_state->thread->current_sync_level = obj_desc->mutex.sync_level;
|
||||
|
||||
/* Link the mutex to the current thread for force-unlock at method exit */
|
||||
|
||||
acpi_ex_link_mutex (obj_desc, walk_state->thread);
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_release_mutex
|
||||
*
|
||||
* PARAMETERS: obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Release a previously acquired Mutex.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_release_mutex (
|
||||
union acpi_operand_object *obj_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_release_mutex");
|
||||
|
||||
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* The mutex must have been previously acquired in order to release it */
|
||||
|
||||
if (!obj_desc->mutex.owner_thread) {
|
||||
ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], not acquired\n",
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node)));
|
||||
return_ACPI_STATUS (AE_AML_MUTEX_NOT_ACQUIRED);
|
||||
}
|
||||
|
||||
/* Sanity check -- we must have a valid thread ID */
|
||||
|
||||
if (!walk_state->thread) {
|
||||
ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], null thread info\n",
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node)));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Mutex is owned, but this thread must be the owner.
|
||||
* Special case for Global Lock, any thread can release
|
||||
*/
|
||||
if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
|
||||
(obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
|
||||
ACPI_REPORT_ERROR ((
|
||||
"Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
|
||||
walk_state->thread->thread_id,
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node),
|
||||
obj_desc->mutex.owner_thread->thread_id));
|
||||
return_ACPI_STATUS (AE_AML_NOT_OWNER);
|
||||
}
|
||||
|
||||
/*
|
||||
* The sync level of the mutex must be less than or
|
||||
* equal to the current sync level
|
||||
*/
|
||||
if (obj_desc->mutex.sync_level > walk_state->thread->current_sync_level) {
|
||||
ACPI_REPORT_ERROR (("Cannot release Mutex [%4.4s], incorrect sync_level\n",
|
||||
acpi_ut_get_node_name (obj_desc->mutex.node)));
|
||||
return_ACPI_STATUS (AE_AML_MUTEX_ORDER);
|
||||
}
|
||||
|
||||
/* Match multiple Acquires with multiple Releases */
|
||||
|
||||
obj_desc->mutex.acquisition_depth--;
|
||||
if (obj_desc->mutex.acquisition_depth != 0) {
|
||||
/* Just decrement the depth and return */
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
/* Unlink the mutex from the owner's list */
|
||||
|
||||
acpi_ex_unlink_mutex (obj_desc);
|
||||
|
||||
/* Release the mutex */
|
||||
|
||||
status = acpi_ex_system_release_mutex (obj_desc);
|
||||
|
||||
/* Update the mutex and walk state, restore sync_level before acquire */
|
||||
|
||||
obj_desc->mutex.owner_thread = NULL;
|
||||
walk_state->thread->current_sync_level = obj_desc->mutex.original_sync_level;
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_release_all_mutexes
|
||||
*
|
||||
* PARAMETERS: mutex_list - Head of the mutex list
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Release all mutexes in the list
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_release_all_mutexes (
|
||||
struct acpi_thread_state *thread)
|
||||
{
|
||||
union acpi_operand_object *next = thread->acquired_mutex_list;
|
||||
union acpi_operand_object *this;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/* Traverse the list of owned mutexes, releasing each one */
|
||||
|
||||
while (next) {
|
||||
this = next;
|
||||
next = this->mutex.next;
|
||||
|
||||
this->mutex.acquisition_depth = 1;
|
||||
this->mutex.prev = NULL;
|
||||
this->mutex.next = NULL;
|
||||
|
||||
/* Release the mutex */
|
||||
|
||||
status = acpi_ex_system_release_mutex (this);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Mark mutex unowned */
|
||||
|
||||
this->mutex.owner_thread = NULL;
|
||||
|
||||
/* Update Thread sync_level (Last mutex is the important one) */
|
||||
|
||||
thread->current_sync_level = this->mutex.original_sync_level;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,427 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exnames - interpreter/scanner name load/execute
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exnames")
|
||||
|
||||
|
||||
/* AML Package Length encodings */
|
||||
|
||||
#define ACPI_AML_PACKAGE_TYPE1 0x40
|
||||
#define ACPI_AML_PACKAGE_TYPE2 0x4000
|
||||
#define ACPI_AML_PACKAGE_TYPE3 0x400000
|
||||
#define ACPI_AML_PACKAGE_TYPE4 0x40000000
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_allocate_name_string
|
||||
*
|
||||
* PARAMETERS: prefix_count - Count of parent levels. Special cases:
|
||||
* (-1) = root, 0 = none
|
||||
* num_name_segs - count of 4-character name segments
|
||||
*
|
||||
* RETURN: A pointer to the allocated string segment. This segment must
|
||||
* be deleted by the caller.
|
||||
*
|
||||
* DESCRIPTION: Allocate a buffer for a name string. Ensure allocated name
|
||||
* string is long enough, and set up prefix if any.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
char *
|
||||
acpi_ex_allocate_name_string (
|
||||
u32 prefix_count,
|
||||
u32 num_name_segs)
|
||||
{
|
||||
char *temp_ptr;
|
||||
char *name_string;
|
||||
u32 size_needed;
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_allocate_name_string");
|
||||
|
||||
|
||||
/*
|
||||
* Allow room for all \ and ^ prefixes, all segments, and a multi_name_prefix.
|
||||
* Also, one byte for the null terminator.
|
||||
* This may actually be somewhat longer than needed.
|
||||
*/
|
||||
if (prefix_count == ACPI_UINT32_MAX) {
|
||||
/* Special case for root */
|
||||
|
||||
size_needed = 1 + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
|
||||
}
|
||||
else {
|
||||
size_needed = prefix_count + (ACPI_NAME_SIZE * num_name_segs) + 2 + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a buffer for the name.
|
||||
* This buffer must be deleted by the caller!
|
||||
*/
|
||||
name_string = ACPI_MEM_ALLOCATE (size_needed);
|
||||
if (!name_string) {
|
||||
ACPI_REPORT_ERROR (("ex_allocate_name_string: Could not allocate size %d\n", size_needed));
|
||||
return_PTR (NULL);
|
||||
}
|
||||
|
||||
temp_ptr = name_string;
|
||||
|
||||
/* Set up Root or Parent prefixes if needed */
|
||||
|
||||
if (prefix_count == ACPI_UINT32_MAX) {
|
||||
*temp_ptr++ = AML_ROOT_PREFIX;
|
||||
}
|
||||
else {
|
||||
while (prefix_count--) {
|
||||
*temp_ptr++ = AML_PARENT_PREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set up Dual or Multi prefixes if needed */
|
||||
|
||||
if (num_name_segs > 2) {
|
||||
/* Set up multi prefixes */
|
||||
|
||||
*temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
|
||||
*temp_ptr++ = (char) num_name_segs;
|
||||
}
|
||||
else if (2 == num_name_segs) {
|
||||
/* Set up dual prefixes */
|
||||
|
||||
*temp_ptr++ = AML_DUAL_NAME_PREFIX;
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate string following prefixes. acpi_ex_name_segment() will
|
||||
* append the segment(s)
|
||||
*/
|
||||
*temp_ptr = 0;
|
||||
|
||||
return_PTR (name_string);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_name_segment
|
||||
*
|
||||
* PARAMETERS: interpreter_mode - Current running mode (load1/Load2/Exec)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute a name segment (4 bytes)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_name_segment (
|
||||
u8 **in_aml_address,
|
||||
char *name_string)
|
||||
{
|
||||
char *aml_address = (void *) *in_aml_address;
|
||||
acpi_status status = AE_OK;
|
||||
u32 index;
|
||||
char char_buf[5];
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_name_segment");
|
||||
|
||||
|
||||
/*
|
||||
* If first character is a digit, then we know that we aren't looking at a
|
||||
* valid name segment
|
||||
*/
|
||||
char_buf[0] = *aml_address;
|
||||
|
||||
if ('0' <= char_buf[0] && char_buf[0] <= '9') {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "leading digit: %c\n", char_buf[0]));
|
||||
return_ACPI_STATUS (AE_CTRL_PENDING);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Bytes from stream:\n"));
|
||||
|
||||
for (index = 0;
|
||||
(index < ACPI_NAME_SIZE) && (acpi_ut_valid_acpi_character (*aml_address));
|
||||
index++) {
|
||||
char_buf[index] = *aml_address++;
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "%c\n", char_buf[index]));
|
||||
}
|
||||
|
||||
|
||||
/* Valid name segment */
|
||||
|
||||
if (index == 4) {
|
||||
/* Found 4 valid characters */
|
||||
|
||||
char_buf[4] = '\0';
|
||||
|
||||
if (name_string) {
|
||||
ACPI_STRCAT (name_string, char_buf);
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
|
||||
"Appended to - %s \n", name_string));
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
|
||||
"No Name string - %s \n", char_buf));
|
||||
}
|
||||
}
|
||||
else if (index == 0) {
|
||||
/*
|
||||
* First character was not a valid name character,
|
||||
* so we are looking at something other than a name.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"Leading character is not alpha: %02Xh (not a name)\n",
|
||||
char_buf[0]));
|
||||
status = AE_CTRL_PENDING;
|
||||
}
|
||||
else {
|
||||
/* Segment started with one or more valid characters, but fewer than 4 */
|
||||
|
||||
status = AE_AML_BAD_NAME;
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad character %02x in name, at %p\n",
|
||||
*aml_address, aml_address));
|
||||
}
|
||||
|
||||
*in_aml_address = (u8 *) aml_address;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_get_name_string
|
||||
*
|
||||
* PARAMETERS: data_type - Data type to be associated with this name
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Get a name, including any prefixes.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_get_name_string (
|
||||
acpi_object_type data_type,
|
||||
u8 *in_aml_address,
|
||||
char **out_name_string,
|
||||
u32 *out_name_length)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u8 *aml_address = in_aml_address;
|
||||
char *name_string = NULL;
|
||||
u32 num_segments;
|
||||
u32 prefix_count = 0;
|
||||
u8 has_prefix = FALSE;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_get_name_string", aml_address);
|
||||
|
||||
|
||||
if (ACPI_TYPE_LOCAL_REGION_FIELD == data_type ||
|
||||
ACPI_TYPE_LOCAL_BANK_FIELD == data_type ||
|
||||
ACPI_TYPE_LOCAL_INDEX_FIELD == data_type) {
|
||||
/* Disallow prefixes for types associated with field_unit names */
|
||||
|
||||
name_string = acpi_ex_allocate_name_string (0, 1);
|
||||
if (!name_string) {
|
||||
status = AE_NO_MEMORY;
|
||||
}
|
||||
else {
|
||||
status = acpi_ex_name_segment (&aml_address, name_string);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* data_type is not a field name.
|
||||
* Examine first character of name for root or parent prefix operators
|
||||
*/
|
||||
switch (*aml_address) {
|
||||
case AML_ROOT_PREFIX:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "root_prefix(\\) at %p\n", aml_address));
|
||||
|
||||
/*
|
||||
* Remember that we have a root_prefix --
|
||||
* see comment in acpi_ex_allocate_name_string()
|
||||
*/
|
||||
aml_address++;
|
||||
prefix_count = ACPI_UINT32_MAX;
|
||||
has_prefix = TRUE;
|
||||
break;
|
||||
|
||||
|
||||
case AML_PARENT_PREFIX:
|
||||
|
||||
/* Increment past possibly multiple parent prefixes */
|
||||
|
||||
do {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "parent_prefix (^) at %p\n", aml_address));
|
||||
|
||||
aml_address++;
|
||||
prefix_count++;
|
||||
|
||||
} while (*aml_address == AML_PARENT_PREFIX);
|
||||
|
||||
has_prefix = TRUE;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Not a prefix character */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* Examine first character of name for name segment prefix operator */
|
||||
|
||||
switch (*aml_address) {
|
||||
case AML_DUAL_NAME_PREFIX:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "dual_name_prefix at %p\n", aml_address));
|
||||
|
||||
aml_address++;
|
||||
name_string = acpi_ex_allocate_name_string (prefix_count, 2);
|
||||
if (!name_string) {
|
||||
status = AE_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Indicate that we processed a prefix */
|
||||
|
||||
has_prefix = TRUE;
|
||||
|
||||
status = acpi_ex_name_segment (&aml_address, name_string);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
status = acpi_ex_name_segment (&aml_address, name_string);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_MULTI_NAME_PREFIX_OP:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "multi_name_prefix at %p\n", aml_address));
|
||||
|
||||
/* Fetch count of segments remaining in name path */
|
||||
|
||||
aml_address++;
|
||||
num_segments = *aml_address;
|
||||
|
||||
name_string = acpi_ex_allocate_name_string (prefix_count, num_segments);
|
||||
if (!name_string) {
|
||||
status = AE_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Indicate that we processed a prefix */
|
||||
|
||||
aml_address++;
|
||||
has_prefix = TRUE;
|
||||
|
||||
while (num_segments &&
|
||||
(status = acpi_ex_name_segment (&aml_address, name_string)) == AE_OK) {
|
||||
num_segments--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 0:
|
||||
|
||||
/* null_name valid as of 8-12-98 ASL/AML Grammar Update */
|
||||
|
||||
if (prefix_count == ACPI_UINT32_MAX) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "name_seg is \"\\\" followed by NULL\n"));
|
||||
}
|
||||
|
||||
/* Consume the NULL byte */
|
||||
|
||||
aml_address++;
|
||||
name_string = acpi_ex_allocate_name_string (prefix_count, 0);
|
||||
if (!name_string) {
|
||||
status = AE_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Name segment string */
|
||||
|
||||
name_string = acpi_ex_allocate_name_string (prefix_count, 1);
|
||||
if (!name_string) {
|
||||
status = AE_NO_MEMORY;
|
||||
break;
|
||||
}
|
||||
|
||||
status = acpi_ex_name_segment (&aml_address, name_string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AE_CTRL_PENDING == status && has_prefix) {
|
||||
/* Ran out of segments after processing a prefix */
|
||||
|
||||
ACPI_REPORT_ERROR (
|
||||
("ex_do_name: Malformed Name at %p\n", name_string));
|
||||
status = AE_AML_BAD_NAME;
|
||||
}
|
||||
|
||||
*out_name_string = name_string;
|
||||
*out_name_length = (u32) (aml_address - in_aml_address);
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,608 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exoparg2 - AML execution - opcodes with 2 arguments
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acevents.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exoparg2")
|
||||
|
||||
|
||||
/*!
|
||||
* Naming convention for AML interpreter execution routines.
|
||||
*
|
||||
* The routines that begin execution of AML opcodes are named with a common
|
||||
* convention based upon the number of arguments, the number of target operands,
|
||||
* and whether or not a value is returned:
|
||||
*
|
||||
* AcpiExOpcode_xA_yT_zR
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* xA - ARGUMENTS: The number of arguments (input operands) that are
|
||||
* required for this opcode type (1 through 6 args).
|
||||
* yT - TARGETS: The number of targets (output operands) that are required
|
||||
* for this opcode type (0, 1, or 2 targets).
|
||||
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
|
||||
* as the function return (0 or 1).
|
||||
*
|
||||
* The AcpiExOpcode* functions are called via the Dispatcher component with
|
||||
* fully resolved operands.
|
||||
!*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_2A_0T_0R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute opcode with two arguments, no target, and no return
|
||||
* value.
|
||||
*
|
||||
* ALLOCATION: Deletes both operands
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_2A_0T_0R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
struct acpi_namespace_node *node;
|
||||
u32 value;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
|
||||
acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
/* Examine the opcode */
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_NOTIFY_OP: /* Notify (notify_object, notify_value) */
|
||||
|
||||
/* The first operand is a namespace node */
|
||||
|
||||
node = (struct acpi_namespace_node *) operand[0];
|
||||
|
||||
/* Second value is the notify value */
|
||||
|
||||
value = (u32) operand[1]->integer.value;
|
||||
|
||||
/* Notifies allowed on this object? */
|
||||
|
||||
if (!acpi_ev_is_notify_object (node)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Unexpected notify object type [%s]\n",
|
||||
acpi_ut_get_type_name (node->type)));
|
||||
|
||||
status = AE_AML_OPERAND_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ACPI_GPE_NOTIFY_CHECK
|
||||
/*
|
||||
* GPE method wake/notify check. Here, we want to ensure that we
|
||||
* don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
|
||||
* GPE method during system runtime. If we do, the GPE is marked
|
||||
* as "wake-only" and disabled.
|
||||
*
|
||||
* 1) Is the Notify() value == device_wake?
|
||||
* 2) Is this a GPE deferred method? (An _Lxx or _Exx method)
|
||||
* 3) Did the original GPE happen at system runtime?
|
||||
* (versus during wake)
|
||||
*
|
||||
* If all three cases are true, this is a wake-only GPE that should
|
||||
* be disabled at runtime.
|
||||
*/
|
||||
if (value == 2) /* device_wake */ {
|
||||
status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
/* AE_WAKE_ONLY_GPE only error, means ignore this notify */
|
||||
|
||||
return_ACPI_STATUS (AE_OK)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Dispatch the notify to the appropriate handler
|
||||
* NOTE: the request is queued for execution after this method
|
||||
* completes. The notify handlers are NOT invoked synchronously
|
||||
* from this thread -- because handlers may in turn run other
|
||||
* control methods.
|
||||
*/
|
||||
status = acpi_ev_queue_notify_request (node, value);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_2A_2T_1R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
|
||||
* and one implicit return value.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_2A_2T_1R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *return_desc1 = NULL;
|
||||
union acpi_operand_object *return_desc2 = NULL;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R",
|
||||
acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
/*
|
||||
* Execute the opcode
|
||||
*/
|
||||
switch (walk_state->opcode) {
|
||||
case AML_DIVIDE_OP: /* Divide (Dividend, Divisor, remainder_result quotient_result) */
|
||||
|
||||
return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc1) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc2) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Quotient to return_desc1, remainder to return_desc2 */
|
||||
|
||||
status = acpi_ut_divide (operand[0]->integer.value,
|
||||
operand[1]->integer.value,
|
||||
&return_desc1->integer.value,
|
||||
&return_desc2->integer.value);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
/* Store the results to the target reference operands */
|
||||
|
||||
status = acpi_ex_store (return_desc2, operand[2], walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
status = acpi_ex_store (return_desc1, operand[3], walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Return the remainder */
|
||||
|
||||
walk_state->result_obj = return_desc1;
|
||||
|
||||
|
||||
cleanup:
|
||||
/*
|
||||
* Since the remainder is not returned indirectly, remove a reference to
|
||||
* it. Only the quotient is returned indirectly.
|
||||
*/
|
||||
acpi_ut_remove_reference (return_desc2);
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
/* Delete the return object */
|
||||
|
||||
acpi_ut_remove_reference (return_desc1);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_2A_1T_1R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute opcode with two arguments, one target, and a return
|
||||
* value.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_2A_1T_1R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *return_desc = NULL;
|
||||
u32 index;
|
||||
acpi_status status = AE_OK;
|
||||
acpi_size length;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R",
|
||||
acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
/*
|
||||
* Execute the opcode
|
||||
*/
|
||||
if (walk_state->op_info->flags & AML_MATH) {
|
||||
/* All simple math opcodes (add, etc.) */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
|
||||
operand[0]->integer.value,
|
||||
operand[1]->integer.value);
|
||||
goto store_result_to_target;
|
||||
}
|
||||
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* return_desc will contain the remainder */
|
||||
|
||||
status = acpi_ut_divide (operand[0]->integer.value,
|
||||
operand[1]->integer.value,
|
||||
NULL,
|
||||
&return_desc->integer.value);
|
||||
break;
|
||||
|
||||
|
||||
case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
|
||||
|
||||
status = acpi_ex_do_concatenate (operand[0], operand[1],
|
||||
&return_desc, walk_state);
|
||||
break;
|
||||
|
||||
|
||||
case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
|
||||
|
||||
/*
|
||||
* Input object is guaranteed to be a buffer at this point (it may have
|
||||
* been converted.) Copy the raw buffer data to a new object of type String.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get the length of the new string. It is the smallest of:
|
||||
* 1) Length of the input buffer
|
||||
* 2) Max length as specified in the to_string operator
|
||||
* 3) Length of input buffer up to a zero byte (null terminator)
|
||||
*
|
||||
* NOTE: A length of zero is ok, and will create a zero-length, null
|
||||
* terminated string.
|
||||
*/
|
||||
length = 0;
|
||||
while ((length < operand[0]->buffer.length) &&
|
||||
(length < operand[1]->integer.value) &&
|
||||
(operand[0]->buffer.pointer[length])) {
|
||||
length++;
|
||||
if (length > ACPI_MAX_STRING_CONVERSION) {
|
||||
status = AE_AML_STRING_LIMIT;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a new string object */
|
||||
|
||||
return_desc = acpi_ut_create_string_object (length);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Copy the raw buffer data with no transform. NULL terminated already. */
|
||||
|
||||
ACPI_MEMCPY (return_desc->string.pointer,
|
||||
operand[0]->buffer.pointer, length);
|
||||
break;
|
||||
|
||||
|
||||
case AML_CONCAT_RES_OP: /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
|
||||
|
||||
status = acpi_ex_concat_template (operand[0], operand[1],
|
||||
&return_desc, walk_state);
|
||||
break;
|
||||
|
||||
|
||||
case AML_INDEX_OP: /* Index (Source Index Result) */
|
||||
|
||||
/* Create the internal return object */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
index = (u32) operand[1]->integer.value;
|
||||
|
||||
/*
|
||||
* At this point, the Source operand is a Package, Buffer, or String
|
||||
*/
|
||||
if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
|
||||
/* Object to be indexed is a Package */
|
||||
|
||||
if (index >= operand[0]->package.count) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Index value (%X) beyond package end (%X)\n",
|
||||
index, operand[0]->package.count));
|
||||
status = AE_AML_PACKAGE_LIMIT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
|
||||
return_desc->reference.object = operand[0];
|
||||
return_desc->reference.where = &operand[0]->package.elements [index];
|
||||
}
|
||||
else {
|
||||
/* Object to be indexed is a Buffer/String */
|
||||
|
||||
if (index >= operand[0]->buffer.length) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Index value (%X) beyond end of buffer (%X)\n",
|
||||
index, operand[0]->buffer.length));
|
||||
status = AE_AML_BUFFER_LIMIT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
|
||||
return_desc->reference.object = operand[0];
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a reference to the target package/buffer/string for the life
|
||||
* of the index.
|
||||
*/
|
||||
acpi_ut_add_reference (operand[0]);
|
||||
|
||||
/* Complete the Index reference object */
|
||||
|
||||
return_desc->reference.opcode = AML_INDEX_OP;
|
||||
return_desc->reference.offset = index;
|
||||
|
||||
/* Store the reference to the Target */
|
||||
|
||||
status = acpi_ex_store (return_desc, operand[2], walk_state);
|
||||
|
||||
/* Return the reference */
|
||||
|
||||
walk_state->result_obj = return_desc;
|
||||
goto cleanup;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
store_result_to_target:
|
||||
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
/*
|
||||
* Store the result of the operation (which is now in return_desc) into
|
||||
* the Target descriptor.
|
||||
*/
|
||||
status = acpi_ex_store (return_desc, operand[2], walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!walk_state->result_obj) {
|
||||
walk_state->result_obj = return_desc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Delete return object on error */
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_remove_reference (return_desc);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_2A_0T_1R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_2A_0T_1R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *return_desc = NULL;
|
||||
acpi_status status = AE_OK;
|
||||
u8 logical_result = FALSE;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
|
||||
acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
/* Create the internal return object */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute the Opcode
|
||||
*/
|
||||
if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ {
|
||||
status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
|
||||
operand[0]->integer.value, operand[1]->integer.value,
|
||||
&logical_result);
|
||||
goto store_logical_result;
|
||||
}
|
||||
else if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
|
||||
status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
|
||||
operand[1], &logical_result);
|
||||
goto store_logical_result;
|
||||
}
|
||||
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_ACQUIRE_OP: /* Acquire (mutex_object, Timeout) */
|
||||
|
||||
status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
|
||||
if (status == AE_TIME) {
|
||||
logical_result = TRUE; /* TRUE = Acquire timed out */
|
||||
status = AE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_WAIT_OP: /* Wait (event_object, Timeout) */
|
||||
|
||||
status = acpi_ex_system_wait_event (operand[1], operand[0]);
|
||||
if (status == AE_TIME) {
|
||||
logical_result = TRUE; /* TRUE, Wait timed out */
|
||||
status = AE_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
store_logical_result:
|
||||
/*
|
||||
* Set return value to according to logical_result. logical TRUE (all ones)
|
||||
* Default is FALSE (zero)
|
||||
*/
|
||||
if (logical_result) {
|
||||
return_desc->integer.value = ACPI_INTEGER_MAX;
|
||||
}
|
||||
|
||||
walk_state->result_obj = return_desc;
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Delete return object on error */
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_remove_reference (return_desc);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exoparg3 - AML execution - opcodes with 3 arguments
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exoparg3")
|
||||
|
||||
|
||||
/*!
|
||||
* Naming convention for AML interpreter execution routines.
|
||||
*
|
||||
* The routines that begin execution of AML opcodes are named with a common
|
||||
* convention based upon the number of arguments, the number of target operands,
|
||||
* and whether or not a value is returned:
|
||||
*
|
||||
* AcpiExOpcode_xA_yT_zR
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* xA - ARGUMENTS: The number of arguments (input operands) that are
|
||||
* required for this opcode type (1 through 6 args).
|
||||
* yT - TARGETS: The number of targets (output operands) that are required
|
||||
* for this opcode type (0, 1, or 2 targets).
|
||||
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
|
||||
* as the function return (0 or 1).
|
||||
*
|
||||
* The AcpiExOpcode* functions are called via the Dispatcher component with
|
||||
* fully resolved operands.
|
||||
!*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_3A_0T_0R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute Triadic operator (3 operands)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_3A_0T_0R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
struct acpi_signal_fatal_info *fatal;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_0T_0R", acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"fatal_op: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
|
||||
(u32) operand[0]->integer.value,
|
||||
(u32) operand[1]->integer.value,
|
||||
(u32) operand[2]->integer.value));
|
||||
|
||||
fatal = ACPI_MEM_ALLOCATE (sizeof (struct acpi_signal_fatal_info));
|
||||
if (fatal) {
|
||||
fatal->type = (u32) operand[0]->integer.value;
|
||||
fatal->code = (u32) operand[1]->integer.value;
|
||||
fatal->argument = (u32) operand[2]->integer.value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Always signal the OS!
|
||||
*/
|
||||
status = acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
|
||||
|
||||
/* Might return while OS is shutting down, just continue */
|
||||
|
||||
ACPI_MEM_FREE (fatal);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_3A_1T_1R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute Triadic operator (3 operands)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_3A_1T_1R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *return_desc = NULL;
|
||||
char *buffer;
|
||||
acpi_status status = AE_OK;
|
||||
acpi_native_uint index;
|
||||
acpi_size length;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_3A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_MID_OP: /* Mid (Source[0], Index[1], Length[2], Result[3]) */
|
||||
|
||||
/*
|
||||
* Create the return object. The Source operand is guaranteed to be
|
||||
* either a String or a Buffer, so just use its type.
|
||||
*/
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_GET_OBJECT_TYPE (operand[0]));
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Get the Integer values from the objects */
|
||||
|
||||
index = (acpi_native_uint) operand[1]->integer.value;
|
||||
length = (acpi_size) operand[2]->integer.value;
|
||||
|
||||
/*
|
||||
* If the index is beyond the length of the String/Buffer, or if the
|
||||
* requested length is zero, return a zero-length String/Buffer
|
||||
*/
|
||||
if ((index < operand[0]->string.length) &&
|
||||
(length > 0)) {
|
||||
/* Truncate request if larger than the actual String/Buffer */
|
||||
|
||||
if ((index + length) >
|
||||
operand[0]->string.length) {
|
||||
length = (acpi_size) operand[0]->string.length - index;
|
||||
}
|
||||
|
||||
/* Allocate a new buffer for the String/Buffer */
|
||||
|
||||
buffer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
|
||||
if (!buffer) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Copy the portion requested */
|
||||
|
||||
ACPI_MEMCPY (buffer, operand[0]->string.pointer + index,
|
||||
length);
|
||||
|
||||
/* Set the length of the new String/Buffer */
|
||||
|
||||
return_desc->string.pointer = buffer;
|
||||
return_desc->string.length = (u32) length;
|
||||
}
|
||||
|
||||
/* Mark buffer initialized */
|
||||
|
||||
return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Store the result in the target */
|
||||
|
||||
status = acpi_ex_store (return_desc, operand[3], walk_state);
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Delete return object on error */
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_remove_reference (return_desc);
|
||||
}
|
||||
|
||||
/* Set the return object and exit */
|
||||
|
||||
if (!walk_state->result_obj) {
|
||||
walk_state->result_obj = return_desc;
|
||||
}
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,336 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exoparg6 - AML execution - opcodes with 6 arguments
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exoparg6")
|
||||
|
||||
|
||||
/*!
|
||||
* Naming convention for AML interpreter execution routines.
|
||||
*
|
||||
* The routines that begin execution of AML opcodes are named with a common
|
||||
* convention based upon the number of arguments, the number of target operands,
|
||||
* and whether or not a value is returned:
|
||||
*
|
||||
* AcpiExOpcode_xA_yT_zR
|
||||
*
|
||||
* Where:
|
||||
*
|
||||
* xA - ARGUMENTS: The number of arguments (input operands) that are
|
||||
* required for this opcode type (1 through 6 args).
|
||||
* yT - TARGETS: The number of targets (output operands) that are required
|
||||
* for this opcode type (0, 1, or 2 targets).
|
||||
* zR - RETURN VALUE: Indicates whether this opcode type returns a value
|
||||
* as the function return (0 or 1).
|
||||
*
|
||||
* The AcpiExOpcode* functions are called via the Dispatcher component with
|
||||
* fully resolved operands.
|
||||
!*/
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_do_match
|
||||
*
|
||||
* PARAMETERS: match_op - The AML match operand
|
||||
* package_obj - Object from the target package
|
||||
* match_obj - Object to be matched
|
||||
*
|
||||
* RETURN: TRUE if the match is successful, FALSE otherwise
|
||||
*
|
||||
* DESCRIPTION: Implements the low-level match for the ASL Match operator.
|
||||
* Package elements will be implicitly converted to the type of
|
||||
* the match object (Integer/Buffer/String).
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8
|
||||
acpi_ex_do_match (
|
||||
u32 match_op,
|
||||
union acpi_operand_object *package_obj,
|
||||
union acpi_operand_object *match_obj)
|
||||
{
|
||||
u8 logical_result = TRUE;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
/*
|
||||
* Note: Since the package_obj/match_obj ordering is opposite to that of
|
||||
* the standard logical operators, we have to reverse them when we call
|
||||
* do_logical_op in order to make the implicit conversion rules work
|
||||
* correctly. However, this means we have to flip the entire equation
|
||||
* also. A bit ugly perhaps, but overall, better than fussing the
|
||||
* parameters around at runtime, over and over again.
|
||||
*
|
||||
* Below, P[i] refers to the package element, M refers to the Match object.
|
||||
*/
|
||||
switch (match_op) {
|
||||
case MATCH_MTR:
|
||||
|
||||
/* Always true */
|
||||
|
||||
break;
|
||||
|
||||
case MATCH_MEQ:
|
||||
|
||||
/*
|
||||
* True if equal: (P[i] == M)
|
||||
* Change to: (M == P[i])
|
||||
*/
|
||||
status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj,
|
||||
&logical_result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case MATCH_MLE:
|
||||
|
||||
/*
|
||||
* True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
|
||||
* Change to: (M >= P[i]) (M not_less than P[i])
|
||||
*/
|
||||
status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
|
||||
&logical_result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
logical_result = (u8) !logical_result;
|
||||
break;
|
||||
|
||||
case MATCH_MLT:
|
||||
|
||||
/*
|
||||
* True if less than: (P[i] < M)
|
||||
* Change to: (M > P[i])
|
||||
*/
|
||||
status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
|
||||
&logical_result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
case MATCH_MGE:
|
||||
|
||||
/*
|
||||
* True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
|
||||
* Change to: (M <= P[i]) (M not_greater than P[i])
|
||||
*/
|
||||
status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
|
||||
&logical_result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
logical_result = (u8)!logical_result;
|
||||
break;
|
||||
|
||||
case MATCH_MGT:
|
||||
|
||||
/*
|
||||
* True if greater than: (P[i] > M)
|
||||
* Change to: (M < P[i])
|
||||
*/
|
||||
status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
|
||||
&logical_result);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Undefined */
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return logical_result;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_opcode_6A_0T_1R
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_opcode_6A_0T_1R (
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
union acpi_operand_object *return_desc = NULL;
|
||||
acpi_status status = AE_OK;
|
||||
u32 index;
|
||||
union acpi_operand_object *this_element;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR ("ex_opcode_6A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
|
||||
|
||||
|
||||
switch (walk_state->opcode) {
|
||||
case AML_MATCH_OP:
|
||||
/*
|
||||
* Match (search_pkg[0], match_op1[1], match_obj1[2],
|
||||
* match_op2[3], match_obj2[4], start_index[5])
|
||||
*/
|
||||
|
||||
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
|
||||
|
||||
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
|
||||
(operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n"));
|
||||
status = AE_AML_OPERAND_VALUE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Get the package start_index, validate against the package length */
|
||||
|
||||
index = (u32) operand[5]->integer.value;
|
||||
if (index >= (u32) operand[0]->package.count) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index beyond package end\n"));
|
||||
status = AE_AML_PACKAGE_LIMIT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Create an integer for the return value */
|
||||
|
||||
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
|
||||
if (!return_desc) {
|
||||
status = AE_NO_MEMORY;
|
||||
goto cleanup;
|
||||
|
||||
}
|
||||
|
||||
/* Default return value if no match found */
|
||||
|
||||
return_desc->integer.value = ACPI_INTEGER_MAX;
|
||||
|
||||
/*
|
||||
* Examine each element until a match is found. Both match conditions
|
||||
* must be satisfied for a match to occur. Within the loop,
|
||||
* "continue" signifies that the current element does not match
|
||||
* and the next should be examined.
|
||||
*
|
||||
* Upon finding a match, the loop will terminate via "break" at
|
||||
* the bottom. If it terminates "normally", match_value will be
|
||||
* ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
|
||||
* match was found.
|
||||
*/
|
||||
for ( ; index < operand[0]->package.count; index++) {
|
||||
/* Get the current package element */
|
||||
|
||||
this_element = operand[0]->package.elements[index];
|
||||
|
||||
/* Treat any uninitialized (NULL) elements as non-matching */
|
||||
|
||||
if (!this_element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Both match conditions must be satisfied. Execution of a continue
|
||||
* (proceed to next iteration of enclosing for loop) signifies a
|
||||
* non-match.
|
||||
*/
|
||||
if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
|
||||
this_element, operand[2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
|
||||
this_element, operand[4])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Match found: Index is the return value */
|
||||
|
||||
return_desc->integer.value = index;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_LOAD_TABLE_OP:
|
||||
|
||||
status = acpi_ex_load_table_op (walk_state, &return_desc);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_opcode_3A_0T_0R: Unknown opcode %X\n",
|
||||
walk_state->opcode));
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
walk_state->result_obj = return_desc;
|
||||
|
||||
|
||||
cleanup:
|
||||
|
||||
/* Delete return object on error */
|
||||
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_remove_reference (return_desc);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exprep")
|
||||
|
||||
|
||||
#ifdef ACPI_UNDER_DEVELOPMENT
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_generate_access
|
||||
*
|
||||
* PARAMETERS: field_bit_offset - Start of field within parent region/buffer
|
||||
* field_bit_length - Length of field in bits
|
||||
* region_length - Length of parent in bytes
|
||||
*
|
||||
* RETURN: Field granularity (8, 16, 32 or 64) and
|
||||
* byte_alignment (1, 2, 3, or 4)
|
||||
*
|
||||
* DESCRIPTION: Generate an optimal access width for fields defined with the
|
||||
* any_acc keyword.
|
||||
*
|
||||
* NOTE: Need to have the region_length in order to check for boundary
|
||||
* conditions (end-of-region). However, the region_length is a deferred
|
||||
* operation. Therefore, to complete this implementation, the generation
|
||||
* of this access width must be deferred until the region length has
|
||||
* been evaluated.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u32
|
||||
acpi_ex_generate_access (
|
||||
u32 field_bit_offset,
|
||||
u32 field_bit_length,
|
||||
u32 region_length)
|
||||
{
|
||||
u32 field_byte_length;
|
||||
u32 field_byte_offset;
|
||||
u32 field_byte_end_offset;
|
||||
u32 access_byte_width;
|
||||
u32 field_start_offset;
|
||||
u32 field_end_offset;
|
||||
u32 minimum_access_width = 0xFFFFFFFF;
|
||||
u32 minimum_accesses = 0xFFFFFFFF;
|
||||
u32 accesses;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_generate_access");
|
||||
|
||||
|
||||
/* Round Field start offset and length to "minimal" byte boundaries */
|
||||
|
||||
field_byte_offset = ACPI_DIV_8 (ACPI_ROUND_DOWN (field_bit_offset, 8));
|
||||
field_byte_end_offset = ACPI_DIV_8 (ACPI_ROUND_UP (field_bit_length + field_bit_offset, 8));
|
||||
field_byte_length = field_byte_end_offset - field_byte_offset;
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Bit length %d, Bit offset %d\n",
|
||||
field_bit_length, field_bit_offset));
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Byte Length %d, Byte Offset %d, End Offset %d\n",
|
||||
field_byte_length, field_byte_offset, field_byte_end_offset));
|
||||
|
||||
/*
|
||||
* Iterative search for the maximum access width that is both aligned
|
||||
* and does not go beyond the end of the region
|
||||
*
|
||||
* Start at byte_acc and work upwards to qword_acc max. (1,2,4,8 bytes)
|
||||
*/
|
||||
for (access_byte_width = 1; access_byte_width <= 8; access_byte_width <<= 1) {
|
||||
/*
|
||||
* 1) Round end offset up to next access boundary and make sure that this
|
||||
* does not go beyond the end of the parent region.
|
||||
* 2) When the Access width is greater than the field_byte_length, we are done.
|
||||
* (This does not optimize for the perfectly aligned case yet).
|
||||
*/
|
||||
if (ACPI_ROUND_UP (field_byte_end_offset, access_byte_width) <= region_length) {
|
||||
field_start_offset = ACPI_ROUND_DOWN (field_byte_offset, access_byte_width) /
|
||||
access_byte_width;
|
||||
field_end_offset = ACPI_ROUND_UP ((field_byte_length + field_byte_offset),
|
||||
access_byte_width) / access_byte_width;
|
||||
accesses = field_end_offset - field_start_offset;
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"access_width %d end is within region\n", access_byte_width));
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Field Start %d, Field End %d -- requires %d accesses\n",
|
||||
field_start_offset, field_end_offset, accesses));
|
||||
|
||||
/* Single access is optimal */
|
||||
|
||||
if (accesses <= 1) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Entire field can be accessed with one operation of size %d\n",
|
||||
access_byte_width));
|
||||
return_VALUE (access_byte_width);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fits in the region, but requires more than one read/write.
|
||||
* try the next wider access on next iteration
|
||||
*/
|
||||
if (accesses < minimum_accesses) {
|
||||
minimum_accesses = accesses;
|
||||
minimum_access_width = access_byte_width;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"access_width %d end is NOT within region\n", access_byte_width));
|
||||
if (access_byte_width == 1) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Field goes beyond end-of-region!\n"));
|
||||
return_VALUE (0); /* Field does not fit in the region at all */
|
||||
}
|
||||
|
||||
/* This width goes beyond the end-of-region, back off to previous access */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Backing off to previous optimal access width of %d\n",
|
||||
minimum_access_width));
|
||||
return_VALUE (minimum_access_width);
|
||||
}
|
||||
}
|
||||
|
||||
/* Could not read/write field with one operation, just use max access width */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Cannot access field in one operation, using width 8\n"));
|
||||
return_VALUE (8);
|
||||
}
|
||||
#endif /* ACPI_UNDER_DEVELOPMENT */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_decode_field_access
|
||||
*
|
||||
* PARAMETERS: Access - Encoded field access bits
|
||||
* Length - Field length.
|
||||
*
|
||||
* RETURN: Field granularity (8, 16, 32 or 64) and
|
||||
* byte_alignment (1, 2, 3, or 4)
|
||||
*
|
||||
* DESCRIPTION: Decode the access_type bits of a field definition.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u32
|
||||
acpi_ex_decode_field_access (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u8 field_flags,
|
||||
u32 *return_byte_alignment)
|
||||
{
|
||||
u32 access;
|
||||
u32 byte_alignment;
|
||||
u32 bit_length;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_decode_field_access");
|
||||
|
||||
|
||||
access = (field_flags & AML_FIELD_ACCESS_TYPE_MASK);
|
||||
|
||||
switch (access) {
|
||||
case AML_FIELD_ACCESS_ANY:
|
||||
|
||||
#ifdef ACPI_UNDER_DEVELOPMENT
|
||||
byte_alignment = acpi_ex_generate_access (obj_desc->common_field.start_field_bit_offset,
|
||||
obj_desc->common_field.bit_length,
|
||||
0xFFFFFFFF /* Temp until we pass region_length as param */);
|
||||
bit_length = byte_alignment * 8;
|
||||
#endif
|
||||
|
||||
byte_alignment = 1;
|
||||
bit_length = 8;
|
||||
break;
|
||||
|
||||
case AML_FIELD_ACCESS_BYTE:
|
||||
case AML_FIELD_ACCESS_BUFFER: /* ACPI 2.0 (SMBus Buffer) */
|
||||
byte_alignment = 1;
|
||||
bit_length = 8;
|
||||
break;
|
||||
|
||||
case AML_FIELD_ACCESS_WORD:
|
||||
byte_alignment = 2;
|
||||
bit_length = 16;
|
||||
break;
|
||||
|
||||
case AML_FIELD_ACCESS_DWORD:
|
||||
byte_alignment = 4;
|
||||
bit_length = 32;
|
||||
break;
|
||||
|
||||
case AML_FIELD_ACCESS_QWORD: /* ACPI 2.0 */
|
||||
byte_alignment = 8;
|
||||
bit_length = 64;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Invalid field access type */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Unknown field access type %X\n",
|
||||
access));
|
||||
return_VALUE (0);
|
||||
}
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_BUFFER_FIELD) {
|
||||
/*
|
||||
* buffer_field access can be on any byte boundary, so the
|
||||
* byte_alignment is always 1 byte -- regardless of any byte_alignment
|
||||
* implied by the field access type.
|
||||
*/
|
||||
byte_alignment = 1;
|
||||
}
|
||||
|
||||
*return_byte_alignment = byte_alignment;
|
||||
return_VALUE (bit_length);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_prep_common_field_object
|
||||
*
|
||||
* PARAMETERS: obj_desc - The field object
|
||||
* field_flags - Access, lock_rule, and update_rule.
|
||||
* The format of a field_flag is described
|
||||
* in the ACPI specification
|
||||
* field_bit_position - Field start position
|
||||
* field_bit_length - Field length in number of bits
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Initialize the areas of the field object that are common
|
||||
* to the various types of fields. Note: This is very "sensitive"
|
||||
* code because we are solving the general case for field
|
||||
* alignment.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_prep_common_field_object (
|
||||
union acpi_operand_object *obj_desc,
|
||||
u8 field_flags,
|
||||
u8 field_attribute,
|
||||
u32 field_bit_position,
|
||||
u32 field_bit_length)
|
||||
{
|
||||
u32 access_bit_width;
|
||||
u32 byte_alignment;
|
||||
u32 nearest_byte_address;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_prep_common_field_object");
|
||||
|
||||
|
||||
/*
|
||||
* Note: the structure being initialized is the
|
||||
* ACPI_COMMON_FIELD_INFO; No structure fields outside of the common
|
||||
* area are initialized by this procedure.
|
||||
*/
|
||||
obj_desc->common_field.field_flags = field_flags;
|
||||
obj_desc->common_field.attribute = field_attribute;
|
||||
obj_desc->common_field.bit_length = field_bit_length;
|
||||
|
||||
/*
|
||||
* Decode the access type so we can compute offsets. The access type gives
|
||||
* two pieces of information - the width of each field access and the
|
||||
* necessary byte_alignment (address granularity) of the access.
|
||||
*
|
||||
* For any_acc, the access_bit_width is the largest width that is both
|
||||
* necessary and possible in an attempt to access the whole field in one
|
||||
* I/O operation. However, for any_acc, the byte_alignment is always one
|
||||
* byte.
|
||||
*
|
||||
* For all Buffer Fields, the byte_alignment is always one byte.
|
||||
*
|
||||
* For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
|
||||
* the same (equivalent) as the byte_alignment.
|
||||
*/
|
||||
access_bit_width = acpi_ex_decode_field_access (obj_desc, field_flags,
|
||||
&byte_alignment);
|
||||
if (!access_bit_width) {
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
/* Setup width (access granularity) fields */
|
||||
|
||||
obj_desc->common_field.access_byte_width = (u8)
|
||||
ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
|
||||
|
||||
obj_desc->common_field.access_bit_width = (u8) access_bit_width;
|
||||
|
||||
/*
|
||||
* base_byte_offset is the address of the start of the field within the
|
||||
* region. It is the byte address of the first *datum* (field-width data
|
||||
* unit) of the field. (i.e., the first datum that contains at least the
|
||||
* first *bit* of the field.)
|
||||
*
|
||||
* Note: byte_alignment is always either equal to the access_bit_width or 8
|
||||
* (Byte access), and it defines the addressing granularity of the parent
|
||||
* region or buffer.
|
||||
*/
|
||||
nearest_byte_address =
|
||||
ACPI_ROUND_BITS_DOWN_TO_BYTES (field_bit_position);
|
||||
obj_desc->common_field.base_byte_offset = (u32)
|
||||
ACPI_ROUND_DOWN (nearest_byte_address, byte_alignment);
|
||||
|
||||
/*
|
||||
* start_field_bit_offset is the offset of the first bit of the field within
|
||||
* a field datum.
|
||||
*/
|
||||
obj_desc->common_field.start_field_bit_offset = (u8)
|
||||
(field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
|
||||
|
||||
/*
|
||||
* Does the entire field fit within a single field access element? (datum)
|
||||
* (i.e., without crossing a datum boundary)
|
||||
*/
|
||||
if ((obj_desc->common_field.start_field_bit_offset + field_bit_length) <=
|
||||
(u16) access_bit_width) {
|
||||
obj_desc->common.flags |= AOPOBJ_SINGLE_DATUM;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_prep_field_value
|
||||
*
|
||||
* PARAMETERS: Node - Owning Node
|
||||
* region_node - Region in which field is being defined
|
||||
* field_flags - Access, lock_rule, and update_rule.
|
||||
* field_bit_position - Field start position
|
||||
* field_bit_length - Field length in number of bits
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Construct an union acpi_operand_object of type def_field and
|
||||
* connect it to the parent Node.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_prep_field_value (
|
||||
struct acpi_create_field_info *info)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
u32 type;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_prep_field_value");
|
||||
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (info->field_type != ACPI_TYPE_LOCAL_INDEX_FIELD) {
|
||||
if (!info->region_node) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null region_node\n"));
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
type = acpi_ns_get_type (info->region_node);
|
||||
if (type != ACPI_TYPE_REGION) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed Region, found type %X (%s)\n",
|
||||
type, acpi_ut_get_type_name (type)));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate a new field object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object (info->field_type);
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Initialize areas of the object that are common to all fields */
|
||||
|
||||
obj_desc->common_field.node = info->field_node;
|
||||
status = acpi_ex_prep_common_field_object (obj_desc, info->field_flags,
|
||||
info->attribute, info->field_bit_position, info->field_bit_length);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
acpi_ut_delete_object_desc (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Initialize areas of the object that are specific to the field type */
|
||||
|
||||
switch (info->field_type) {
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
|
||||
obj_desc->field.region_obj = acpi_ns_get_attached_object (info->region_node);
|
||||
|
||||
/* An additional reference for the container */
|
||||
|
||||
acpi_ut_add_reference (obj_desc->field.region_obj);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"region_field: bit_off %X, Off %X, Gran %X, Region %p\n",
|
||||
obj_desc->field.start_field_bit_offset, obj_desc->field.base_byte_offset,
|
||||
obj_desc->field.access_byte_width, obj_desc->field.region_obj));
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
|
||||
obj_desc->bank_field.value = info->bank_value;
|
||||
obj_desc->bank_field.region_obj = acpi_ns_get_attached_object (info->region_node);
|
||||
obj_desc->bank_field.bank_obj = acpi_ns_get_attached_object (info->register_node);
|
||||
|
||||
/* An additional reference for the attached objects */
|
||||
|
||||
acpi_ut_add_reference (obj_desc->bank_field.region_obj);
|
||||
acpi_ut_add_reference (obj_desc->bank_field.bank_obj);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"Bank Field: bit_off %X, Off %X, Gran %X, Region %p, bank_reg %p\n",
|
||||
obj_desc->bank_field.start_field_bit_offset,
|
||||
obj_desc->bank_field.base_byte_offset,
|
||||
obj_desc->field.access_byte_width,
|
||||
obj_desc->bank_field.region_obj,
|
||||
obj_desc->bank_field.bank_obj));
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
obj_desc->index_field.index_obj = acpi_ns_get_attached_object (info->register_node);
|
||||
obj_desc->index_field.data_obj = acpi_ns_get_attached_object (info->data_register_node);
|
||||
obj_desc->index_field.value = (u32)
|
||||
(info->field_bit_position / ACPI_MUL_8 (obj_desc->field.access_byte_width));
|
||||
|
||||
if (!obj_desc->index_field.data_obj || !obj_desc->index_field.index_obj) {
|
||||
ACPI_REPORT_ERROR (("Null Index Object during field prep\n"));
|
||||
acpi_ut_delete_object_desc (obj_desc);
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/* An additional reference for the attached objects */
|
||||
|
||||
acpi_ut_add_reference (obj_desc->index_field.data_obj);
|
||||
acpi_ut_add_reference (obj_desc->index_field.index_obj);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
|
||||
"index_field: bit_off %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
|
||||
obj_desc->index_field.start_field_bit_offset,
|
||||
obj_desc->index_field.base_byte_offset,
|
||||
obj_desc->index_field.value,
|
||||
obj_desc->field.access_byte_width,
|
||||
obj_desc->index_field.index_obj,
|
||||
obj_desc->index_field.data_obj));
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No other types should get here */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the constructed descriptor (obj_desc) into the parent Node,
|
||||
* preserving the current type of that named_obj.
|
||||
*/
|
||||
status = acpi_ns_attach_object (info->field_node, obj_desc,
|
||||
acpi_ns_get_type (info->field_node));
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Set named_obj %p [%4.4s], obj_desc %p\n",
|
||||
info->field_node, acpi_ut_get_node_name (info->field_node), obj_desc));
|
||||
|
||||
/* Remove local reference to the object */
|
||||
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exregion - ACPI default op_region (address space) handlers
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exregion")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_memory_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the System Memory address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_memory_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
void *logical_addr_ptr = NULL;
|
||||
struct acpi_mem_space_context *mem_info = region_context;
|
||||
u32 length;
|
||||
acpi_size window_size;
|
||||
#ifndef ACPI_MISALIGNED_TRANSFERS
|
||||
u32 remainder;
|
||||
#endif
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_memory_space_handler");
|
||||
|
||||
|
||||
/* Validate and translate the bit width */
|
||||
|
||||
switch (bit_width) {
|
||||
case 8:
|
||||
length = 1;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
length = 2;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
length = 4;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
length = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid system_memory width %d\n",
|
||||
bit_width));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_VALUE);
|
||||
}
|
||||
|
||||
|
||||
#ifndef ACPI_MISALIGNED_TRANSFERS
|
||||
/*
|
||||
* Hardware does not support non-aligned data transfers, we must verify
|
||||
* the request.
|
||||
*/
|
||||
(void) acpi_ut_short_divide ((acpi_integer) address, length, NULL, &remainder);
|
||||
if (remainder != 0) {
|
||||
return_ACPI_STATUS (AE_AML_ALIGNMENT);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Does the request fit into the cached memory mapping?
|
||||
* Is 1) Address below the current mapping? OR
|
||||
* 2) Address beyond the current mapping?
|
||||
*/
|
||||
if ((address < mem_info->mapped_physical_address) ||
|
||||
(((acpi_integer) address + length) >
|
||||
((acpi_integer) mem_info->mapped_physical_address + mem_info->mapped_length))) {
|
||||
/*
|
||||
* The request cannot be resolved by the current memory mapping;
|
||||
* Delete the existing mapping and create a new one.
|
||||
*/
|
||||
if (mem_info->mapped_length) {
|
||||
/* Valid mapping, delete it */
|
||||
|
||||
acpi_os_unmap_memory (mem_info->mapped_logical_address,
|
||||
mem_info->mapped_length);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't attempt to map memory beyond the end of the region, and
|
||||
* constrain the maximum mapping size to something reasonable.
|
||||
*/
|
||||
window_size = (acpi_size) ((mem_info->address + mem_info->length) - address);
|
||||
if (window_size > ACPI_SYSMEM_REGION_WINDOW_SIZE) {
|
||||
window_size = ACPI_SYSMEM_REGION_WINDOW_SIZE;
|
||||
}
|
||||
|
||||
/* Create a new mapping starting at the address given */
|
||||
|
||||
status = acpi_os_map_memory (address, window_size,
|
||||
(void **) &mem_info->mapped_logical_address);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X%8.8X, size %X\n",
|
||||
ACPI_FORMAT_UINT64 (address), (u32) window_size));
|
||||
mem_info->mapped_length = 0;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Save the physical address and mapping size */
|
||||
|
||||
mem_info->mapped_physical_address = address;
|
||||
mem_info->mapped_length = window_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a logical pointer corresponding to the address we want to
|
||||
* access
|
||||
*/
|
||||
logical_addr_ptr = mem_info->mapped_logical_address +
|
||||
((acpi_integer) address - (acpi_integer) mem_info->mapped_physical_address);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"system_memory %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
|
||||
ACPI_FORMAT_UINT64 (address)));
|
||||
|
||||
/*
|
||||
* Perform the memory read or write
|
||||
*
|
||||
* Note: For machines that do not support non-aligned transfers, the target
|
||||
* address was checked for alignment above. We do not attempt to break the
|
||||
* transfer up into smaller (byte-size) chunks because the AML specifically
|
||||
* asked for a transfer width that the hardware may require.
|
||||
*/
|
||||
switch (function) {
|
||||
case ACPI_READ:
|
||||
|
||||
*value = 0;
|
||||
switch (bit_width) {
|
||||
case 8:
|
||||
*value = (acpi_integer) *((u8 *) logical_addr_ptr);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
*value = (acpi_integer) *((u16 *) logical_addr_ptr);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
*value = (acpi_integer) *((u32 *) logical_addr_ptr);
|
||||
break;
|
||||
|
||||
#if ACPI_MACHINE_WIDTH != 16
|
||||
case 64:
|
||||
*value = (acpi_integer) *((u64 *) logical_addr_ptr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
/* bit_width was already validated */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_WRITE:
|
||||
|
||||
switch (bit_width) {
|
||||
case 8:
|
||||
*(u8 *) logical_addr_ptr = (u8) *value;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
*(u16 *) logical_addr_ptr = (u16) *value;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
*(u32 *) logical_addr_ptr = (u32) *value;
|
||||
break;
|
||||
|
||||
#if ACPI_MACHINE_WIDTH != 16
|
||||
case 64:
|
||||
*(u64 *) logical_addr_ptr = (u64) *value;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
/* bit_width was already validated */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_io_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the System IO address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_io_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u32 value32;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_io_space_handler");
|
||||
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"system_iO %d (%d width) Address=%8.8X%8.8X\n", function, bit_width,
|
||||
ACPI_FORMAT_UINT64 (address)));
|
||||
|
||||
/* Decode the function parameter */
|
||||
|
||||
switch (function) {
|
||||
case ACPI_READ:
|
||||
|
||||
status = acpi_os_read_port ((acpi_io_address) address, &value32, bit_width);
|
||||
*value = value32;
|
||||
break;
|
||||
|
||||
case ACPI_WRITE:
|
||||
|
||||
status = acpi_os_write_port ((acpi_io_address) address, (u32) *value, bit_width);
|
||||
break;
|
||||
|
||||
default:
|
||||
status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_pci_config_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the PCI Config address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_pci_config_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_pci_id *pci_id;
|
||||
u16 pci_register;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_pci_config_space_handler");
|
||||
|
||||
|
||||
/*
|
||||
* The arguments to acpi_os(Read|Write)pci_configuration are:
|
||||
*
|
||||
* pci_segment is the PCI bus segment range 0-31
|
||||
* pci_bus is the PCI bus number range 0-255
|
||||
* pci_device is the PCI device number range 0-31
|
||||
* pci_function is the PCI device function number
|
||||
* pci_register is the Config space register range 0-255 bytes
|
||||
*
|
||||
* Value - input value for write, output address for read
|
||||
*
|
||||
*/
|
||||
pci_id = (struct acpi_pci_id *) region_context;
|
||||
pci_register = (u16) (u32) address;
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"pci_config %d (%d) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
|
||||
function, bit_width, pci_id->segment, pci_id->bus, pci_id->device,
|
||||
pci_id->function, pci_register));
|
||||
|
||||
switch (function) {
|
||||
case ACPI_READ:
|
||||
|
||||
*value = 0;
|
||||
status = acpi_os_read_pci_configuration (pci_id, pci_register, value, bit_width);
|
||||
break;
|
||||
|
||||
case ACPI_WRITE:
|
||||
|
||||
status = acpi_os_write_pci_configuration (pci_id, pci_register, *value, bit_width);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_cmos_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the CMOS address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_cmos_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_cmos_space_handler");
|
||||
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_pci_bar_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the PCI bar_target address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_pci_bar_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_pci_bar_space_handler");
|
||||
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_data_table_space_handler
|
||||
*
|
||||
* PARAMETERS: Function - Read or Write operation
|
||||
* Address - Where in the space to read or write
|
||||
* bit_width - Field width in bits (8, 16, or 32)
|
||||
* Value - Pointer to in or out value
|
||||
* handler_context - Pointer to Handler's context
|
||||
* region_context - Pointer to context specific to the
|
||||
* accessed region
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Handler for the Data Table address space (Op Region)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_data_table_space_handler (
|
||||
u32 function,
|
||||
acpi_physical_address address,
|
||||
u32 bit_width,
|
||||
acpi_integer *value,
|
||||
void *handler_context,
|
||||
void *region_context)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u32 byte_width = ACPI_DIV_8 (bit_width);
|
||||
u32 i;
|
||||
char *logical_addr_ptr;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_data_table_space_handler");
|
||||
|
||||
|
||||
logical_addr_ptr = ACPI_PHYSADDR_TO_PTR (address);
|
||||
|
||||
|
||||
/* Perform the memory read or write */
|
||||
|
||||
switch (function) {
|
||||
case ACPI_READ:
|
||||
|
||||
for (i = 0; i < byte_width; i++) {
|
||||
((char *) value) [i] = logical_addr_ptr[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case ACPI_WRITE:
|
||||
default:
|
||||
|
||||
return_ACPI_STATUS (AE_SUPPORT);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exresnte - AML Interpreter object resolution
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exresnte")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_node_to_value
|
||||
*
|
||||
* PARAMETERS: object_ptr - Pointer to a location that contains
|
||||
* a pointer to a NS node, and will receive a
|
||||
* pointer to the resolved object.
|
||||
* walk_state - Current state. Valid only if executing AML
|
||||
* code. NULL if simply resolving an object
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Resolve a Namespace node to a valued object
|
||||
*
|
||||
* Note: for some of the data types, the pointer attached to the Node
|
||||
* can be either a pointer to an actual internal object or a pointer into the
|
||||
* AML stream itself. These types are currently:
|
||||
*
|
||||
* ACPI_TYPE_INTEGER
|
||||
* ACPI_TYPE_STRING
|
||||
* ACPI_TYPE_BUFFER
|
||||
* ACPI_TYPE_MUTEX
|
||||
* ACPI_TYPE_PACKAGE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_node_to_value (
|
||||
struct acpi_namespace_node **object_ptr,
|
||||
struct acpi_walk_state *walk_state)
|
||||
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *source_desc;
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
struct acpi_namespace_node *node;
|
||||
acpi_object_type entry_type;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_resolve_node_to_value");
|
||||
|
||||
|
||||
/*
|
||||
* The stack pointer points to a struct acpi_namespace_node (Node). Get the
|
||||
* object that is attached to the Node.
|
||||
*/
|
||||
node = *object_ptr;
|
||||
source_desc = acpi_ns_get_attached_object (node);
|
||||
entry_type = acpi_ns_get_type ((acpi_handle) node);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Entry=%p source_desc=%p [%s]\n",
|
||||
node, source_desc, acpi_ut_get_type_name (entry_type)));
|
||||
|
||||
if ((entry_type == ACPI_TYPE_LOCAL_ALIAS) ||
|
||||
(entry_type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
|
||||
/* There is always exactly one level of indirection */
|
||||
|
||||
node = ACPI_CAST_PTR (struct acpi_namespace_node, node->object);
|
||||
source_desc = acpi_ns_get_attached_object (node);
|
||||
entry_type = acpi_ns_get_type ((acpi_handle) node);
|
||||
*object_ptr = node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Several object types require no further processing:
|
||||
* 1) Devices rarely have an attached object, return the Node
|
||||
* 2) Method locals and arguments have a pseudo-Node
|
||||
*/
|
||||
if (entry_type == ACPI_TYPE_DEVICE ||
|
||||
(node->flags & (ANOBJ_METHOD_ARG | ANOBJ_METHOD_LOCAL))) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
if (!source_desc) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No object attached to node %p\n",
|
||||
node));
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
/*
|
||||
* Action is based on the type of the Node, which indicates the type
|
||||
* of the attached object or pointer
|
||||
*/
|
||||
switch (entry_type) {
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_PACKAGE) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Package, type %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
status = acpi_ds_get_package_arguments (source_desc);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Buffer, type %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
status = acpi_ds_get_buffer_arguments (source_desc);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a String, type %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Object not a Integer, type %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read Node=%p source_desc=%p Type=%X\n",
|
||||
node, source_desc, entry_type));
|
||||
|
||||
status = acpi_ex_read_data_from_field (walk_state, source_desc, &obj_desc);
|
||||
break;
|
||||
|
||||
/*
|
||||
* For these objects, just return the object attached to the Node
|
||||
*/
|
||||
case ACPI_TYPE_MUTEX:
|
||||
case ACPI_TYPE_METHOD:
|
||||
case ACPI_TYPE_POWER:
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
case ACPI_TYPE_THERMAL:
|
||||
case ACPI_TYPE_EVENT:
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
break;
|
||||
|
||||
|
||||
/* TYPE_ANY is untyped, and thus there is no object associated with it */
|
||||
|
||||
case ACPI_TYPE_ANY:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Untyped entry %p, no attached object!\n",
|
||||
node));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE); /* Cannot be AE_TYPE */
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
switch (source_desc->reference.opcode) {
|
||||
case AML_LOAD_OP:
|
||||
|
||||
/* This is a ddb_handle */
|
||||
/* Return an additional reference to the object */
|
||||
|
||||
obj_desc = source_desc;
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No named references are allowed here */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unsupported Reference opcode %X (%s)\n",
|
||||
source_desc->reference.opcode,
|
||||
acpi_ps_get_opcode_name (source_desc->reference.opcode)));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
/* Default case is for unknown types */
|
||||
|
||||
default:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Node %p - Unknown object type %X\n",
|
||||
node, entry_type));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
|
||||
} /* switch (entry_type) */
|
||||
|
||||
|
||||
/* Put the object descriptor on the stack */
|
||||
|
||||
*object_ptr = (void *) obj_desc;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,546 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exresolv - AML Interpreter object resolution
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
#include <acpi/acparser.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exresolv")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_to_value
|
||||
*
|
||||
* PARAMETERS: **stack_ptr - Points to entry on obj_stack, which can
|
||||
* be either an (union acpi_operand_object *)
|
||||
* or an acpi_handle.
|
||||
* walk_state - Current method state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Convert Reference objects to values
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_to_value (
|
||||
union acpi_operand_object **stack_ptr,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_resolve_to_value", stack_ptr);
|
||||
|
||||
|
||||
if (!stack_ptr || !*stack_ptr) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Internal - null pointer\n"));
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
/*
|
||||
* The entity pointed to by the stack_ptr can be either
|
||||
* 1) A valid union acpi_operand_object, or
|
||||
* 2) A struct acpi_namespace_node (named_obj)
|
||||
*/
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_OPERAND) {
|
||||
status = acpi_ex_resolve_object_to_value (stack_ptr, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Object on the stack may have changed if acpi_ex_resolve_object_to_value()
|
||||
* was called (i.e., we can't use an _else_ here.)
|
||||
*/
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (*stack_ptr) == ACPI_DESC_TYPE_NAMED) {
|
||||
status = acpi_ex_resolve_node_to_value (
|
||||
ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, stack_ptr),
|
||||
walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Resolved object %p\n", *stack_ptr));
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_object_to_value
|
||||
*
|
||||
* PARAMETERS: stack_ptr - Pointer to a stack location that contains a
|
||||
* ptr to an internal object.
|
||||
* walk_state - Current method state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Retrieve the value from an internal object. The Reference type
|
||||
* uses the associated AML opcode to determine the value.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_object_to_value (
|
||||
union acpi_operand_object **stack_ptr,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *stack_desc;
|
||||
void *temp_node;
|
||||
union acpi_operand_object *obj_desc;
|
||||
u16 opcode;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_resolve_object_to_value");
|
||||
|
||||
|
||||
stack_desc = *stack_ptr;
|
||||
|
||||
/* This is an union acpi_operand_object */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (stack_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
opcode = stack_desc->reference.opcode;
|
||||
|
||||
switch (opcode) {
|
||||
case AML_NAME_OP:
|
||||
|
||||
/*
|
||||
* Convert indirect name ptr to a direct name ptr.
|
||||
* Then, acpi_ex_resolve_node_to_value can be used to get the value
|
||||
*/
|
||||
temp_node = stack_desc->reference.object;
|
||||
|
||||
/* Delete the Reference Object */
|
||||
|
||||
acpi_ut_remove_reference (stack_desc);
|
||||
|
||||
/* Put direct name pointer onto stack and exit */
|
||||
|
||||
(*stack_ptr) = temp_node;
|
||||
break;
|
||||
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
|
||||
/*
|
||||
* Get the local from the method's state info
|
||||
* Note: this increments the local's object reference count
|
||||
*/
|
||||
status = acpi_ds_method_data_get_value (opcode,
|
||||
stack_desc->reference.offset, walk_state, &obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[Arg/Local %X] value_obj is %p\n",
|
||||
stack_desc->reference.offset, obj_desc));
|
||||
|
||||
/*
|
||||
* Now we can delete the original Reference Object and
|
||||
* replace it with the resolved value
|
||||
*/
|
||||
acpi_ut_remove_reference (stack_desc);
|
||||
*stack_ptr = obj_desc;
|
||||
break;
|
||||
|
||||
|
||||
case AML_INDEX_OP:
|
||||
|
||||
switch (stack_desc->reference.target_type) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
||||
/* Just return - leave the Reference on the stack */
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
obj_desc = *stack_desc->reference.where;
|
||||
if (obj_desc) {
|
||||
/*
|
||||
* Valid obj descriptor, copy pointer to return value
|
||||
* (i.e., dereference the package index)
|
||||
* Delete the ref object, increment the returned object
|
||||
*/
|
||||
acpi_ut_remove_reference (stack_desc);
|
||||
acpi_ut_add_reference (obj_desc);
|
||||
*stack_ptr = obj_desc;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* A NULL object descriptor means an unitialized element of
|
||||
* the package, can't dereference it
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Attempt to deref an Index to NULL pkg element Idx=%p\n",
|
||||
stack_desc));
|
||||
status = AE_AML_UNINITIALIZED_ELEMENT;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Invalid reference object */
|
||||
|
||||
ACPI_REPORT_ERROR ((
|
||||
"During resolve, Unknown target_type %X in Index/Reference obj %p\n",
|
||||
stack_desc->reference.target_type, stack_desc));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_REF_OF_OP:
|
||||
case AML_DEBUG_OP:
|
||||
case AML_LOAD_OP:
|
||||
|
||||
/* Just leave the object as-is */
|
||||
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("During resolve, Unknown Reference opcode %X (%s) in %p\n",
|
||||
opcode, acpi_ps_get_opcode_name (opcode), stack_desc));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
status = acpi_ds_get_buffer_arguments (stack_desc);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
status = acpi_ds_get_package_arguments (stack_desc);
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* These cases may never happen here, but just in case..
|
||||
*/
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "field_read source_desc=%p Type=%X\n",
|
||||
stack_desc, ACPI_GET_OBJECT_TYPE (stack_desc)));
|
||||
|
||||
status = acpi_ex_read_data_from_field (walk_state, stack_desc, &obj_desc);
|
||||
*stack_ptr = (void *) obj_desc;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_multiple
|
||||
*
|
||||
* PARAMETERS: walk_state - Current state (contains AML opcode)
|
||||
* Operand - Starting point for resolution
|
||||
* return_type - Where the object type is returned
|
||||
* return_desc - Where the resolved object is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Return the base object and type. Traverse a reference list if
|
||||
* necessary to get to the base object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_multiple (
|
||||
struct acpi_walk_state *walk_state,
|
||||
union acpi_operand_object *operand,
|
||||
acpi_object_type *return_type,
|
||||
union acpi_operand_object **return_desc)
|
||||
{
|
||||
union acpi_operand_object *obj_desc = (void *) operand;
|
||||
struct acpi_namespace_node *node;
|
||||
acpi_object_type type;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("acpi_ex_resolve_multiple");
|
||||
|
||||
|
||||
/*
|
||||
* Operand can be either a namespace node or an operand descriptor
|
||||
*/
|
||||
switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
|
||||
case ACPI_DESC_TYPE_OPERAND:
|
||||
type = obj_desc->common.type;
|
||||
break;
|
||||
|
||||
case ACPI_DESC_TYPE_NAMED:
|
||||
type = ((struct acpi_namespace_node *) obj_desc)->type;
|
||||
obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
|
||||
|
||||
/* If we had an Alias node, use the attached object for type info */
|
||||
|
||||
if (type == ACPI_TYPE_LOCAL_ALIAS) {
|
||||
type = ((struct acpi_namespace_node *) obj_desc)->type;
|
||||
obj_desc = acpi_ns_get_attached_object ((struct acpi_namespace_node *) obj_desc);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If type is anything other than a reference, we are done
|
||||
*/
|
||||
if (type != ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* For reference objects created via the ref_of or Index operators,
|
||||
* we need to get to the base object (as per the ACPI specification
|
||||
* of the object_type and size_of operators). This means traversing
|
||||
* the list of possibly many nested references.
|
||||
*/
|
||||
while (ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_REF_OF_OP:
|
||||
|
||||
/* Dereference the reference pointer */
|
||||
|
||||
node = obj_desc->reference.object;
|
||||
|
||||
/* All "References" point to a NS node */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
|
||||
node, acpi_ut_get_descriptor_name (node)));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/* Get the attached object */
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object (node);
|
||||
if (!obj_desc) {
|
||||
/* No object, use the NS node type */
|
||||
|
||||
type = acpi_ns_get_type (node);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check for circular references */
|
||||
|
||||
if (obj_desc == operand) {
|
||||
return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_INDEX_OP:
|
||||
|
||||
/* Get the type of this reference (index into another object) */
|
||||
|
||||
type = obj_desc->reference.target_type;
|
||||
if (type != ACPI_TYPE_PACKAGE) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
* The main object is a package, we want to get the type
|
||||
* of the individual package element that is referenced by
|
||||
* the index.
|
||||
*
|
||||
* This could of course in turn be another reference object.
|
||||
*/
|
||||
obj_desc = *(obj_desc->reference.where);
|
||||
if (!obj_desc) {
|
||||
/* NULL package elements are allowed */
|
||||
|
||||
type = 0; /* Uninitialized */
|
||||
goto exit;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_INT_NAMEPATH_OP:
|
||||
|
||||
/* Dereference the reference pointer */
|
||||
|
||||
node = obj_desc->reference.node;
|
||||
|
||||
/* All "References" point to a NS node */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (node) != ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Not a NS node %p [%s]\n",
|
||||
node, acpi_ut_get_descriptor_name (node)));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/* Get the attached object */
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object (node);
|
||||
if (!obj_desc) {
|
||||
/* No object, use the NS node type */
|
||||
|
||||
type = acpi_ns_get_type (node);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check for circular references */
|
||||
|
||||
if (obj_desc == operand) {
|
||||
return_ACPI_STATUS (AE_AML_CIRCULAR_REFERENCE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
|
||||
if (return_desc) {
|
||||
status = acpi_ds_method_data_get_value (obj_desc->reference.opcode,
|
||||
obj_desc->reference.offset, walk_state, &obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
}
|
||||
else {
|
||||
status = acpi_ds_method_data_get_node (obj_desc->reference.opcode,
|
||||
obj_desc->reference.offset, walk_state, &node);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object (node);
|
||||
if (!obj_desc) {
|
||||
type = ACPI_TYPE_ANY;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case AML_DEBUG_OP:
|
||||
|
||||
/* The Debug Object is of type "debug_object" */
|
||||
|
||||
type = ACPI_TYPE_DEBUG_OBJECT;
|
||||
goto exit;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("acpi_ex_resolve_multiple: Unknown Reference subtype %X\n",
|
||||
obj_desc->reference.opcode));
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we are guaranteed to have an object that has not been created
|
||||
* via the ref_of or Index operators.
|
||||
*/
|
||||
type = ACPI_GET_OBJECT_TYPE (obj_desc);
|
||||
|
||||
|
||||
exit:
|
||||
/* Convert internal types to external types */
|
||||
|
||||
switch (type) {
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
type = ACPI_TYPE_FIELD_UNIT;
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_LOCAL_SCOPE:
|
||||
|
||||
/* Per ACPI Specification, Scope is untyped */
|
||||
|
||||
type = ACPI_TYPE_ANY;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No change to Type required */
|
||||
break;
|
||||
}
|
||||
|
||||
*return_type = type;
|
||||
if (return_desc) {
|
||||
*return_desc = obj_desc;
|
||||
}
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,661 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exresop - AML Interpreter operand/object resolution
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acparser.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exresop")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_check_object_type
|
||||
*
|
||||
* PARAMETERS: type_needed Object type needed
|
||||
* this_type Actual object type
|
||||
* Object Object pointer
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Check required type against actual type
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_check_object_type (
|
||||
acpi_object_type type_needed,
|
||||
acpi_object_type this_type,
|
||||
void *object)
|
||||
{
|
||||
ACPI_FUNCTION_NAME ("ex_check_object_type");
|
||||
|
||||
|
||||
if (type_needed == ACPI_TYPE_ANY) {
|
||||
/* All types OK, so we don't perform any typechecks */
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
if (type_needed == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
/*
|
||||
* Allow the AML "Constant" opcodes (Zero, One, etc.) to be reference
|
||||
* objects and thus allow them to be targets. (As per the ACPI
|
||||
* specification, a store to a constant is a noop.)
|
||||
*/
|
||||
if ((this_type == ACPI_TYPE_INTEGER) &&
|
||||
(((union acpi_operand_object *) object)->common.flags & AOPOBJ_AML_CONSTANT)) {
|
||||
return (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
if (type_needed != this_type) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [%s], found [%s] %p\n",
|
||||
acpi_ut_get_type_name (type_needed),
|
||||
acpi_ut_get_type_name (this_type), object));
|
||||
|
||||
return (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_operands
|
||||
*
|
||||
* PARAMETERS: Opcode - Opcode being interpreted
|
||||
* stack_ptr - Pointer to the operand stack to be
|
||||
* resolved
|
||||
* walk_state - Current state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Convert multiple input operands to the types required by the
|
||||
* target operator.
|
||||
*
|
||||
* Each 5-bit group in arg_types represents one required
|
||||
* operand and indicates the required Type. The corresponding operand
|
||||
* will be converted to the required type if possible, otherwise we
|
||||
* abort with an exception.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_operands (
|
||||
u16 opcode,
|
||||
union acpi_operand_object **stack_ptr,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
acpi_status status = AE_OK;
|
||||
u8 object_type;
|
||||
void *temp_node;
|
||||
u32 arg_types;
|
||||
const struct acpi_opcode_info *op_info;
|
||||
u32 this_arg_type;
|
||||
acpi_object_type type_needed;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_U32 ("ex_resolve_operands", opcode);
|
||||
|
||||
|
||||
op_info = acpi_ps_get_opcode_info (opcode);
|
||||
if (op_info->class == AML_CLASS_UNKNOWN) {
|
||||
return_ACPI_STATUS (AE_AML_BAD_OPCODE);
|
||||
}
|
||||
|
||||
arg_types = op_info->runtime_args;
|
||||
if (arg_types == ARGI_INVALID_OPCODE) {
|
||||
ACPI_REPORT_ERROR (("resolve_operands: %X is not a valid AML opcode\n",
|
||||
opcode));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode %X [%s] required_operand_types=%8.8X \n",
|
||||
opcode, op_info->name, arg_types));
|
||||
|
||||
/*
|
||||
* Normal exit is with (arg_types == 0) at end of argument list.
|
||||
* Function will return an exception from within the loop upon
|
||||
* finding an entry which is not (or cannot be converted
|
||||
* to) the required type; if stack underflows; or upon
|
||||
* finding a NULL stack entry (which should not happen).
|
||||
*/
|
||||
while (GET_CURRENT_ARG_TYPE (arg_types)) {
|
||||
if (!stack_ptr || !*stack_ptr) {
|
||||
ACPI_REPORT_ERROR (("resolve_operands: Null stack entry at %p\n",
|
||||
stack_ptr));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
/* Extract useful items */
|
||||
|
||||
obj_desc = *stack_ptr;
|
||||
|
||||
/* Decode the descriptor type */
|
||||
|
||||
switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) {
|
||||
case ACPI_DESC_TYPE_NAMED:
|
||||
|
||||
/* Node */
|
||||
|
||||
object_type = ((struct acpi_namespace_node *) obj_desc)->type;
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_DESC_TYPE_OPERAND:
|
||||
|
||||
/* ACPI internal object */
|
||||
|
||||
object_type = ACPI_GET_OBJECT_TYPE (obj_desc);
|
||||
|
||||
/* Check for bad acpi_object_type */
|
||||
|
||||
if (!acpi_ut_valid_object_type (object_type)) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Bad operand object type [%X]\n",
|
||||
object_type));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
if (object_type == (u8) ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
/*
|
||||
* Decode the Reference
|
||||
*/
|
||||
op_info = acpi_ps_get_opcode_info (opcode);
|
||||
if (op_info->class == AML_CLASS_UNKNOWN) {
|
||||
return_ACPI_STATUS (AE_AML_BAD_OPCODE);
|
||||
}
|
||||
|
||||
switch (obj_desc->reference.opcode) {
|
||||
case AML_DEBUG_OP:
|
||||
case AML_NAME_OP:
|
||||
case AML_INDEX_OP:
|
||||
case AML_REF_OF_OP:
|
||||
case AML_ARG_OP:
|
||||
case AML_LOCAL_OP:
|
||||
case AML_LOAD_OP: /* ddb_handle from LOAD_OP or LOAD_TABLE_OP */
|
||||
|
||||
ACPI_DEBUG_ONLY_MEMBERS (ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"Operand is a Reference, ref_opcode [%s]\n",
|
||||
(acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name)));
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Operand is a Reference, Unknown Reference Opcode %X [%s]\n",
|
||||
obj_desc->reference.opcode,
|
||||
(acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Invalid descriptor */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Invalid descriptor %p [%s]\n",
|
||||
obj_desc, acpi_ut_get_descriptor_name (obj_desc)));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get one argument type, point to the next
|
||||
*/
|
||||
this_arg_type = GET_CURRENT_ARG_TYPE (arg_types);
|
||||
INCREMENT_ARG_LIST (arg_types);
|
||||
|
||||
/*
|
||||
* Handle cases where the object does not need to be
|
||||
* resolved to a value
|
||||
*/
|
||||
switch (this_arg_type) {
|
||||
case ARGI_REF_OR_STRING: /* Can be a String or Reference */
|
||||
|
||||
if ((ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_OPERAND) &&
|
||||
(ACPI_GET_OBJECT_TYPE (obj_desc) == ACPI_TYPE_STRING)) {
|
||||
/*
|
||||
* String found - the string references a named object and must be
|
||||
* resolved to a node
|
||||
*/
|
||||
goto next_operand;
|
||||
}
|
||||
|
||||
/* Else not a string - fall through to the normal Reference case below */
|
||||
/*lint -fallthrough */
|
||||
|
||||
case ARGI_REFERENCE: /* References: */
|
||||
case ARGI_INTEGER_REF:
|
||||
case ARGI_OBJECT_REF:
|
||||
case ARGI_DEVICE_REF:
|
||||
case ARGI_TARGETREF: /* Allows implicit conversion rules before store */
|
||||
case ARGI_FIXED_TARGET: /* No implicit conversion before store to target */
|
||||
case ARGI_SIMPLE_TARGET: /* Name, Local, or Arg - no implicit conversion */
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_LOCAL_REFERENCE */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) /* Node (name) ptr OK as-is */ {
|
||||
goto next_operand;
|
||||
}
|
||||
|
||||
status = acpi_ex_check_object_type (ACPI_TYPE_LOCAL_REFERENCE,
|
||||
object_type, obj_desc);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (AML_NAME_OP == obj_desc->reference.opcode) {
|
||||
/*
|
||||
* Convert an indirect name ptr to direct name ptr and put
|
||||
* it on the stack
|
||||
*/
|
||||
temp_node = obj_desc->reference.object;
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
(*stack_ptr) = temp_node;
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_DATAREFOBJ: /* Store operator only */
|
||||
|
||||
/*
|
||||
* We don't want to resolve index_op reference objects during
|
||||
* a store because this would be an implicit de_ref_of operation.
|
||||
* Instead, we just want to store the reference object.
|
||||
* -- All others must be resolved below.
|
||||
*/
|
||||
if ((opcode == AML_STORE_OP) &&
|
||||
(ACPI_GET_OBJECT_TYPE (*stack_ptr) == ACPI_TYPE_LOCAL_REFERENCE) &&
|
||||
((*stack_ptr)->reference.opcode == AML_INDEX_OP)) {
|
||||
goto next_operand;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* All cases covered above */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Resolve this object to a value
|
||||
*/
|
||||
status = acpi_ex_resolve_to_value (stack_ptr, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Get the resolved object */
|
||||
|
||||
obj_desc = *stack_ptr;
|
||||
|
||||
/*
|
||||
* Check the resulting object (value) type
|
||||
*/
|
||||
switch (this_arg_type) {
|
||||
/*
|
||||
* For the simple cases, only one type of resolved object
|
||||
* is allowed
|
||||
*/
|
||||
case ARGI_MUTEX:
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_MUTEX */
|
||||
|
||||
type_needed = ACPI_TYPE_MUTEX;
|
||||
break;
|
||||
|
||||
case ARGI_EVENT:
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_EVENT */
|
||||
|
||||
type_needed = ACPI_TYPE_EVENT;
|
||||
break;
|
||||
|
||||
case ARGI_PACKAGE: /* Package */
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_PACKAGE */
|
||||
|
||||
type_needed = ACPI_TYPE_PACKAGE;
|
||||
break;
|
||||
|
||||
case ARGI_ANYTYPE:
|
||||
|
||||
/* Any operand type will do */
|
||||
|
||||
type_needed = ACPI_TYPE_ANY;
|
||||
break;
|
||||
|
||||
case ARGI_DDBHANDLE:
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_DDB_HANDLE */
|
||||
|
||||
type_needed = ACPI_TYPE_LOCAL_REFERENCE;
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
* The more complex cases allow multiple resolved object types
|
||||
*/
|
||||
case ARGI_INTEGER: /* Number */
|
||||
|
||||
/*
|
||||
* Need an operand of type ACPI_TYPE_INTEGER,
|
||||
* But we can implicitly convert from a STRING or BUFFER
|
||||
* Aka - "Implicit Source Operand Conversion"
|
||||
*/
|
||||
status = acpi_ex_convert_to_integer (obj_desc, stack_ptr, 16);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status == AE_TYPE) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Integer/String/Buffer], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_BUFFER:
|
||||
|
||||
/*
|
||||
* Need an operand of type ACPI_TYPE_BUFFER,
|
||||
* But we can implicitly convert from a STRING or INTEGER
|
||||
* Aka - "Implicit Source Operand Conversion"
|
||||
*/
|
||||
status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status == AE_TYPE) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Integer/String/Buffer], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_STRING:
|
||||
|
||||
/*
|
||||
* Need an operand of type ACPI_TYPE_STRING,
|
||||
* But we can implicitly convert from a BUFFER or INTEGER
|
||||
* Aka - "Implicit Source Operand Conversion"
|
||||
*/
|
||||
status = acpi_ex_convert_to_string (obj_desc, stack_ptr,
|
||||
ACPI_IMPLICIT_CONVERT_HEX);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
if (status == AE_TYPE) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Integer/String/Buffer], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_COMPUTEDATA:
|
||||
|
||||
/* Need an operand of type INTEGER, STRING or BUFFER */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Integer/String/Buffer], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_BUFFER_OR_STRING:
|
||||
|
||||
/* Need an operand of type STRING or BUFFER */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* Highest priority conversion is to type Buffer */
|
||||
|
||||
status = acpi_ex_convert_to_buffer (obj_desc, stack_ptr);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Integer/String/Buffer], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_DATAOBJECT:
|
||||
/*
|
||||
* ARGI_DATAOBJECT is only used by the size_of operator.
|
||||
* Need a buffer, string, package, or ref_of reference.
|
||||
*
|
||||
* The only reference allowed here is a direct reference to
|
||||
* a namespace node.
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Buffer/String/Package/Reference], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_COMPLEXOBJ:
|
||||
|
||||
/* Need a buffer or package or (ACPI 2.0) String */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Buffer/String/Package], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_REGION_OR_FIELD:
|
||||
|
||||
/* Need an operand of type ACPI_TYPE_REGION or a FIELD in a region */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_REGION:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed [Region/region_field], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
case ARGI_DATAREFOBJ:
|
||||
|
||||
/* Used by the Store() operator only */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
case ACPI_TYPE_DDB_HANDLE:
|
||||
|
||||
/* Valid operand */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
if (acpi_gbl_enable_interpreter_slack) {
|
||||
/*
|
||||
* Enable original behavior of Store(), allowing any and all
|
||||
* objects as the source operand. The ACPI spec does not
|
||||
* allow this, however.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p\n",
|
||||
acpi_ut_get_object_type_name (obj_desc), obj_desc));
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
goto next_operand;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
/* Unknown type */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Internal - Unknown ARGI (required operand) type %X\n",
|
||||
this_arg_type));
|
||||
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the original object was resolved to the
|
||||
* required object type (Simple cases only).
|
||||
*/
|
||||
status = acpi_ex_check_object_type (type_needed,
|
||||
ACPI_GET_OBJECT_TYPE (*stack_ptr), *stack_ptr);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
next_operand:
|
||||
/*
|
||||
* If more operands needed, decrement stack_ptr to point
|
||||
* to next operand on stack
|
||||
*/
|
||||
if (GET_CURRENT_ARG_TYPE (arg_types)) {
|
||||
stack_ptr--;
|
||||
}
|
||||
|
||||
} /* while (*Types) */
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,536 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exstore - AML Interpreter object store support
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acdispat.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acnamesp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exstore")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store
|
||||
*
|
||||
* PARAMETERS: *source_desc - Value to be stored
|
||||
* *dest_desc - Where to store it. Must be an NS node
|
||||
* or an union acpi_operand_object of type
|
||||
* Reference;
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Store the value described by source_desc into the location
|
||||
* described by dest_desc. Called by various interpreter
|
||||
* functions to store the result of an operation into
|
||||
* the destination operand -- not just simply the actual "Store"
|
||||
* ASL operator.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *dest_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *ref_desc = dest_desc;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_store", dest_desc);
|
||||
|
||||
|
||||
/* Validate parameters */
|
||||
|
||||
if (!source_desc || !dest_desc) {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null parameter\n"));
|
||||
return_ACPI_STATUS (AE_AML_NO_OPERAND);
|
||||
}
|
||||
|
||||
/* dest_desc can be either a namespace node or an ACPI object */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE (dest_desc) == ACPI_DESC_TYPE_NAMED) {
|
||||
/*
|
||||
* Dest is a namespace node,
|
||||
* Storing an object into a Named node.
|
||||
*/
|
||||
status = acpi_ex_store_object_to_node (source_desc,
|
||||
(struct acpi_namespace_node *) dest_desc, walk_state,
|
||||
ACPI_IMPLICIT_CONVERSION);
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* Destination object must be a Reference or a Constant object */
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
|
||||
case ACPI_TYPE_LOCAL_REFERENCE:
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* Allow stores to Constants -- a Noop as per ACPI spec */
|
||||
|
||||
if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
/*lint -fallthrough */
|
||||
|
||||
default:
|
||||
|
||||
/* Destination is not a Reference object */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Target is not a Reference or Constant object - %s [%p]\n",
|
||||
acpi_ut_get_object_type_name (dest_desc), dest_desc));
|
||||
|
||||
ACPI_DUMP_STACK_ENTRY (source_desc);
|
||||
ACPI_DUMP_STACK_ENTRY (dest_desc);
|
||||
ACPI_DUMP_OPERANDS (&dest_desc, ACPI_IMODE_EXECUTE, "ex_store",
|
||||
2, "Target is not a Reference or Constant object");
|
||||
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Examine the Reference opcode. These cases are handled:
|
||||
*
|
||||
* 1) Store to Name (Change the object associated with a name)
|
||||
* 2) Store to an indexed area of a Buffer or Package
|
||||
* 3) Store to a Method Local or Arg
|
||||
* 4) Store to the debug object
|
||||
*/
|
||||
switch (ref_desc->reference.opcode) {
|
||||
case AML_NAME_OP:
|
||||
case AML_REF_OF_OP:
|
||||
|
||||
/* Storing an object into a Name "container" */
|
||||
|
||||
status = acpi_ex_store_object_to_node (source_desc, ref_desc->reference.object,
|
||||
walk_state, ACPI_IMPLICIT_CONVERSION);
|
||||
break;
|
||||
|
||||
|
||||
case AML_INDEX_OP:
|
||||
|
||||
/* Storing to an Index (pointer into a packager or buffer) */
|
||||
|
||||
status = acpi_ex_store_object_to_index (source_desc, ref_desc, walk_state);
|
||||
break;
|
||||
|
||||
|
||||
case AML_LOCAL_OP:
|
||||
case AML_ARG_OP:
|
||||
|
||||
/* Store to a method local/arg */
|
||||
|
||||
status = acpi_ds_store_object_to_local (ref_desc->reference.opcode,
|
||||
ref_desc->reference.offset, source_desc, walk_state);
|
||||
break;
|
||||
|
||||
|
||||
case AML_DEBUG_OP:
|
||||
|
||||
/*
|
||||
* Storing to the Debug object causes the value stored to be
|
||||
* displayed and otherwise has no effect -- see ACPI Specification
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"**** Write to Debug Object: Object %p %s ****:\n\n",
|
||||
source_desc, acpi_ut_get_object_type_name (source_desc)));
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %s: ",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
|
||||
if (!acpi_ut_valid_internal_object (source_desc)) {
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT,
|
||||
"%p, Invalid Internal Object!\n", source_desc));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
if (acpi_gbl_integer_byte_width == 4) {
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n",
|
||||
(u32) source_desc->integer.value));
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n",
|
||||
ACPI_FORMAT_UINT64 (source_desc->integer.value)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]",
|
||||
(u32) source_desc->buffer.length));
|
||||
ACPI_DUMP_BUFFER (source_desc->buffer.pointer,
|
||||
(source_desc->buffer.length < 32) ? source_desc->buffer.length : 32);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n",
|
||||
source_desc->string.length, source_desc->string.pointer));
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] Elements Ptr - %p\n",
|
||||
source_desc->package.count, source_desc->package.elements));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DEBUG_OBJECT, "%p\n",
|
||||
source_desc));
|
||||
break;
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n"));
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_REPORT_ERROR (("ex_store: Unknown Reference opcode %X\n",
|
||||
ref_desc->reference.opcode));
|
||||
ACPI_DUMP_ENTRY (ref_desc, ACPI_LV_ERROR);
|
||||
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store_object_to_index
|
||||
*
|
||||
* PARAMETERS: *source_desc - Value to be stored
|
||||
* *dest_desc - Named object to receive the value
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Store the object to indexed Buffer or Package element
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store_object_to_index (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *index_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *obj_desc;
|
||||
union acpi_operand_object *new_desc;
|
||||
u8 value = 0;
|
||||
u32 i;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_store_object_to_index");
|
||||
|
||||
|
||||
/*
|
||||
* Destination must be a reference pointer, and
|
||||
* must point to either a buffer or a package
|
||||
*/
|
||||
switch (index_desc->reference.target_type) {
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/*
|
||||
* Storing to a package element. Copy the object and replace
|
||||
* any existing object with the new object. No implicit
|
||||
* conversion is performed.
|
||||
*
|
||||
* The object at *(index_desc->Reference.Where) is the
|
||||
* element within the package that is to be modified.
|
||||
* The parent package object is at index_desc->Reference.Object
|
||||
*/
|
||||
obj_desc = *(index_desc->reference.where);
|
||||
|
||||
status = acpi_ut_copy_iobject_to_iobject (source_desc, &new_desc, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (obj_desc) {
|
||||
/* Decrement reference count by the ref count of the parent package */
|
||||
|
||||
for (i = 0; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
|
||||
acpi_ut_remove_reference (obj_desc);
|
||||
}
|
||||
}
|
||||
|
||||
*(index_desc->reference.where) = new_desc;
|
||||
|
||||
/* Increment reference count by the ref count of the parent package -1 */
|
||||
|
||||
for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common.reference_count; i++) {
|
||||
acpi_ut_add_reference (new_desc);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
|
||||
/*
|
||||
* Store into a Buffer or String (not actually a real buffer_field)
|
||||
* at a location defined by an Index.
|
||||
*
|
||||
* The first 8-bit element of the source object is written to the
|
||||
* 8-bit Buffer location defined by the Index destination object,
|
||||
* according to the ACPI 2.0 specification.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Make sure the target is a Buffer or String. An error should
|
||||
* not happen here, since the reference_object was constructed
|
||||
* by the INDEX_OP code.
|
||||
*/
|
||||
obj_desc = index_desc->reference.object;
|
||||
if ((ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_BUFFER) &&
|
||||
(ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_STRING)) {
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The assignment of the individual elements will be slightly
|
||||
* different for each source type.
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (source_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
/* Use the least-significant byte of the integer */
|
||||
|
||||
value = (u8) (source_desc->integer.value);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
/* Note: Takes advantage of common string/buffer fields */
|
||||
|
||||
value = source_desc->buffer.pointer[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* All other types are invalid */
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Source must be Integer/Buffer/String type, not %s\n",
|
||||
acpi_ut_get_object_type_name (source_desc)));
|
||||
return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
|
||||
}
|
||||
|
||||
/* Store the source value into the target buffer byte */
|
||||
|
||||
obj_desc->buffer.pointer[index_desc->reference.offset] = value;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Target is not a Package or buffer_field\n"));
|
||||
status = AE_AML_OPERAND_TYPE;
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store_object_to_node
|
||||
*
|
||||
* PARAMETERS: source_desc - Value to be stored
|
||||
* Node - Named object to receive the value
|
||||
* walk_state - Current walk state
|
||||
* implicit_conversion - Perform implicit conversion (yes/no)
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Store the object to the named object.
|
||||
*
|
||||
* The Assignment of an object to a named object is handled here
|
||||
* The value passed in will replace the current value (if any)
|
||||
* with the input value.
|
||||
*
|
||||
* When storing into an object the data is converted to the
|
||||
* target object type then stored in the object. This means
|
||||
* that the target object type (for an initialized target) will
|
||||
* not be changed by a store operation.
|
||||
*
|
||||
* Assumes parameters are already validated.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store_object_to_node (
|
||||
union acpi_operand_object *source_desc,
|
||||
struct acpi_namespace_node *node,
|
||||
struct acpi_walk_state *walk_state,
|
||||
u8 implicit_conversion)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_operand_object *target_desc;
|
||||
union acpi_operand_object *new_desc;
|
||||
acpi_object_type target_type;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_node", source_desc);
|
||||
|
||||
|
||||
/*
|
||||
* Get current type of the node, and object attached to Node
|
||||
*/
|
||||
target_type = acpi_ns_get_type (node);
|
||||
target_desc = acpi_ns_get_attached_object (node);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n",
|
||||
source_desc, acpi_ut_get_object_type_name (source_desc),
|
||||
node, acpi_ut_get_type_name (target_type)));
|
||||
|
||||
/*
|
||||
* Resolve the source object to an actual value
|
||||
* (If it is a reference object)
|
||||
*/
|
||||
status = acpi_ex_resolve_object (&source_desc, target_type, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
/* If no implicit conversion, drop into the default case below */
|
||||
|
||||
if (!implicit_conversion) {
|
||||
/* Force execution of default (no implicit conversion) */
|
||||
|
||||
target_type = ACPI_TYPE_ANY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the actual store operation
|
||||
*/
|
||||
switch (target_type) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
|
||||
/*
|
||||
* For fields, copy the source data to the target field.
|
||||
*/
|
||||
status = acpi_ex_write_data_to_field (source_desc, target_desc, &walk_state->result_obj);
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/*
|
||||
* These target types are all of type Integer/String/Buffer, and
|
||||
* therefore support implicit conversion before the store.
|
||||
*
|
||||
* Copy and/or convert the source object to a new target object
|
||||
*/
|
||||
status = acpi_ex_store_object_to_object (source_desc, target_desc, &new_desc, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (new_desc != target_desc) {
|
||||
/*
|
||||
* Store the new new_desc as the new value of the Name, and set
|
||||
* the Name's type to that of the value being stored in it.
|
||||
* source_desc reference count is incremented by attach_object.
|
||||
*
|
||||
* Note: This may change the type of the node if an explicit store
|
||||
* has been performed such that the node/object type has been
|
||||
* changed.
|
||||
*/
|
||||
status = acpi_ns_attach_object (node, new_desc, new_desc->common.type);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"Store %s into %s via Convert/Attach\n",
|
||||
acpi_ut_get_object_type_name (source_desc),
|
||||
acpi_ut_get_object_type_name (new_desc)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
|
||||
"Storing %s (%p) directly into node (%p), no implicit conversion\n",
|
||||
acpi_ut_get_object_type_name (source_desc), source_desc, node));
|
||||
|
||||
/* No conversions for all other types. Just attach the source object */
|
||||
|
||||
status = acpi_ns_attach_object (node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc));
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exstoren - AML Interpreter object store support,
|
||||
* Store to Node (namespace object)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exstoren")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_resolve_object
|
||||
*
|
||||
* PARAMETERS: source_desc_ptr - Pointer to the source object
|
||||
* target_type - Current type of the target
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status, resolved object in source_desc_ptr.
|
||||
*
|
||||
* DESCRIPTION: Resolve an object. If the object is a reference, dereference
|
||||
* it and return the actual object in the source_desc_ptr.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_resolve_object (
|
||||
union acpi_operand_object **source_desc_ptr,
|
||||
acpi_object_type target_type,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *source_desc = *source_desc_ptr;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_resolve_object");
|
||||
|
||||
|
||||
/*
|
||||
* Ensure we have a Target that can be stored to
|
||||
*/
|
||||
switch (target_type) {
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_LOCAL_REGION_FIELD:
|
||||
case ACPI_TYPE_LOCAL_BANK_FIELD:
|
||||
case ACPI_TYPE_LOCAL_INDEX_FIELD:
|
||||
/*
|
||||
* These cases all require only Integers or values that
|
||||
* can be converted to Integers (Strings or Buffers)
|
||||
*/
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/*
|
||||
* Stores into a Field/Region or into a Integer/Buffer/String
|
||||
* are all essentially the same. This case handles the
|
||||
* "interchangeable" types Integer, String, and Buffer.
|
||||
*/
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
/* Resolve a reference object first */
|
||||
|
||||
status = acpi_ex_resolve_to_value (source_desc_ptr, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* For copy_object, no further validation necessary */
|
||||
|
||||
if (walk_state->opcode == AML_COPY_OP) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Must have a Integer, Buffer, or String
|
||||
*/
|
||||
if ((ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_INTEGER) &&
|
||||
(ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_BUFFER) &&
|
||||
(ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_TYPE_STRING) &&
|
||||
!((ACPI_GET_OBJECT_TYPE (source_desc) == ACPI_TYPE_LOCAL_REFERENCE) && (source_desc->reference.opcode == AML_LOAD_OP))) {
|
||||
/*
|
||||
* Conversion successful but still not a valid type
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
|
||||
"Cannot assign type %s to %s (must be type Int/Str/Buf)\n",
|
||||
acpi_ut_get_object_type_name (source_desc),
|
||||
acpi_ut_get_type_name (target_type)));
|
||||
status = AE_AML_OPERAND_TYPE;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_LOCAL_ALIAS:
|
||||
case ACPI_TYPE_LOCAL_METHOD_ALIAS:
|
||||
|
||||
/*
|
||||
* Aliases are resolved by acpi_ex_prep_operands
|
||||
*/
|
||||
ACPI_REPORT_ERROR (("Store into Alias - should never happen\n"));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
default:
|
||||
|
||||
/*
|
||||
* All other types than Alias and the various Fields come here,
|
||||
* including the untyped case - ACPI_TYPE_ANY.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store_object_to_object
|
||||
*
|
||||
* PARAMETERS: source_desc - Object to store
|
||||
* dest_desc - Object to receive a copy of the source
|
||||
* new_desc - New object if dest_desc is obsoleted
|
||||
* walk_state - Current walk state
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: "Store" an object to another object. This may include
|
||||
* converting the source type to the target type (implicit
|
||||
* conversion), and a copy of the value of the source to
|
||||
* the target.
|
||||
*
|
||||
* The Assignment of an object to another (not named) object
|
||||
* is handled here.
|
||||
* The Source passed in will replace the current value (if any)
|
||||
* with the input value.
|
||||
*
|
||||
* When storing into an object the data is converted to the
|
||||
* target object type then stored in the object. This means
|
||||
* that the target object type (for an initialized target) will
|
||||
* not be changed by a store operation.
|
||||
*
|
||||
* This module allows destination types of Number, String,
|
||||
* Buffer, and Package.
|
||||
*
|
||||
* Assumes parameters are already validated. NOTE: source_desc
|
||||
* resolution (from a reference object) must be performed by
|
||||
* the caller if necessary.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store_object_to_object (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *dest_desc,
|
||||
union acpi_operand_object **new_desc,
|
||||
struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object *actual_src_desc;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
|
||||
|
||||
|
||||
actual_src_desc = source_desc;
|
||||
if (!dest_desc) {
|
||||
/*
|
||||
* There is no destination object (An uninitialized node or
|
||||
* package element), so we can simply copy the source object
|
||||
* creating a new destination object
|
||||
*/
|
||||
status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, new_desc, walk_state);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
|
||||
/*
|
||||
* The source type does not match the type of the destination.
|
||||
* Perform the "implicit conversion" of the source to the current type
|
||||
* of the target as per the ACPI specification.
|
||||
*
|
||||
* If no conversion performed, actual_src_desc = source_desc.
|
||||
* Otherwise, actual_src_desc is a temporary object to hold the
|
||||
* converted object.
|
||||
*/
|
||||
status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc),
|
||||
source_desc, &actual_src_desc, walk_state);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (source_desc == actual_src_desc) {
|
||||
/*
|
||||
* No conversion was performed. Return the source_desc as the
|
||||
* new object.
|
||||
*/
|
||||
*new_desc = source_desc;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We now have two objects of identical types, and we can perform a
|
||||
* copy of the *value* of the source object.
|
||||
*/
|
||||
switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
|
||||
case ACPI_TYPE_INTEGER:
|
||||
|
||||
dest_desc->integer.value = actual_src_desc->integer.value;
|
||||
|
||||
/* Truncate value if we are executing from a 32-bit ACPI table */
|
||||
|
||||
acpi_ex_truncate_for32bit_table (dest_desc);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_STRING:
|
||||
|
||||
status = acpi_ex_store_string_to_string (actual_src_desc, dest_desc);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_BUFFER:
|
||||
|
||||
/*
|
||||
* Note: There is different store behavior depending on the original
|
||||
* source type
|
||||
*/
|
||||
status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
|
||||
status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc,
|
||||
walk_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other types come here.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "Store into type %s not implemented\n",
|
||||
acpi_ut_get_object_type_name (dest_desc)));
|
||||
|
||||
status = AE_NOT_IMPLEMENTED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (actual_src_desc != source_desc) {
|
||||
/* Delete the intermediate (temporary) source object */
|
||||
|
||||
acpi_ut_remove_reference (actual_src_desc);
|
||||
}
|
||||
|
||||
*new_desc = dest_desc;
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exstorob - AML Interpreter object store support, store to object
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exstorob")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store_buffer_to_buffer
|
||||
*
|
||||
* PARAMETERS: source_desc - Source object to copy
|
||||
* target_desc - Destination object of the copy
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Copy a buffer object to another buffer object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store_buffer_to_buffer (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *target_desc)
|
||||
{
|
||||
u32 length;
|
||||
u8 *buffer;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_store_buffer_to_buffer", source_desc);
|
||||
|
||||
|
||||
/* We know that source_desc is a buffer by now */
|
||||
|
||||
buffer = (u8 *) source_desc->buffer.pointer;
|
||||
length = source_desc->buffer.length;
|
||||
|
||||
/*
|
||||
* If target is a buffer of length zero or is a static buffer,
|
||||
* allocate a new buffer of the proper length
|
||||
*/
|
||||
if ((target_desc->buffer.length == 0) ||
|
||||
(target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
|
||||
target_desc->buffer.pointer = ACPI_MEM_ALLOCATE (length);
|
||||
if (!target_desc->buffer.pointer) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
target_desc->buffer.length = length;
|
||||
}
|
||||
|
||||
/* Copy source buffer to target buffer */
|
||||
|
||||
if (length <= target_desc->buffer.length) {
|
||||
/* Clear existing buffer and copy in the new one */
|
||||
|
||||
ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
|
||||
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
|
||||
|
||||
#ifdef ACPI_OBSOLETE_BEHAVIOR
|
||||
/*
|
||||
* NOTE: ACPI versions up to 3.0 specified that the buffer must be
|
||||
* truncated if the string is smaller than the buffer. However, "other"
|
||||
* implementations of ACPI never did this and thus became the defacto
|
||||
* standard. ACPi 3.0_a changes this behavior such that the buffer
|
||||
* is no longer truncated.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OBSOLETE BEHAVIOR:
|
||||
* If the original source was a string, we must truncate the buffer,
|
||||
* according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
|
||||
* copy must not truncate the original buffer.
|
||||
*/
|
||||
if (original_src_type == ACPI_TYPE_STRING) {
|
||||
/* Set the new length of the target */
|
||||
|
||||
target_desc->buffer.length = length;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* Truncate the source, copy only what will fit */
|
||||
|
||||
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, target_desc->buffer.length);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
|
||||
"Truncating source buffer from %X to %X\n",
|
||||
length, target_desc->buffer.length));
|
||||
}
|
||||
|
||||
/* Copy flags */
|
||||
|
||||
target_desc->buffer.flags = source_desc->buffer.flags;
|
||||
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_store_string_to_string
|
||||
*
|
||||
* PARAMETERS: source_desc - Source object to copy
|
||||
* target_desc - Destination object of the copy
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Copy a String object to another String object
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_store_string_to_string (
|
||||
union acpi_operand_object *source_desc,
|
||||
union acpi_operand_object *target_desc)
|
||||
{
|
||||
u32 length;
|
||||
u8 *buffer;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_store_string_to_string", source_desc);
|
||||
|
||||
|
||||
/* We know that source_desc is a string by now */
|
||||
|
||||
buffer = (u8 *) source_desc->string.pointer;
|
||||
length = source_desc->string.length;
|
||||
|
||||
/*
|
||||
* Replace existing string value if it will fit and the string
|
||||
* pointer is not a static pointer (part of an ACPI table)
|
||||
*/
|
||||
if ((length < target_desc->string.length) &&
|
||||
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
|
||||
/*
|
||||
* String will fit in existing non-static buffer.
|
||||
* Clear old string and copy in the new one
|
||||
*/
|
||||
ACPI_MEMSET (target_desc->string.pointer, 0, (acpi_size) target_desc->string.length + 1);
|
||||
ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Free the current buffer, then allocate a new buffer
|
||||
* large enough to hold the value
|
||||
*/
|
||||
if (target_desc->string.pointer &&
|
||||
(!(target_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
|
||||
/* Only free if not a pointer into the DSDT */
|
||||
|
||||
ACPI_MEM_FREE (target_desc->string.pointer);
|
||||
}
|
||||
|
||||
target_desc->string.pointer = ACPI_MEM_CALLOCATE ((acpi_size) length + 1);
|
||||
if (!target_desc->string.pointer) {
|
||||
return_ACPI_STATUS (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
|
||||
ACPI_MEMCPY (target_desc->string.pointer, buffer, length);
|
||||
}
|
||||
|
||||
/* Set the new target length */
|
||||
|
||||
target_desc->string.length = length;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exsystem - Interface to OS services
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/acevents.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exsystem")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_wait_semaphore
|
||||
*
|
||||
* PARAMETERS: Semaphore - OSD semaphore to wait on
|
||||
* Timeout - Max time to wait
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Implements a semaphore wait with a check to see if the
|
||||
* semaphore is available immediately. If it is not, the
|
||||
* interpreter is released.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_wait_semaphore (
|
||||
acpi_handle semaphore,
|
||||
u16 timeout)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_status status2;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_wait_semaphore");
|
||||
|
||||
|
||||
status = acpi_os_wait_semaphore (semaphore, 1, 0);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
if (status == AE_TIME) {
|
||||
/* We must wait, so unlock the interpreter */
|
||||
|
||||
acpi_ex_exit_interpreter ();
|
||||
|
||||
status = acpi_os_wait_semaphore (semaphore, 1, timeout);
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "*** Thread awake after blocking, %s\n",
|
||||
acpi_format_exception (status)));
|
||||
|
||||
/* Reacquire the interpreter */
|
||||
|
||||
status2 = acpi_ex_enter_interpreter ();
|
||||
if (ACPI_FAILURE (status2)) {
|
||||
/* Report fatal error, could not acquire interpreter */
|
||||
|
||||
return_ACPI_STATUS (status2);
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_do_stall
|
||||
*
|
||||
* PARAMETERS: how_long - The amount of time to stall,
|
||||
* in microseconds
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Suspend running thread for specified amount of time.
|
||||
* Note: ACPI specification requires that Stall() does not
|
||||
* relinquish the processor, and delays longer than 100 usec
|
||||
* should use Sleep() instead. We allow stalls up to 255 usec
|
||||
* for compatibility with other interpreters and existing BIOSs.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_do_stall (
|
||||
u32 how_long)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
if (how_long > 255) /* 255 microseconds */ {
|
||||
/*
|
||||
* Longer than 255 usec, this is an error
|
||||
*
|
||||
* (ACPI specifies 100 usec as max, but this gives some slack in
|
||||
* order to support existing BIOSs)
|
||||
*/
|
||||
ACPI_REPORT_ERROR (("Stall: Time parameter is too large (%d)\n", how_long));
|
||||
status = AE_AML_OPERAND_VALUE;
|
||||
}
|
||||
else {
|
||||
acpi_os_stall (how_long);
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_do_suspend
|
||||
*
|
||||
* PARAMETERS: how_long - The amount of time to suspend,
|
||||
* in milliseconds
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Suspend running thread for specified amount of time.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_do_suspend (
|
||||
acpi_integer how_long)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/* Since this thread will sleep, we must release the interpreter */
|
||||
|
||||
acpi_ex_exit_interpreter ();
|
||||
|
||||
acpi_os_sleep (how_long);
|
||||
|
||||
/* And now we must get the interpreter again */
|
||||
|
||||
status = acpi_ex_enter_interpreter ();
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_acquire_mutex
|
||||
*
|
||||
* PARAMETERS: *time_desc - The 'time to delay' object descriptor
|
||||
* *obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Provides an access point to perform synchronization operations
|
||||
* within the AML. This function will cause a lock to be generated
|
||||
* for the Mutex pointed to by obj_desc.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_acquire_mutex (
|
||||
union acpi_operand_object *time_desc,
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE_PTR ("ex_system_acquire_mutex", obj_desc);
|
||||
|
||||
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for the _GL_ Mutex object -- go get the global lock
|
||||
*/
|
||||
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
|
||||
status = acpi_ev_acquire_global_lock ((u16) time_desc->integer.value);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
status = acpi_ex_system_wait_semaphore (obj_desc->mutex.semaphore,
|
||||
(u16) time_desc->integer.value);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_release_mutex
|
||||
*
|
||||
* PARAMETERS: *obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Provides an access point to perform synchronization operations
|
||||
* within the AML. This operation is a request to release a
|
||||
* previously acquired Mutex. If the Mutex variable is set then
|
||||
* it will be decremented.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_release_mutex (
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_release_mutex");
|
||||
|
||||
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/*
|
||||
* Support for the _GL_ Mutex object -- release the global lock
|
||||
*/
|
||||
if (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore) {
|
||||
status = acpi_ev_release_global_lock ();
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
status = acpi_os_signal_semaphore (obj_desc->mutex.semaphore, 1);
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_signal_event
|
||||
*
|
||||
* PARAMETERS: *obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: AE_OK
|
||||
*
|
||||
* DESCRIPTION: Provides an access point to perform synchronization operations
|
||||
* within the AML.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_signal_event (
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_signal_event");
|
||||
|
||||
|
||||
if (obj_desc) {
|
||||
status = acpi_os_signal_semaphore (obj_desc->event.semaphore, 1);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_wait_event
|
||||
*
|
||||
* PARAMETERS: *time_desc - The 'time to delay' object descriptor
|
||||
* *obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Provides an access point to perform synchronization operations
|
||||
* within the AML. This operation is a request to wait for an
|
||||
* event.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_wait_event (
|
||||
union acpi_operand_object *time_desc,
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_system_wait_event");
|
||||
|
||||
|
||||
if (obj_desc) {
|
||||
status = acpi_ex_system_wait_semaphore (obj_desc->event.semaphore,
|
||||
(u16) time_desc->integer.value);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_system_reset_event
|
||||
*
|
||||
* PARAMETERS: *obj_desc - The object descriptor for this op
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Reset an event to a known state.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_system_reset_event (
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
void *temp_semaphore;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/*
|
||||
* We are going to simply delete the existing semaphore and
|
||||
* create a new one!
|
||||
*/
|
||||
status = acpi_os_create_semaphore (ACPI_NO_UNIT_LIMIT, 0, &temp_semaphore);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
(void) acpi_os_delete_semaphore (obj_desc->event.semaphore);
|
||||
obj_desc->event.semaphore = temp_semaphore;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,378 @@
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: exutils - interpreter/scanner utilities
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2005, R. Byron Moore
|
||||
* 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_AML_GLOBALS is tested in amlcode.h
|
||||
* to determine whether certain global names should be "defined" or only
|
||||
* "declared" in the current compilation. This enhances maintainability
|
||||
* by enabling a single header file to embody all knowledge of the names
|
||||
* in question.
|
||||
*
|
||||
* Exactly one module of any executable should #define DEFINE_GLOBALS
|
||||
* before #including the header files which use this convention. The
|
||||
* names in question will be defined and initialized in that module,
|
||||
* and declared as extern in all other modules which #include those
|
||||
* header files.
|
||||
*/
|
||||
|
||||
#define DEFINE_AML_GLOBALS
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acinterp.h>
|
||||
#include <acpi/amlcode.h>
|
||||
#include <acpi/acevents.h>
|
||||
|
||||
#define _COMPONENT ACPI_EXECUTER
|
||||
ACPI_MODULE_NAME ("exutils")
|
||||
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_enter_interpreter
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* DESCRIPTION: Enter the interpreter execution region. Failure to enter
|
||||
* the interpreter region is a fatal system error
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ex_enter_interpreter (void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_enter_interpreter");
|
||||
|
||||
|
||||
status = acpi_ut_acquire_mutex (ACPI_MTX_EXECUTE);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
ACPI_REPORT_ERROR (("Could not acquire interpreter mutex\n"));
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_exit_interpreter
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* DESCRIPTION: Exit the interpreter execution region
|
||||
*
|
||||
* Cases where the interpreter is unlocked:
|
||||
* 1) Completion of the execution of a control method
|
||||
* 2) Method blocked on a Sleep() AML opcode
|
||||
* 3) Method blocked on an Acquire() AML opcode
|
||||
* 4) Method blocked on a Wait() AML opcode
|
||||
* 5) Method blocked to acquire the global lock
|
||||
* 6) Method blocked to execute a serialized control method that is
|
||||
* already executing
|
||||
* 7) About to invoke a user-installed opregion handler
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_exit_interpreter (void)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_exit_interpreter");
|
||||
|
||||
|
||||
status = acpi_ut_release_mutex (ACPI_MTX_EXECUTE);
|
||||
if (ACPI_FAILURE (status)) {
|
||||
ACPI_REPORT_ERROR (("Could not release interpreter mutex\n"));
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_truncate_for32bit_table
|
||||
*
|
||||
* PARAMETERS: obj_desc - Object to be truncated
|
||||
*
|
||||
* RETURN: none
|
||||
*
|
||||
* DESCRIPTION: Truncate a number to 32-bits if the currently executing method
|
||||
* belongs to a 32-bit ACPI table.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_truncate_for32bit_table (
|
||||
union acpi_operand_object *obj_desc)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/*
|
||||
* Object must be a valid number and we must be executing
|
||||
* a control method
|
||||
*/
|
||||
if ((!obj_desc) ||
|
||||
(ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_INTEGER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (acpi_gbl_integer_byte_width == 4) {
|
||||
/*
|
||||
* We are running a method that exists in a 32-bit ACPI table.
|
||||
* Truncate the value to 32 bits by zeroing out the upper 32-bit field
|
||||
*/
|
||||
obj_desc->integer.value &= (acpi_integer) ACPI_UINT32_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_acquire_global_lock
|
||||
*
|
||||
* PARAMETERS: field_flags - Flags with Lock rule:
|
||||
* always_lock or never_lock
|
||||
*
|
||||
* RETURN: TRUE/FALSE indicating whether the lock was actually acquired
|
||||
*
|
||||
* DESCRIPTION: Obtain the global lock and keep track of this fact via two
|
||||
* methods. A global variable keeps the state of the lock, and
|
||||
* the state is returned to the caller.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u8
|
||||
acpi_ex_acquire_global_lock (
|
||||
u32 field_flags)
|
||||
{
|
||||
u8 locked = FALSE;
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_acquire_global_lock");
|
||||
|
||||
|
||||
/* Only attempt lock if the always_lock bit is set */
|
||||
|
||||
if (field_flags & AML_FIELD_LOCK_RULE_MASK) {
|
||||
/* We should attempt to get the lock, wait forever */
|
||||
|
||||
status = acpi_ev_acquire_global_lock (ACPI_WAIT_FOREVER);
|
||||
if (ACPI_SUCCESS (status)) {
|
||||
locked = TRUE;
|
||||
}
|
||||
else {
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not acquire Global Lock, %s\n",
|
||||
acpi_format_exception (status)));
|
||||
}
|
||||
}
|
||||
|
||||
return_VALUE (locked);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_release_global_lock
|
||||
*
|
||||
* PARAMETERS: locked_by_me - Return value from corresponding call to
|
||||
* acquire_global_lock.
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Release the global lock if it is locked.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_release_global_lock (
|
||||
u8 locked_by_me)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_release_global_lock");
|
||||
|
||||
|
||||
/* Only attempt unlock if the caller locked it */
|
||||
|
||||
if (locked_by_me) {
|
||||
/* OK, now release the lock */
|
||||
|
||||
status = acpi_ev_release_global_lock ();
|
||||
if (ACPI_FAILURE (status)) {
|
||||
/* Report the error, but there isn't much else we can do */
|
||||
|
||||
ACPI_REPORT_ERROR (("Could not release ACPI Global Lock, %s\n",
|
||||
acpi_format_exception (status)));
|
||||
}
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_digits_needed
|
||||
*
|
||||
* PARAMETERS: Value - Value to be represented
|
||||
* Base - Base of representation
|
||||
*
|
||||
* RETURN: the number of digits needed to represent Value in Base
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
u32
|
||||
acpi_ex_digits_needed (
|
||||
acpi_integer value,
|
||||
u32 base)
|
||||
{
|
||||
u32 num_digits;
|
||||
acpi_integer current_value;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE ("ex_digits_needed");
|
||||
|
||||
|
||||
/* acpi_integer is unsigned, so we don't worry about a '-' prefix */
|
||||
|
||||
if (value == 0) {
|
||||
return_VALUE (1);
|
||||
}
|
||||
|
||||
current_value = value;
|
||||
num_digits = 0;
|
||||
|
||||
/* Count the digits in the requested base */
|
||||
|
||||
while (current_value) {
|
||||
(void) acpi_ut_short_divide (current_value, base, ¤t_value, NULL);
|
||||
num_digits++;
|
||||
}
|
||||
|
||||
return_VALUE (num_digits);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_eisa_id_to_string
|
||||
*
|
||||
* PARAMETERS: numeric_id - EISA ID to be converted
|
||||
* out_string - Where to put the converted string (8 bytes)
|
||||
*
|
||||
* DESCRIPTION: Convert a numeric EISA ID to string representation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_eisa_id_to_string (
|
||||
u32 numeric_id,
|
||||
char *out_string)
|
||||
{
|
||||
u32 eisa_id;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
/* Swap ID to big-endian to get contiguous bits */
|
||||
|
||||
eisa_id = acpi_ut_dword_byte_swap (numeric_id);
|
||||
|
||||
out_string[0] = (char) ('@' + (((unsigned long) eisa_id >> 26) & 0x1f));
|
||||
out_string[1] = (char) ('@' + ((eisa_id >> 21) & 0x1f));
|
||||
out_string[2] = (char) ('@' + ((eisa_id >> 16) & 0x1f));
|
||||
out_string[3] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 12);
|
||||
out_string[4] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 8);
|
||||
out_string[5] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 4);
|
||||
out_string[6] = acpi_ut_hex_to_ascii_char ((acpi_integer) eisa_id, 0);
|
||||
out_string[7] = 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ex_unsigned_integer_to_string
|
||||
*
|
||||
* PARAMETERS: Value - Value to be converted
|
||||
* out_string - Where to put the converted string (8 bytes)
|
||||
*
|
||||
* RETURN: Convert a number to string representation
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_ex_unsigned_integer_to_string (
|
||||
acpi_integer value,
|
||||
char *out_string)
|
||||
{
|
||||
u32 count;
|
||||
u32 digits_needed;
|
||||
u32 remainder;
|
||||
|
||||
|
||||
ACPI_FUNCTION_ENTRY ();
|
||||
|
||||
|
||||
digits_needed = acpi_ex_digits_needed (value, 10);
|
||||
out_string[digits_needed] = 0;
|
||||
|
||||
for (count = digits_needed; count > 0; count--) {
|
||||
(void) acpi_ut_short_divide (value, 10, &value, &remainder);
|
||||
out_string[count-1] = (char) ('0' + remainder);\
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user