提交 985f3878 编写于 作者: L Len Brown

Merge branch 'acpica' into release

......@@ -2026,24 +2026,21 @@ acpi_sba_ioc_add(struct acpi_device *device)
struct ioc *ioc;
acpi_status status;
u64 hpa, length;
struct acpi_buffer buffer;
struct acpi_device_info *dev_info;
status = hp_acpi_csr_space(device->handle, &hpa, &length);
if (ACPI_FAILURE(status))
return 1;
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_get_object_info(device->handle, &buffer);
status = acpi_get_object_info(device->handle, &dev_info);
if (ACPI_FAILURE(status))
return 1;
dev_info = buffer.pointer;
/*
* For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI
* root bridges, and its CSR space includes the IOC function.
*/
if (strncmp("HWP0001", dev_info->hardware_id.value, 7) == 0) {
if (strncmp("HWP0001", dev_info->hardware_id.string, 7) == 0) {
hpa += ZX1_IOC_OFFSET;
/* zx1 based systems default to kernel page size iommu pages */
if (!iovp_shift)
......
......@@ -481,26 +481,23 @@ static acpi_status is_memory_device(acpi_handle handle)
{
char *hardware_id;
acpi_status status;
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
struct acpi_device_info *info;
status = acpi_get_object_info(handle, &buffer);
status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status))
return status;
info = buffer.pointer;
if (!(info->valid & ACPI_VALID_HID)) {
kfree(buffer.pointer);
kfree(info);
return AE_ERROR;
}
hardware_id = info->hardware_id.value;
hardware_id = info->hardware_id.string;
if ((hardware_id == NULL) ||
(strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
status = AE_ERROR;
kfree(buffer.pointer);
kfree(info);
return status;
}
......
......@@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \
nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \
nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \
nsparse.o nspredef.o
nsparse.o nspredef.o nsrepair.o
acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o
......@@ -44,4 +44,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
utstate.o utmutex.o utobject.o utresrc.o utlock.o
utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o
......@@ -183,7 +183,7 @@
/* Operation regions */
#define ACPI_NUM_PREDEFINED_REGIONS 8
#define ACPI_NUM_PREDEFINED_REGIONS 9
#define ACPI_USER_REGION_BEGIN 0x80
/* Maximum space_ids for Operation Regions */
......@@ -199,9 +199,15 @@
#define ACPI_RSDP_CHECKSUM_LENGTH 20
#define ACPI_RSDP_XCHECKSUM_LENGTH 36
/* SMBus bidirectional buffer size */
/* SMBus and IPMI bidirectional buffer size */
#define ACPI_SMBUS_BUFFER_SIZE 34
#define ACPI_IPMI_BUFFER_SIZE 66
/* _sx_d and _sx_w control methods */
#define ACPI_NUM_sx_d_METHODS 4
#define ACPI_NUM_sx_w_METHODS 5
/******************************************************************************
*
......
......@@ -154,10 +154,6 @@ void
acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state);
void acpi_db_check_predefined_names(void);
void acpi_db_batch_execute(void);
/*
* dbexec - debugger control method execution
*/
......
......@@ -58,6 +58,10 @@
#define ACPI_INIT_GLOBAL(a,b) a
#endif
#ifdef DEFINE_ACPI_GLOBALS
/* Public globals, available from outside ACPICA subsystem */
/*****************************************************************************
*
* Runtime configuration (static defaults that can be overriden at runtime)
......@@ -78,7 +82,7 @@
* 5) Allow unresolved references (invalid target name) in package objects
* 6) Enable warning messages for behavior that is not ACPI spec compliant
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
/*
* Automatically serialize ALL control methods? Default is FALSE, meaning
......@@ -86,27 +90,36 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE);
* Only change this if the ASL code is poorly written and cannot handle
* reentrancy even though methods are marked "NotSerialized".
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE);
/*
* Create the predefined _OSI method in the namespace? Default is TRUE
* because ACPI CA is fully compatible with other ACPI implementations.
* Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE);
/*
* Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
* RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
* be enabled just before going to sleep.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE);
/*
* Optionally use default values for the ACPI register widths. Set this to
* TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
*/
ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */
struct acpi_table_fadt acpi_gbl_FADT;
u32 acpi_current_gpe_count;
u32 acpi_gbl_trace_flags;
acpi_name acpi_gbl_trace_method_name;
#endif
/*****************************************************************************
*
......@@ -114,11 +127,6 @@ ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE);
*
****************************************************************************/
/* Runtime configuration of debug print levels */
extern u32 acpi_dbg_level;
extern u32 acpi_dbg_layer;
/* Procedure nesting level for debug output */
extern u32 acpi_gbl_nesting_level;
......@@ -127,10 +135,8 @@ extern u32 acpi_gbl_nesting_level;
ACPI_EXTERN u32 acpi_gbl_original_dbg_level;
ACPI_EXTERN u32 acpi_gbl_original_dbg_layer;
ACPI_EXTERN acpi_name acpi_gbl_trace_method_name;
ACPI_EXTERN u32 acpi_gbl_trace_dbg_level;
ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer;
ACPI_EXTERN u32 acpi_gbl_trace_flags;
/*****************************************************************************
*
......@@ -142,10 +148,8 @@ ACPI_EXTERN u32 acpi_gbl_trace_flags;
* acpi_gbl_root_table_list is the master list of ACPI tables found in the
* RSDT/XSDT.
*
* acpi_gbl_FADT is a local copy of the FADT, converted to a common format.
*/
ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list;
ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT;
ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS;
/* These addresses are calculated from the FADT Event Block addresses */
......@@ -261,7 +265,8 @@ ACPI_EXTERN u8 acpi_gbl_osi_data;
extern u8 acpi_gbl_shutdown;
extern u32 acpi_gbl_startup_flags;
extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT];
extern const char *acpi_gbl_highest_dstate_names[4];
extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS];
extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
......@@ -290,6 +295,7 @@ extern char const *acpi_gbl_exception_names_ctrl[];
ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list;
extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES];
extern const struct acpi_predefined_names
......@@ -340,7 +346,6 @@ ACPI_EXTERN struct acpi_fixed_event_handler
ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
ACPI_EXTERN struct acpi_gpe_block_info
*acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
ACPI_EXTERN u32 acpi_current_gpe_count;
/*****************************************************************************
*
......
......@@ -62,6 +62,14 @@ u32 acpi_hw_get_mode(void);
/*
* hwregs - ACPI Register I/O
*/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address);
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg);
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg);
struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id);
acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control);
......
......@@ -461,9 +461,9 @@ void acpi_ex_acquire_global_lock(u32 rule);
void acpi_ex_release_global_lock(u32 rule);
void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string);
void acpi_ex_eisa_id_to_string(char *dest, acpi_integer compressed_id);
void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string);
void acpi_ex_integer_to_string(char *dest, acpi_integer value);
/*
* exregion - default op_region handlers
......
......@@ -369,6 +369,19 @@ union acpi_predefined_info {
struct acpi_package_info3 ret_info3;
};
/* Data block used during object validation */
struct acpi_predefined_data {
char *pathname;
const union acpi_predefined_info *predefined;
u32 flags;
u8 node_flags;
};
/* Defines for Flags field above */
#define ACPI_OBJECT_REPAIRED 1
/*
* Bitmapped return value types
* Note: the actual data types must be contiguous, a loop in nspredef.c
......@@ -885,6 +898,9 @@ struct acpi_bit_register_info {
#define ACPI_OSI_WIN_XP_SP2 0x05
#define ACPI_OSI_WINSRV_2003_SP1 0x06
#define ACPI_OSI_WIN_VISTA 0x07
#define ACPI_OSI_WINSRV_2008 0x08
#define ACPI_OSI_WIN_VISTA_SP1 0x09
#define ACPI_OSI_WIN_7 0x0A
#define ACPI_ALWAYS_ILLEGAL 0x00
......
......@@ -340,6 +340,7 @@
*/
#define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e);
#define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e);
#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist
#else
......@@ -347,6 +348,7 @@
#define ACPI_ERROR_NAMESPACE(s, e)
#define ACPI_ERROR_METHOD(s, n, p, e)
#define ACPI_WARN_PREDEFINED(plist)
#endif /* ACPI_NO_ERROR_MESSAGES */
/*
......
......@@ -73,6 +73,14 @@
#define ACPI_NS_WALK_UNLOCK 0x01
#define ACPI_NS_WALK_TEMP_NODES 0x02
/* Object is not a package element */
#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX
/* Always emit warning message, not dependent on node flags */
#define ACPI_WARN_ALWAYS 0
/*
* nsinit - Namespace initialization
*/
......@@ -144,6 +152,8 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name);
void acpi_ns_delete_node(struct acpi_namespace_node *node);
void acpi_ns_remove_node(struct acpi_namespace_node *node);
void
acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle);
......@@ -186,6 +196,8 @@ acpi_ns_dump_objects(acpi_object_type type,
*/
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
void acpi_ns_exec_module_code_list(void);
/*
* nspredef - Support for predefined/reserved names
*/
......@@ -259,6 +271,19 @@ acpi_status
acpi_ns_get_attached_data(struct acpi_namespace_node *node,
acpi_object_handler handler, void **data);
/*
* nsrepair - return object repair for predefined methods/objects
*/
acpi_status
acpi_ns_repair_object(struct acpi_predefined_data *data,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr);
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr);
/*
* nssearch - Namespace searching and entry
*/
......
......@@ -98,6 +98,7 @@
#define AOPOBJ_SETUP_COMPLETE 0x10
#define AOPOBJ_SINGLE_DATUM 0x20
#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
#define AOPOBJ_MODULE_LEVEL 0x80
/******************************************************************************
*
......
......@@ -62,6 +62,8 @@
#define ACPI_PARSE_DEFERRED_OP 0x0100
#define ACPI_PARSE_DISASSEMBLE 0x0200
#define ACPI_PARSE_MODULE_LEVEL 0x0400
/******************************************************************************
*
* Parser interfaces
......
此差异已折叠。
......@@ -324,26 +324,30 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
acpi_status
acpi_ut_evaluate_numeric_object(char *object_name,
struct acpi_namespace_node *device_node,
acpi_integer * address);
acpi_integer *value);
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id *hid);
acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 *status_flags);
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpi_compatible_id_list **return_cid_list);
acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node,
const char **method_names,
u8 method_count, u8 *out_values);
/*
* utids - device ID support
*/
acpi_status
acpi_ut_execute_STA(struct acpi_namespace_node *device_node,
u32 * status_flags);
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id);
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpica_device_id *uid);
struct acpica_device_id **return_id);
acpi_status
acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest);
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpica_device_id_list **return_cid_list);
/*
* utlock - reader/writer locks
......@@ -445,6 +449,8 @@ acpi_ut_short_divide(acpi_integer in_dividend,
*/
const char *acpi_ut_validate_exception(acpi_status status);
u8 acpi_ut_is_pci_root_bridge(char *id);
u8 acpi_ut_is_aml_table(struct acpi_table_header *table);
acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id);
......@@ -469,6 +475,12 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position);
acpi_status
acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer);
void ACPI_INTERNAL_VAR_XFACE
acpi_ut_predefined_warning(const char *module_name,
u32 line_number,
char *pathname,
u8 node_flags, const char *format, ...);
/* Values for Base above (16=Hex, 10=Decimal) */
#define ACPI_ANY_BASE 0
......
......@@ -404,6 +404,7 @@ typedef enum {
REGION_SMBUS,
REGION_CMOS,
REGION_PCI_BAR,
REGION_IPMI,
REGION_DATA_TABLE, /* Internal use only */
REGION_FIXED_HW = 0x7F
} AML_REGION_TYPES;
......
......@@ -123,9 +123,12 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node temporary if we are executing a method */
if (walk_state->method_node) {
/*
* Mark node temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
......@@ -456,9 +459,12 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node(s) temporary if we are executing a method */
if (walk_state->method_node) {
/*
* Mark node(s) temporary if we are executing a normal control
* method. (Don't mark if this is a module-level code method)
*/
if (walk_state->method_node &&
!(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
......
......@@ -578,10 +578,15 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
}
/*
* Delete any namespace objects created anywhere within
* the namespace by the execution of this method
* Delete any namespace objects created anywhere within the
* namespace by the execution of this method. Unless this method
* is a module-level executable code method, in which case we
* want make the objects permanent.
*/
acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id);
if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
acpi_ns_delete_namespace_by_owner(method_desc->method.
owner_id);
}
}
/* Decrement the thread count on the method */
......@@ -622,7 +627,9 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
/* No more threads, we can free the owner_id */
acpi_ut_release_owner_id(&method_desc->method.owner_id);
if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
acpi_ut_release_owner_id(&method_desc->method.owner_id);
}
}
return_VOID;
......
......@@ -433,10 +433,10 @@ acpi_ds_method_data_get_value(u8 type,
case ACPI_REFCLASS_LOCAL:
ACPI_ERROR((AE_INFO,
"Uninitialized Local[%d] at node %p",
index, node));
/*
* No error message for this case, will be trapped again later to
* detect and ignore cases of Store(local_x,local_x)
*/
return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL);
default:
......
......@@ -482,14 +482,27 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
if (arg) {
/*
* num_elements was exhausted, but there are remaining elements in the
* package_list.
* package_list. Truncate the package to num_elements.
*
* Note: technically, this is an error, from ACPI spec: "It is an error
* for NumElements to be less than the number of elements in the
* PackageList". However, for now, we just print an error message and
* no exception is returned.
* PackageList". However, we just print an error message and
* no exception is returned. This provides Windows compatibility. Some
* BIOSs will alter the num_elements on the fly, creating this type
* of ill-formed package object.
*/
while (arg) {
/*
* We must delete any package elements that were created earlier
* and are not going to be used because of the package truncation.
*/
if (arg->common.node) {
acpi_ut_remove_reference(ACPI_CAST_PTR
(union
acpi_operand_object,
arg->common.node));
arg->common.node = NULL;
}
/* Find out how many elements there really are */
......@@ -498,7 +511,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
}
ACPI_WARNING((AE_INFO,
"Package List length (%X) larger than NumElements count (%X), truncated\n",
"Package List length (0x%X) larger than NumElements count (0x%X), truncated\n",
i, element_count));
} else if (i < element_count) {
/*
......@@ -506,7 +519,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
* Note: this is not an error, the package is padded out with NULLs.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Package List length (%X) smaller than NumElements count (%X), padded with null elements\n",
"Package List length (0x%X) smaller than NumElements count (0x%X), padded with null elements\n",
i, element_count));
}
......
......@@ -581,21 +581,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
(walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
(!(walk_state->op_info->flags & AML_NAMED))) {
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Begin/EXEC: %s (fl %8.8X)\n",
walk_state->op_info->name,
walk_state->op_info->flags));
/* Executing a type1 or type2 opcode outside of a method */
status =
acpi_ds_exec_begin_op(walk_state, out_op);
return_ACPI_STATUS(status);
}
#endif
return_ACPI_STATUS(AE_OK);
}
......@@ -768,7 +753,13 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
/* Execution mode, node cannot already exist, node is temporary */
flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY);
flags |= ACPI_NS_ERROR_IF_FOUND;
if (!
(walk_state->
parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
flags |= ACPI_NS_TEMPORARY;
}
}
/* Add new entry or lookup existing entry */
......@@ -851,24 +842,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
/* Check if opcode had an associated namespace object */
if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
#ifndef ACPI_NO_METHOD_EXECUTION
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
/* No namespace object. Executable opcode? */
if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
(walk_state->op_info->class == AML_CLASS_CONTROL)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"End/EXEC: %s (fl %8.8X)\n",
walk_state->op_info->name,
walk_state->op_info->flags));
/* Executing a type1 or type2 opcode outside of a method */
status = acpi_ds_exec_end_op(walk_state);
return_ACPI_STATUS(status);
}
#endif
#endif
return_ACPI_STATUS(AE_OK);
}
......
......@@ -424,8 +424,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Status Register */
status =
acpi_read(&status_reg,
&gpe_register_info->status_address);
acpi_hw_read(&status_reg,
&gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
......@@ -433,8 +433,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list)
/* Read the Enable Register */
status =
acpi_read(&enable_reg,
&gpe_register_info->enable_address);
acpi_hw_read(&enable_reg,
&gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
......
......@@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
/* Disable all GPEs within this register */
status = acpi_write(0x00, &this_register->enable_address);
status = acpi_hw_write(0x00, &this_register->enable_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
/* Clear any pending GPE events within this register */
status = acpi_write(0xFF, &this_register->status_address);
status = acpi_hw_write(0xFF, &this_register->status_address);
if (ACPI_FAILURE(status)) {
goto error_exit;
}
......
......@@ -50,8 +50,6 @@
ACPI_MODULE_NAME("evrgnini")
/* Local prototypes */
static u8 acpi_ev_match_pci_root_bridge(char *id);
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
/*******************************************************************************
......@@ -330,37 +328,6 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_match_pci_root_bridge
*
* PARAMETERS: Id - The HID/CID in string format
*
* RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
*
* DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
*
******************************************************************************/
static u8 acpi_ev_match_pci_root_bridge(char *id)
{
/*
* Check if this is a PCI root.
* ACPI 3.0+: check for a PCI Express root also.
*/
if (!(ACPI_STRNCMP(id,
PCI_ROOT_HID_STRING,
sizeof(PCI_ROOT_HID_STRING))) ||
!(ACPI_STRNCMP(id,
PCI_EXPRESS_ROOT_HID_STRING,
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
return (TRUE);
}
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ev_is_pci_root_bridge
......@@ -377,9 +344,10 @@ static u8 acpi_ev_match_pci_root_bridge(char *id)
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
{
acpi_status status;
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
struct acpica_device_id *hid;
struct acpica_device_id_list *cid;
u32 i;
u8 match;
/* Get the _HID and check for a PCI Root Bridge */
......@@ -388,7 +356,10 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
return (FALSE);
}
if (acpi_ev_match_pci_root_bridge(hid.value)) {
match = acpi_ut_is_pci_root_bridge(hid->string);
ACPI_FREE(hid);
if (match) {
return (TRUE);
}
......@@ -402,7 +373,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
/* Check all _CIDs in the returned list */
for (i = 0; i < cid->count; i++) {
if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) {
if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) {
ACPI_FREE(cid);
return (TRUE);
}
......
......@@ -110,8 +110,15 @@ acpi_ex_add_table(u32 table_index,
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(obj_desc);
*ddb_handle = NULL;
return_ACPI_STATUS(status);
}
/* Execute any module-level code that was found in the table */
acpi_ex_exit_interpreter();
acpi_ns_exec_module_code_list();
acpi_ex_enter_interpreter();
return_ACPI_STATUS(status);
}
......
......@@ -418,9 +418,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
case ACPI_EXD_REFERENCE:
acpi_ex_out_string("Class Name",
(char *)
acpi_ut_get_reference_name
(obj_desc));
ACPI_CAST_PTR(char,
acpi_ut_get_reference_name
(obj_desc)));
acpi_ex_dump_reference_obj(obj_desc);
break;
......
......@@ -72,6 +72,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
union acpi_operand_object *buffer_desc;
acpi_size length;
void *buffer;
u32 function;
ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc);
......@@ -97,13 +98,27 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS)) {
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus read. We must create a buffer to hold the data
* and directly access the region handler.
* This is an SMBus or IPMI read. We must create a buffer to hold
* the data and then directly access the region handler.
*
* Note: Smbus protocol value is passed in upper 16-bits of Function
*/
buffer_desc =
acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_READ | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_READ;
}
buffer_desc = acpi_ut_create_buffer_object(length);
if (!buffer_desc) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
......@@ -112,16 +127,13 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
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
*/
/* Call the region handler for the read */
status = acpi_ex_access_region(obj_desc, 0,
ACPI_CAST_PTR(acpi_integer,
buffer_desc->
buffer.pointer),
ACPI_READ | (obj_desc->field.
attribute << 16));
function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
goto exit;
}
......@@ -212,6 +224,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
u32 length;
void *buffer;
union acpi_operand_object *buffer_desc;
u32 function;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc);
......@@ -234,39 +247,56 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
}
} else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) &&
(obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS)) {
ACPI_ADR_SPACE_SMBUS
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
* This is an SMBus write. We will bypass the entire field mechanism
* and handoff the buffer directly to the handler.
* This is an SMBus or IPMI write. We will bypass the entire field
* mechanism and handoff the buffer directly to the handler. For
* these address spaces, the buffer is bi-directional; on a write,
* return data is returned in the same buffer.
*
* Source must be a buffer of sufficient size:
* ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE.
*
* Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE).
* Note: SMBus protocol type is passed in upper 16-bits of Function
*/
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
"SMBus write requires Buffer, found type %s",
"SMBus or IPMI write requires Buffer, found type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) {
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
length = ACPI_SMBUS_BUFFER_SIZE;
function =
ACPI_WRITE | (obj_desc->field.attribute << 16);
} else { /* IPMI */
length = ACPI_IPMI_BUFFER_SIZE;
function = ACPI_WRITE;
}
if (source_desc->buffer.length < length) {
ACPI_ERROR((AE_INFO,
"SMBus write requires Buffer of length %X, found length %X",
ACPI_SMBUS_BUFFER_SIZE,
source_desc->buffer.length));
"SMBus or IPMI write requires Buffer of length %X, found length %X",
length, source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
}
buffer_desc =
acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE);
/* Create the bi-directional buffer */
buffer_desc = acpi_ut_create_buffer_object(length);
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);
ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length);
/* Lock entire transaction if requested */
......@@ -275,12 +305,10 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
/*
* 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));
function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
*result_desc = buffer_desc;
......
......@@ -120,12 +120,13 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
}
/*
* Exit now for SMBus address space, it has a non-linear address space
* Exit now for SMBus or IPMI address space, it has a non-linear address space
* and the request cannot be directly validated
*/
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) {
if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
/* SMBus has a non-linear address space */
/* SMBus or IPMI has a non-linear address space */
return_ACPI_STATUS(AE_OK);
}
......
......@@ -358,50 +358,67 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base)
*
* FUNCTION: acpi_ex_eisa_id_to_string
*
* PARAMETERS: numeric_id - EISA ID to be converted
* PARAMETERS: compressed_id - EISAID to be converted
* out_string - Where to put the converted string (8 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert a numeric EISA ID to string representation
* DESCRIPTION: Convert a numeric EISAID to string representation. Return
* buffer must be large enough to hold the string. The string
* returned is always exactly of length ACPI_EISAID_STRING_SIZE
* (includes null terminator). The EISAID is always 32 bits.
*
******************************************************************************/
void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string)
void acpi_ex_eisa_id_to_string(char *out_string, acpi_integer compressed_id)
{
u32 eisa_id;
u32 swapped_id;
ACPI_FUNCTION_ENTRY();
/* The EISAID should be a 32-bit integer */
if (compressed_id > ACPI_UINT32_MAX) {
ACPI_WARNING((AE_INFO,
"Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
ACPI_FORMAT_UINT64(compressed_id)));
}
/* Swap ID to big-endian to get contiguous bits */
eisa_id = acpi_ut_dword_byte_swap(numeric_id);
swapped_id = acpi_ut_dword_byte_swap((u32)compressed_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);
/* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */
out_string[0] =
(char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F));
out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F));
out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F));
out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 12);
out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 8);
out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 4);
out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 0);
out_string[7] = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_unsigned_integer_to_string
* FUNCTION: acpi_ex_integer_to_string
*
* PARAMETERS: Value - Value to be converted
* out_string - Where to put the converted string (8 bytes)
* PARAMETERS: out_string - Where to put the converted string. At least
* 21 bytes are needed to hold the largest
* possible 64-bit integer.
* Value - Value to be converted
*
* RETURN: None, string
*
* DESCRIPTION: Convert a number to string representation. Assumes string
* buffer is large enough to hold the string.
* DESCRIPTION: Convert a 64-bit integer to decimal string representation.
* Assumes string buffer is large enough to hold the string. The
* largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1).
*
******************************************************************************/
void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string)
void acpi_ex_integer_to_string(char *out_string, acpi_integer value)
{
u32 count;
u32 digits_needed;
......
......@@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Get current value of the enable register that contains this GPE */
status = acpi_read(&enable_mask, &gpe_register_info->enable_address);
status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info)
/* Write the updated enable mask */
status = acpi_write(enable_mask, &gpe_register_info->enable_address);
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
......@@ -130,8 +130,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info)
/* Write the entire GPE (runtime) enable register */
status = acpi_write(gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
status = acpi_hw_write(gpe_register_info->enable_for_run,
&gpe_register_info->enable_address);
return (status);
}
......@@ -163,8 +163,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info)
* Write a one to the appropriate bit in the status register to
* clear this GPE.
*/
status = acpi_write(register_bit,
&gpe_event_info->register_info->status_address);
status = acpi_hw_write(register_bit,
&gpe_event_info->register_info->status_address);
return (status);
}
......@@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info,
/* GPE currently active (status bit == 1)? */
status = acpi_read(&in_byte, &gpe_register_info->status_address);
status = acpi_hw_read(&in_byte, &gpe_register_info->status_address);
if (ACPI_FAILURE(status)) {
goto unlock_and_exit;
}
......@@ -266,8 +266,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Disable all GPEs in this register */
status =
acpi_write(0x00,
&gpe_block->register_info[i].enable_address);
acpi_hw_write(0x00,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -303,8 +303,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Clear status on all GPEs in this register */
status =
acpi_write(0xFF,
&gpe_block->register_info[i].status_address);
acpi_hw_write(0xFF,
&gpe_block->register_info[i].status_address);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Enable all "runtime" GPEs in this register */
status = acpi_write(gpe_block->register_info[i].enable_for_run,
&gpe_block->register_info[i].
enable_address);
status =
acpi_hw_write(gpe_block->register_info[i].enable_for_run,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
/* Enable all "wake" GPEs in this register */
status = acpi_write(gpe_block->register_info[i].enable_for_wake,
&gpe_block->register_info[i].
enable_address);
status =
acpi_hw_write(gpe_block->register_info[i].enable_for_wake,
&gpe_block->register_info[i].enable_address);
if (ACPI_FAILURE(status)) {
return (status);
}
......
......@@ -62,6 +62,184 @@ acpi_hw_write_multiple(u32 value,
struct acpi_generic_address *register_a,
struct acpi_generic_address *register_b);
/******************************************************************************
*
* FUNCTION: acpi_hw_validate_register
*
* PARAMETERS: Reg - GAS register structure
* max_bit_width - Max bit_width supported (32 or 64)
* Address - Pointer to where the gas->address
* is returned
*
* RETURN: Status
*
* DESCRIPTION: Validate the contents of a GAS register. Checks the GAS
* pointer, Address, space_id, bit_width, and bit_offset.
*
******************************************************************************/
acpi_status
acpi_hw_validate_register(struct acpi_generic_address *reg,
u8 max_bit_width, u64 *address)
{
/* Must have a valid pointer to a GAS structure */
if (!reg) {
return (AE_BAD_PARAMETER);
}
/*
* Copy the target address. This handles possible alignment issues.
* Address must not be null. A null address also indicates an optional
* ACPI register that is not supported, so no error message.
*/
ACPI_MOVE_64_TO_64(address, &reg->address);
if (!(*address)) {
return (AE_BAD_ADDRESS);
}
/* Validate the space_iD */
if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
(reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
ACPI_ERROR((AE_INFO,
"Unsupported address space: 0x%X", reg->space_id));
return (AE_SUPPORT);
}
/* Validate the bit_width */
if ((reg->bit_width != 8) &&
(reg->bit_width != 16) &&
(reg->bit_width != 32) && (reg->bit_width != max_bit_width)) {
ACPI_ERROR((AE_INFO,
"Unsupported register bit width: 0x%X",
reg->bit_width));
return (AE_SUPPORT);
}
/* Validate the bit_offset. Just a warning for now. */
if (reg->bit_offset != 0) {
ACPI_WARNING((AE_INFO,
"Unsupported register bit offset: 0x%X",
reg->bit_offset));
}
return (AE_OK);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_read
*
* PARAMETERS: Value - Where the value is returned
* Reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Read from either memory or IO space. This is a 32-bit max
* version of acpi_read, used internally since the overhead of
* 64-bit values is not needed.
*
* LIMITATIONS: <These limitations also apply to acpi_hw_write>
* bit_width must be exactly 8, 16, or 32.
* space_iD must be system_memory or system_iO.
* bit_offset and access_width are currently ignored, as there has
* not been a need to implement these.
*
******************************************************************************/
acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg)
{
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(hw_read);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Initialize entire 32-bit return value to zero */
*value = 0;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, value, reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_read_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
/******************************************************************************
*
* FUNCTION: acpi_hw_write
*
* PARAMETERS: Value - Value to be written
* Reg - GAS register structure
*
* RETURN: Status
*
* DESCRIPTION: Write to either memory or IO space. This is a 32-bit max
* version of acpi_write, used internally since the overhead of
* 64-bit values is not needed.
*
******************************************************************************/
acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg)
{
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(hw_write);
/* Validate contents of the GAS register */
status = acpi_hw_validate_register(reg, 32, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, value, reg->bit_width);
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_write_port((acpi_io_address)
address, value, reg->bit_width);
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, reg->bit_width, ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
}
/*******************************************************************************
*
* FUNCTION: acpi_hw_clear_acpi_status
......@@ -152,15 +330,16 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control)
ACPI_FUNCTION_TRACE(hw_write_pm1_control);
status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
status =
acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (acpi_gbl_FADT.xpm1b_control_block.address) {
status =
acpi_write(pm1b_control,
&acpi_gbl_FADT.xpm1b_control_block);
acpi_hw_write(pm1b_control,
&acpi_gbl_FADT.xpm1b_control_block);
}
return_ACPI_STATUS(status);
}
......@@ -218,12 +397,13 @@ acpi_hw_register_read(u32 register_id, u32 * return_value)
case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */
status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block);
status =
acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block);
status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
......@@ -340,7 +520,8 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
* as per the ACPI spec.
*/
status =
acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block);
acpi_hw_read(&read_value,
&acpi_gbl_FADT.xpm2_control_block);
if (ACPI_FAILURE(status)) {
goto exit;
}
......@@ -350,12 +531,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value)
ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS,
read_value);
status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block);
status =
acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block);
break;
case ACPI_REGISTER_PM_TIMER: /* 32-bit access */
status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block);
status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block);
break;
case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */
......@@ -401,7 +583,7 @@ acpi_hw_read_multiple(u32 *value,
/* The first register is always required */
status = acpi_read(&value_a, register_a);
status = acpi_hw_read(&value_a, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -409,7 +591,7 @@ acpi_hw_read_multiple(u32 *value,
/* Second register is optional */
if (register_b->address) {
status = acpi_read(&value_b, register_b);
status = acpi_hw_read(&value_b, register_b);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -452,7 +634,7 @@ acpi_hw_write_multiple(u32 value,
/* The first register is always required */
status = acpi_write(value, register_a);
status = acpi_hw_write(value, register_a);
if (ACPI_FAILURE(status)) {
return (status);
}
......@@ -470,7 +652,7 @@ acpi_hw_write_multiple(u32 value,
* and writes have no side effects"
*/
if (register_b->address) {
status = acpi_write(value, register_b);
status = acpi_hw_write(value, register_b);
}
return (status);
......
......@@ -100,7 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks)
}
status =
acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block);
acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block);
return_ACPI_STATUS(status);
}
......
......@@ -78,9 +78,22 @@ acpi_status acpi_reset(void)
return_ACPI_STATUS(AE_NOT_EXIST);
}
/* Write the reset value to the reset register */
if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
/*
* For I/O space, write directly to the OSL. This bypasses the port
* validation mechanism, which may block a valid write to the reset
* register.
*/
status =
acpi_os_write_port((acpi_io_address) reset_reg->address,
acpi_gbl_FADT.reset_value,
reset_reg->bit_width);
} else {
/* Write the reset value to the reset register */
status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg);
}
status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg);
return_ACPI_STATUS(status);
}
......@@ -97,67 +110,92 @@ ACPI_EXPORT_SYMBOL(acpi_reset)
*
* DESCRIPTION: Read from either memory or IO space.
*
* LIMITATIONS: <These limitations also apply to acpi_write>
* bit_width must be exactly 8, 16, 32, or 64.
* space_iD must be system_memory or system_iO.
* bit_offset and access_width are currently ignored, as there has
* not been a need to implement these.
*
******************************************************************************/
acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg)
acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg)
{
u32 value;
u32 width;
u64 address;
acpi_status status;
ACPI_FUNCTION_NAME(acpi_read);
/*
* Must have a valid pointer to a GAS structure, and a non-zero address
* within.
*/
if (!reg) {
if (!return_value) {
return (AE_BAD_PARAMETER);
}
/* Get a local copy of the address. Handles possible alignment issues */
/* Validate contents of the GAS register. Allow 64-bit transfers */
ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_BAD_ADDRESS);
status = acpi_hw_validate_register(reg, 64, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Supported widths are 8/16/32 */
width = reg->bit_width;
if ((width != 8) && (width != 16) && (width != 32)) {
return (AE_SUPPORT);
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/* Initialize entire 32-bit return value to zero */
/* Initialize entire 64-bit return value to zero */
*value = 0;
*return_value = 0;
value = 0;
/*
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_read_memory((acpi_physical_address)
address, &value, width);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = value;
status = acpi_os_read_memory((acpi_physical_address) address,
value, width);
break;
if (reg->bit_width == 64) {
case ACPI_ADR_SPACE_SYSTEM_IO:
/* Read the top 32 bits */
status =
acpi_hw_read_port((acpi_io_address) address, value, width);
break;
status = acpi_os_read_memory((acpi_physical_address)
(address + 4), &value, 32);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value |= ((u64)value << 32);
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
default:
ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", reg->space_id));
return (AE_BAD_PARAMETER);
status = acpi_hw_read_port((acpi_io_address)
address, &value, width);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value = value;
if (reg->bit_width == 64) {
/* Read the top 32 bits */
status = acpi_hw_read_port((acpi_io_address)
(address + 4), &value, 32);
if (ACPI_FAILURE(status)) {
return (status);
}
*return_value |= ((u64)value << 32);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Read: %8.8X width %2d from %8.8X%8.8X (%s)\n",
*value, width, ACPI_FORMAT_UINT64(address),
"Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n",
ACPI_FORMAT_UINT64(*return_value), reg->bit_width,
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
......@@ -169,7 +207,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
*
* FUNCTION: acpi_write
*
* PARAMETERS: Value - To be written
* PARAMETERS: Value - Value to be written
* Reg - GAS register structure
*
* RETURN: Status
......@@ -177,7 +215,7 @@ ACPI_EXPORT_SYMBOL(acpi_read)
* DESCRIPTION: Write to either memory or IO space.
*
******************************************************************************/
acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
acpi_status acpi_write(u64 value, struct acpi_generic_address *reg)
{
u32 width;
u64 address;
......@@ -185,54 +223,61 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg)
ACPI_FUNCTION_NAME(acpi_write);
/*
* Must have a valid pointer to a GAS structure, and a non-zero address
* within.
*/
if (!reg) {
return (AE_BAD_PARAMETER);
}
/* Get a local copy of the address. Handles possible alignment issues */
/* Validate contents of the GAS register. Allow 64-bit transfers */
ACPI_MOVE_64_TO_64(&address, &reg->address);
if (!address) {
return (AE_BAD_ADDRESS);
status = acpi_hw_validate_register(reg, 64, &address);
if (ACPI_FAILURE(status)) {
return (status);
}
/* Supported widths are 8/16/32 */
width = reg->bit_width;
if ((width != 8) && (width != 16) && (width != 32)) {
return (AE_SUPPORT);
if (width == 64) {
width = 32; /* Break into two 32-bit transfers */
}
/*
* Two address spaces supported: Memory or IO.
* PCI_Config is not supported here because the GAS struct is insufficient
* Two address spaces supported: Memory or IO. PCI_Config is
* not supported here because the GAS structure is insufficient
*/
switch (reg->space_id) {
case ACPI_ADR_SPACE_SYSTEM_MEMORY:
status = acpi_os_write_memory((acpi_physical_address) address,
value, width);
break;
if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
status = acpi_os_write_memory((acpi_physical_address)
address, ACPI_LODWORD(value),
width);
if (ACPI_FAILURE(status)) {
return (status);
}
case ACPI_ADR_SPACE_SYSTEM_IO:
if (reg->bit_width == 64) {
status = acpi_os_write_memory((acpi_physical_address)
(address + 4),
ACPI_HIDWORD(value), 32);
if (ACPI_FAILURE(status)) {
return (status);
}
}
} else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */
status = acpi_hw_write_port((acpi_io_address) address, value,
status = acpi_hw_write_port((acpi_io_address)
address, ACPI_LODWORD(value),
width);
break;
if (ACPI_FAILURE(status)) {
return (status);
}
default:
ACPI_ERROR((AE_INFO,
"Unsupported address space: %X", reg->space_id));
return (AE_BAD_PARAMETER);
if (reg->bit_width == 64) {
status = acpi_hw_write_port((acpi_io_address)
(address + 4),
ACPI_HIDWORD(value), 32);
if (ACPI_FAILURE(status)) {
return (status);
}
}
}
ACPI_DEBUG_PRINT((ACPI_DB_IO,
"Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n",
value, width, ACPI_FORMAT_UINT64(address),
"Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n",
ACPI_FORMAT_UINT64(value), reg->bit_width,
ACPI_FORMAT_UINT64(address),
acpi_ut_get_region_name(reg->space_id)));
return (status);
......
......@@ -96,17 +96,68 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name)
*
* RETURN: None
*
* DESCRIPTION: Delete a namespace node
* DESCRIPTION: Delete a namespace node. All node deletions must come through
* here. Detaches any attached objects, including any attached
* data. If a handler is associated with attached data, it is
* invoked before the node is deleted.
*
******************************************************************************/
void acpi_ns_delete_node(struct acpi_namespace_node *node)
{
union acpi_operand_object *obj_desc;
ACPI_FUNCTION_NAME(ns_delete_node);
/* Detach an object if there is one */
acpi_ns_detach_object(node);
/*
* Delete an attached data object if present (an object that was created
* and attached via acpi_attach_data). Note: After any normal object is
* detached above, the only possible remaining object is a data object.
*/
obj_desc = node->object;
if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) {
/* Invoke the attached data deletion handler if present */
if (obj_desc->data.handler) {
obj_desc->data.handler(node, obj_desc->data.pointer);
}
acpi_ut_remove_reference(obj_desc);
}
/* Now we can delete the node */
(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
node, acpi_gbl_current_node_count));
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_remove_node
*
* PARAMETERS: Node - Node to be removed/deleted
*
* RETURN: None
*
* DESCRIPTION: Remove (unlink) and delete a namespace node
*
******************************************************************************/
void acpi_ns_remove_node(struct acpi_namespace_node *node)
{
struct acpi_namespace_node *parent_node;
struct acpi_namespace_node *prev_node;
struct acpi_namespace_node *next_node;
ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node);
ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node);
parent_node = acpi_ns_get_parent_node(node);
......@@ -142,12 +193,9 @@ void acpi_ns_delete_node(struct acpi_namespace_node *node)
}
}
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
/* Detach an object if there is one, then delete the node */
/* Delete the node and any attached objects */
acpi_ns_detach_object(node);
(void)acpi_os_release_object(acpi_gbl_namespace_cache, node);
acpi_ns_delete_node(node);
return_VOID;
}
......@@ -273,25 +321,11 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node)
parent_node, child_node));
}
/* Now we can free this child object */
ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++);
ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
"Object %p, Remaining %X\n", child_node,
acpi_gbl_current_node_count));
/* Detach an object if there is one, then free the child node */
acpi_ns_detach_object(child_node);
/* Now we can delete the node */
(void)acpi_os_release_object(acpi_gbl_namespace_cache,
child_node);
/* And move on to the next child in the list */
/*
* Delete this child node and move on to the next child in the list.
* No need to unlink the node since we are deleting the entire branch.
*/
acpi_ns_delete_node(child_node);
child_node = next_node;
} while (!(flags & ANOBJ_END_OF_PEER_LIST));
......@@ -433,7 +467,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id)
if (deletion_node) {
acpi_ns_delete_children(deletion_node);
acpi_ns_delete_node(deletion_node);
acpi_ns_remove_node(deletion_node);
deletion_node = NULL;
}
......
......@@ -70,7 +70,6 @@ static acpi_status
acpi_ns_dump_one_device(acpi_handle obj_handle,
u32 level, void *context, void **return_value)
{
struct acpi_buffer buffer;
struct acpi_device_info *info;
acpi_status status;
u32 i;
......@@ -80,17 +79,15 @@ acpi_ns_dump_one_device(acpi_handle obj_handle,
status =
acpi_ns_dump_one_object(obj_handle, level, context, return_value);
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_get_object_info(obj_handle, &buffer);
status = acpi_get_object_info(obj_handle, &info);
if (ACPI_SUCCESS(status)) {
info = buffer.pointer;
for (i = 0; i < level; i++) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " "));
}
ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES,
" HID: %s, ADR: %8.8X%8.8X, Status: %X\n",
info->hardware_id.value,
info->hardware_id.string,
ACPI_FORMAT_UINT64(info->address),
info->current_status));
ACPI_FREE(info);
......
......@@ -50,6 +50,11 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nseval")
/* Local prototypes */
static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info);
/*******************************************************************************
*
* FUNCTION: acpi_ns_evaluate
......@@ -76,6 +81,7 @@ ACPI_MODULE_NAME("nseval")
* MUTEX: Locks interpreter
*
******************************************************************************/
acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
{
acpi_status status;
......@@ -276,3 +282,134 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
*/
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_exec_module_code_list
*
* PARAMETERS: None
*
* RETURN: None. Exceptions during method execution are ignored, since
* we cannot abort a table load.
*
* DESCRIPTION: Execute all elements of the global module-level code list.
* Each element is executed as a single control method.
*
******************************************************************************/
void acpi_ns_exec_module_code_list(void)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
struct acpi_evaluate_info *info;
u32 method_count = 0;
ACPI_FUNCTION_TRACE(ns_exec_module_code_list);
/* Exit now if the list is empty */
next = acpi_gbl_module_code_list;
if (!next) {
return_VOID;
}
/* Allocate the evaluation information block */
info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info));
if (!info) {
return_VOID;
}
/* Walk the list, executing each "method" */
while (next) {
prev = next;
next = next->method.mutex;
/* Clear the link field and execute the method */
prev->method.mutex = NULL;
acpi_ns_exec_module_code(prev, info);
method_count++;
/* Delete the (temporary) method object */
acpi_ut_remove_reference(prev);
}
ACPI_INFO((AE_INFO,
"Executed %u blocks of module-level executable AML code",
method_count));
ACPI_FREE(info);
acpi_gbl_module_code_list = NULL;
return_VOID;
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_exec_module_code
*
* PARAMETERS: method_obj - Object container for the module-level code
* Info - Info block for method evaluation
*
* RETURN: None. Exceptions during method execution are ignored, since
* we cannot abort a table load.
*
* DESCRIPTION: Execute a control method containing a block of module-level
* executable AML code. The control method is temporarily
* installed to the root node, then evaluated.
*
******************************************************************************/
static void
acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
struct acpi_evaluate_info *info)
{
union acpi_operand_object *root_obj;
acpi_status status;
ACPI_FUNCTION_TRACE(ns_exec_module_code);
/* Initialize the evaluation information block */
ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
info->prefix_node = acpi_gbl_root_node;
/*
* Get the currently attached root object. Add a reference, because the
* ref count will be decreased when the method object is installed to
* the root node.
*/
root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
acpi_ut_add_reference(root_obj);
/* Install the method (module-level code) in the root node */
status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
ACPI_TYPE_METHOD);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Execute the root node as a control method */
status = acpi_ns_evaluate(info);
ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
method_obj->method.aml_start));
/* Detach the temporary method object */
acpi_ns_detach_object(acpi_gbl_root_node);
/* Restore the original root object */
status =
acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
ACPI_TYPE_DEVICE);
exit:
acpi_ut_remove_reference(root_obj);
return_VOID;
}
......@@ -170,6 +170,21 @@ acpi_status acpi_ns_initialize_devices(void)
goto error_exit;
}
/*
* Execute the "global" _INI method that may appear at the root. This
* support is provided for Windows compatibility (Vista+) and is not
* part of the ACPI specification.
*/
info.evaluate_info->prefix_node = acpi_gbl_root_node;
info.evaluate_info->pathname = METHOD_NAME__INI;
info.evaluate_info->parameters = NULL;
info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE;
status = acpi_ns_evaluate(info.evaluate_info);
if (ACPI_SUCCESS(status)) {
info.num_INI++;
}
/* Walk namespace to execute all _INIs on present devices */
status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
......
......@@ -270,8 +270,7 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle)
/* Now delete the starting object, and we are done */
acpi_ns_delete_node(child_handle);
acpi_ns_remove_node(child_handle);
return_ACPI_STATUS(AE_OK);
}
......
此差异已折叠。
/******************************************************************************
*
* Module Name: nsrepair - Repair for objects returned by predefined methods
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2009, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acnamesp.h"
#include "acpredef.h"
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsrepair")
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_object
*
* PARAMETERS: Data - Pointer to validation data structure
* expected_btypes - Object types expected
* package_index - Index of object within parent package (if
* applicable - ACPI_NOT_PACKAGE_ELEMENT
* otherwise)
* return_object_ptr - Pointer to the object returned from the
* evaluation of a method or object
*
* RETURN: Status. AE_OK if repair was successful.
*
* DESCRIPTION: Attempt to repair/convert a return object of a type that was
* not expected.
*
******************************************************************************/
acpi_status
acpi_ns_repair_object(struct acpi_predefined_data *data,
u32 expected_btypes,
u32 package_index,
union acpi_operand_object **return_object_ptr)
{
union acpi_operand_object *return_object = *return_object_ptr;
union acpi_operand_object *new_object;
acpi_size length;
switch (return_object->common.type) {
case ACPI_TYPE_BUFFER:
/* Does the method/object legally return a string? */
if (!(expected_btypes & ACPI_RTYPE_STRING)) {
return (AE_AML_OPERAND_TYPE);
}
/*
* Have a Buffer, expected a String, convert. Use a to_string
* conversion, no transform performed on the buffer data. The best
* example of this is the _BIF method, where the string data from
* the battery is often (incorrectly) returned as buffer object(s).
*/
length = 0;
while ((length < return_object->buffer.length) &&
(return_object->buffer.pointer[length])) {
length++;
}
/* Allocate a new string object */
new_object = acpi_ut_create_string_object(length);
if (!new_object) {
return (AE_NO_MEMORY);
}
/*
* Copy the raw buffer data with no transform. String is already NULL
* terminated at Length+1.
*/
ACPI_MEMCPY(new_object->string.pointer,
return_object->buffer.pointer, length);
/*
* If the original object is a package element, we need to:
* 1. Set the reference count of the new object to match the
* reference count of the old object.
* 2. Decrement the reference count of the original object.
*/
if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
new_object->common.reference_count =
return_object->common.reference_count;
if (return_object->common.reference_count > 1) {
return_object->common.reference_count--;
}
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
data->node_flags,
"Converted Buffer to expected String at index %u",
package_index));
} else {
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
data->node_flags,
"Converted Buffer to expected String"));
}
/* Delete old object, install the new return object */
acpi_ut_remove_reference(return_object);
*return_object_ptr = new_object;
data->flags |= ACPI_OBJECT_REPAIRED;
return (AE_OK);
default:
break;
}
return (AE_AML_OPERAND_TYPE);
}
/*******************************************************************************
*
* FUNCTION: acpi_ns_repair_package_list
*
* PARAMETERS: Data - Pointer to validation data structure
* obj_desc_ptr - Pointer to the object to repair. The new
* package object is returned here,
* overwriting the old object.
*
* RETURN: Status, new object in *obj_desc_ptr
*
* DESCRIPTION: Repair a common problem with objects that are defined to return
* a variable-length Package of Packages. If the variable-length
* is one, some BIOS code mistakenly simply declares a single
* Package instead of a Package with one sub-Package. This
* function attempts to repair this error by wrapping a Package
* object around the original Package, creating the correct
* Package with one sub-Package.
*
* Names that can be repaired in this manner include:
* _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS
*
******************************************************************************/
acpi_status
acpi_ns_repair_package_list(struct acpi_predefined_data *data,
union acpi_operand_object **obj_desc_ptr)
{
union acpi_operand_object *pkg_obj_desc;
/*
* Create the new outer package and populate it. The new package will
* have a single element, the lone subpackage.
*/
pkg_obj_desc = acpi_ut_create_package_object(1);
if (!pkg_obj_desc) {
return (AE_NO_MEMORY);
}
pkg_obj_desc->package.elements[0] = *obj_desc_ptr;
/* Return the new object in the object pointer */
*obj_desc_ptr = pkg_obj_desc;
data->flags |= ACPI_OBJECT_REPAIRED;
ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
"Incorrectly formed Package, attempting repair"));
return (AE_OK);
}
......@@ -88,7 +88,8 @@ acpi_ns_report_error(const char *module_name,
/* There is a non-ascii character in the name */
ACPI_MOVE_32_TO_32(&bad_name, internal_name);
ACPI_MOVE_32_TO_32(&bad_name,
ACPI_CAST_PTR(u32, internal_name));
acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
} else {
/* Convert path to external format */
......@@ -836,7 +837,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
acpi_status status;
char *internal_path;
ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname);
ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
if (!pathname) {
*return_node = prefix_node;
......
......@@ -535,10 +535,11 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
acpi_status status;
struct acpi_namespace_node *node;
u32 flags;
struct acpica_device_id hid;
struct acpi_compatible_id_list *cid;
struct acpica_device_id *hid;
struct acpica_device_id_list *cid;
u32 i;
int found;
u8 found;
int no_match;
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
......@@ -582,10 +583,14 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
return (AE_CTRL_DEPTH);
}
if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) {
/* Get the list of Compatible IDs */
no_match = ACPI_STRCMP(hid->string, info->hid);
ACPI_FREE(hid);
if (no_match) {
/*
* HID does not match, attempt match within the
* list of Compatible IDs (CIDs)
*/
status = acpi_ut_execute_CID(node, &cid);
if (status == AE_NOT_FOUND) {
return (AE_OK);
......@@ -597,10 +602,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
found = 0;
for (i = 0; i < cid->count; i++) {
if (ACPI_STRNCMP(cid->id[i].value, info->hid,
sizeof(struct
acpi_compatible_id)) ==
0) {
if (ACPI_STRCMP(cid->ids[i].string, info->hid)
== 0) {
found = 1;
break;
}
......
......@@ -51,6 +51,11 @@
#define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("nsxfname")
/* Local prototypes */
static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
struct acpica_device_id *source,
char *string_area);
/******************************************************************************
*
* FUNCTION: acpi_get_handle
......@@ -68,6 +73,7 @@ ACPI_MODULE_NAME("nsxfname")
* namespace handle.
*
******************************************************************************/
acpi_status
acpi_get_handle(acpi_handle parent,
acpi_string pathname, acpi_handle * ret_handle)
......@@ -208,12 +214,40 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
ACPI_EXPORT_SYMBOL(acpi_get_name)
/******************************************************************************
*
* FUNCTION: acpi_ns_copy_device_id
*
* PARAMETERS: Dest - Pointer to the destination DEVICE_ID
* Source - Pointer to the source DEVICE_ID
* string_area - Pointer to where to copy the dest string
*
* RETURN: Pointer to the next string area
*
* DESCRIPTION: Copy a single DEVICE_ID, including the string data.
*
******************************************************************************/
static char *acpi_ns_copy_device_id(struct acpica_device_id *dest,
struct acpica_device_id *source,
char *string_area)
{
/* Create the destination DEVICE_ID */
dest->string = string_area;
dest->length = source->length;
/* Copy actual string and return a pointer to the next string area */
ACPI_MEMCPY(string_area, source->string, source->length);
return (string_area + source->length);
}
/******************************************************************************
*
* FUNCTION: acpi_get_object_info
*
* PARAMETERS: Handle - Object Handle
* Buffer - Where the info is returned
* PARAMETERS: Handle - Object Handle
* return_buffer - Where the info is returned
*
* RETURN: Status
*
......@@ -221,33 +255,37 @@ ACPI_EXPORT_SYMBOL(acpi_get_name)
* namespace node and possibly by running several standard
* control methods (Such as in the case of a device.)
*
* For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
* _ADR, _sx_w, and _sx_d methods.
*
* Note: Allocates the return buffer, must be freed by the caller.
*
******************************************************************************/
acpi_status
acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
acpi_get_object_info(acpi_handle handle,
struct acpi_device_info **return_buffer)
{
acpi_status status;
struct acpi_namespace_node *node;
struct acpi_device_info *info;
struct acpi_device_info *return_info;
struct acpi_compatible_id_list *cid_list = NULL;
acpi_size size;
struct acpica_device_id_list *cid_list = NULL;
struct acpica_device_id *hid = NULL;
struct acpica_device_id *uid = NULL;
char *next_id_string;
acpi_object_type type;
acpi_name name;
u8 param_count = 0;
u8 valid = 0;
u32 info_size;
u32 i;
acpi_status status;
/* Parameter validation */
if (!handle || !buffer) {
if (!handle || !return_buffer) {
return (AE_BAD_PARAMETER);
}
status = acpi_ut_validate_buffer(buffer);
if (ACPI_FAILURE(status)) {
return (status);
}
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
......@@ -256,66 +294,91 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
node = acpi_ns_map_handle_to_node(handle);
if (!node) {
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
status = AE_BAD_PARAMETER;
goto cleanup;
return (AE_BAD_PARAMETER);
}
/* Init return structure */
size = sizeof(struct acpi_device_info);
/* Get the namespace node data while the namespace is locked */
info->type = node->type;
info->name = node->name.integer;
info->valid = 0;
info_size = sizeof(struct acpi_device_info);
type = node->type;
name = node->name.integer;
if (node->type == ACPI_TYPE_METHOD) {
info->param_count = node->object->method.param_count;
param_count = node->object->method.param_count;
}
status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE(status)) {
goto cleanup;
return (status);
}
/* If not a device, we are all done */
if (info->type == ACPI_TYPE_DEVICE) {
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Devices objects only:
* Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
* Get extra info for ACPI Device/Processor objects only:
* Run the Device _HID, _UID, and _CID methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and ran successfully.
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and run successfully.
*/
/* Execute the Device._HID method */
status = acpi_ut_execute_HID(node, &info->hardware_id);
status = acpi_ut_execute_HID(node, &hid);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_HID;
info_size += hid->length;
valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
status = acpi_ut_execute_UID(node, &info->unique_id);
status = acpi_ut_execute_UID(node, &uid);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_UID;
info_size += uid->length;
valid |= ACPI_VALID_UID;
}
/* Execute the Device._CID method */
status = acpi_ut_execute_CID(node, &cid_list);
if (ACPI_SUCCESS(status)) {
size += cid_list->size;
info->valid |= ACPI_VALID_CID;
/* Add size of CID strings and CID pointer array */
info_size +=
(cid_list->list_size -
sizeof(struct acpica_device_id_list));
valid |= ACPI_VALID_CID;
}
}
/*
* Now that we have the variable-length data, we can allocate the
* return buffer
*/
info = ACPI_ALLOCATE_ZEROED(info_size);
if (!info) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Get the fixed-length data */
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Device/Processor objects only:
* Run the _STA, _ADR and, sx_w, and _sx_d methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and run successfully.
*/
/* Execute the Device._STA method */
status = acpi_ut_execute_STA(node, &info->current_status);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_STA;
valid |= ACPI_VALID_STA;
}
/* Execute the Device._ADR method */
......@@ -323,36 +386,100 @@ acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer)
status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
&info->address);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_ADR;
valid |= ACPI_VALID_ADR;
}
/* Execute the Device._sx_w methods */
status = acpi_ut_execute_power_methods(node,
acpi_gbl_lowest_dstate_names,
ACPI_NUM_sx_w_METHODS,
info->lowest_dstates);
if (ACPI_SUCCESS(status)) {
valid |= ACPI_VALID_SXWS;
}
/* Execute the Device._sx_d methods */
status = acpi_ut_execute_sxds(node, info->highest_dstates);
status = acpi_ut_execute_power_methods(node,
acpi_gbl_highest_dstate_names,
ACPI_NUM_sx_d_METHODS,
info->highest_dstates);
if (ACPI_SUCCESS(status)) {
info->valid |= ACPI_VALID_SXDS;
valid |= ACPI_VALID_SXDS;
}
}
/* Validate/Allocate/Clear caller buffer */
/*
* Create a pointer to the string area of the return buffer.
* Point to the end of the base struct acpi_device_info structure.
*/
next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
if (cid_list) {
status = acpi_ut_initialize_buffer(buffer, size);
if (ACPI_FAILURE(status)) {
goto cleanup;
/* Point past the CID DEVICE_ID array */
next_id_string +=
((acpi_size) cid_list->count *
sizeof(struct acpica_device_id));
}
/* Populate the return buffer */
/*
* Copy the HID, UID, and CIDs to the return buffer. The variable-length
* strings are copied to the reserved area at the end of the buffer.
*
* For HID and CID, check if the ID is a PCI Root Bridge.
*/
if (hid) {
next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
hid, next_id_string);
if (acpi_ut_is_pci_root_bridge(hid->string)) {
info->flags |= ACPI_PCI_ROOT_BRIDGE;
}
}
return_info = buffer->pointer;
ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info));
if (uid) {
next_id_string = acpi_ns_copy_device_id(&info->unique_id,
uid, next_id_string);
}
if (cid_list) {
ACPI_MEMCPY(&return_info->compatibility_id, cid_list,
cid_list->size);
info->compatible_id_list.count = cid_list->count;
info->compatible_id_list.list_size = cid_list->list_size;
/* Copy each CID */
for (i = 0; i < cid_list->count; i++) {
next_id_string =
acpi_ns_copy_device_id(&info->compatible_id_list.
ids[i], &cid_list->ids[i],
next_id_string);
if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
info->flags |= ACPI_PCI_ROOT_BRIDGE;
}
}
}
/* Copy the fixed-length data */
info->info_size = info_size;
info->type = type;
info->name = name;
info->param_count = param_count;
info->valid = valid;
*return_buffer = info;
status = AE_OK;
cleanup:
ACPI_FREE(info);
if (hid) {
ACPI_FREE(hid);
}
if (uid) {
ACPI_FREE(uid);
}
if (cid_list) {
ACPI_FREE(cid_list);
}
......
......@@ -86,6 +86,9 @@ static acpi_status
acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, acpi_status status);
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
/*******************************************************************************
*
* FUNCTION: acpi_ps_get_aml_opcode
......@@ -390,6 +393,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
{
acpi_status status = AE_OK;
union acpi_parse_object *arg = NULL;
const struct acpi_opcode_info *op_info;
ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
......@@ -449,13 +453,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
INCREMENT_ARG_LIST(walk_state->arg_types);
}
/* Special processing for certain opcodes */
/* TBD (remove): Temporary mechanism to disable this code if needed */
#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) &&
/*
* Handle executable code at "module-level". This refers to
* executable opcodes that appear outside of any control method.
*/
if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
/*
* We want to skip If/Else/While constructs during Pass1 because we
......@@ -469,6 +471,23 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
case AML_ELSE_OP:
case AML_WHILE_OP:
/*
* Currently supported module-level opcodes are:
* IF/ELSE/WHILE. These appear to be the most common,
* and easiest to support since they open an AML
* package.
*/
if (walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1) {
acpi_ps_link_module_code(aml_op_start,
walk_state->
parser_state.
pkg_end -
aml_op_start,
walk_state->
owner_id);
}
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
"Pass1: Skipping an If/Else/While body\n"));
......@@ -480,10 +499,34 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
break;
default:
/*
* Check for an unsupported executable opcode at module
* level. We must be in PASS1, the parent must be a SCOPE,
* The opcode class must be EXECUTE, and the opcode must
* not be an argument to another opcode.
*/
if ((walk_state->pass_number ==
ACPI_IMODE_LOAD_PASS1)
&& (op->common.parent->common.aml_opcode ==
AML_SCOPE_OP)) {
op_info =
acpi_ps_get_opcode_info(op->common.
aml_opcode);
if ((op_info->class ==
AML_CLASS_EXECUTE) && (!arg)) {
ACPI_WARNING((AE_INFO,
"Detected an unsupported executable opcode "
"at module-level: [0x%.4X] at table offset 0x%.4X",
op->common.aml_opcode,
(u32)((aml_op_start - walk_state->parser_state.aml_start)
+ sizeof(struct acpi_table_header))));
}
}
break;
}
}
#endif
/* Special processing for certain opcodes */
switch (op->common.aml_opcode) {
case AML_METHOD_OP:
......@@ -551,6 +594,66 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_OK);
}
/*******************************************************************************
*
* FUNCTION: acpi_ps_link_module_code
*
* PARAMETERS: aml_start - Pointer to the AML
* aml_length - Length of executable AML
* owner_id - owner_id of module level code
*
* RETURN: None.
*
* DESCRIPTION: Wrap the module-level code with a method object and link the
* object to the global list. Note, the mutex field of the method
* object is used to link multiple module-level code objects.
*
******************************************************************************/
static void
acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
{
union acpi_operand_object *prev;
union acpi_operand_object *next;
union acpi_operand_object *method_obj;
/* Get the tail of the list */
prev = next = acpi_gbl_module_code_list;
while (next) {
prev = next;
next = next->method.mutex;
}
/*
* Insert the module level code into the list. Merge it if it is
* adjacent to the previous element.
*/
if (!prev ||
((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
/* Create, initialize, and link a new temporary method object */
method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
if (!method_obj) {
return;
}
method_obj->method.aml_start = aml_start;
method_obj->method.aml_length = aml_length;
method_obj->method.owner_id = owner_id;
method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
if (!prev) {
acpi_gbl_module_code_list = method_obj;
} else {
prev->method.mutex = method_obj;
}
} else {
prev->method.aml_length += aml_length;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ps_complete_op
......
......@@ -280,6 +280,10 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
goto cleanup;
}
if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) {
walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
}
/* Invoke an internal method if necessary */
if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
......
......@@ -49,6 +49,12 @@
ACPI_MODULE_NAME("tbutils")
/* Local prototypes */
static void acpi_tb_fix_string(char *string, acpi_size length);
static void
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
struct acpi_table_header *header);
static acpi_physical_address
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
......@@ -159,6 +165,59 @@ u8 acpi_tb_tables_loaded(void)
return (FALSE);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_fix_string
*
* PARAMETERS: String - String to be repaired
* Length - Maximum length
*
* RETURN: None
*
* DESCRIPTION: Replace every non-printable or non-ascii byte in the string
* with a question mark '?'.
*
******************************************************************************/
static void acpi_tb_fix_string(char *string, acpi_size length)
{
while (length && *string) {
if (!ACPI_IS_PRINT(*string)) {
*string = '?';
}
string++;
length--;
}
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_cleanup_table_header
*
* PARAMETERS: out_header - Where the cleaned header is returned
* Header - Input ACPI table header
*
* RETURN: Returns the cleaned header in out_header
*
* DESCRIPTION: Copy the table header and ensure that all "string" fields in
* the header consist of printable characters.
*
******************************************************************************/
static void
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
struct acpi_table_header *header)
{
ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header));
acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE);
acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE);
acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE);
}
/*******************************************************************************
*
* FUNCTION: acpi_tb_print_table_header
......@@ -176,6 +235,7 @@ void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header)
{
struct acpi_table_header local_header;
/*
* The reason that the Address is cast to a void pointer is so that we
......@@ -192,6 +252,11 @@ acpi_tb_print_table_header(acpi_physical_address address,
/* RSDP has no common fields */
ACPI_MEMCPY(local_header.oem_id,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->oem_id, ACPI_OEM_ID_SIZE);
acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)",
ACPI_CAST_PTR (void, address),
(ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
......@@ -200,18 +265,21 @@ acpi_tb_print_table_header(acpi_physical_address address,
header)->length : 20,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->revision,
ACPI_CAST_PTR(struct acpi_table_rsdp,
header)->oem_id));
local_header.oem_id));
} else {
/* Standard ACPI table with full common header */
acpi_tb_cleanup_table_header(&local_header, header);
ACPI_INFO((AE_INFO,
"%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)",
header->signature, ACPI_CAST_PTR (void, address),
header->length, header->revision, header->oem_id,
header->oem_table_id, header->oem_revision,
header->asl_compiler_id,
header->asl_compiler_revision));
local_header.signature, ACPI_CAST_PTR(void, address),
local_header.length, local_header.revision,
local_header.oem_id, local_header.oem_table_id,
local_header.oem_revision,
local_header.asl_compiler_id,
local_header.asl_compiler_revision));
}
}
......
此差异已折叠。
......@@ -90,7 +90,15 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = {
"\\_S5_"
};
const char *acpi_gbl_highest_dstate_names[4] = {
const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS] = {
"_S0W",
"_S1W",
"_S2W",
"_S3W",
"_S4W"
};
const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = {
"_S1D",
"_S2D",
"_S3D",
......@@ -351,6 +359,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
"SMBus",
"SystemCMOS",
"PCIBARTarget",
"IPMI",
"DataTable"
};
......@@ -798,6 +807,7 @@ acpi_status acpi_ut_init_globals(void)
/* Namespace */
acpi_gbl_module_code_list = NULL;
acpi_gbl_root_node = NULL;
acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
......
/******************************************************************************
*
* Module Name: utids - support for device IDs - HID, UID, CID
*
*****************************************************************************/
/*
* Copyright (C) 2000 - 2009, Intel Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*/
#include <acpi/acpi.h>
#include "accommon.h"
#include "acinterp.h"
#define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utids")
/* Local prototypes */
static void acpi_ut_copy_id_string(char *destination, char *source);
/*******************************************************************************
*
* FUNCTION: acpi_ut_copy_id_string
*
* PARAMETERS: Destination - Where to copy the string
* Source - Source string
*
* RETURN: None
*
* DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
* Performs removal of a leading asterisk if present -- workaround
* for a known issue on a bunch of machines.
*
******************************************************************************/
static void acpi_ut_copy_id_string(char *destination, char *source)
{
/*
* Workaround for ID strings that have a leading asterisk. This construct
* is not allowed by the ACPI specification (ID strings must be
* alphanumeric), but enough existing machines have this embedded in their
* ID strings that the following code is useful.
*/
if (*source == '*') {
source++;
}
/* Do the actual copy */
ACPI_STRCPY(destination, source);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_HID
*
* PARAMETERS: device_node - Node for the device
* return_id - Where the string HID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _HID control method that returns the hardware
* ID of the device. The HID is either an 32-bit encoded EISAID
* Integer or a String. A string is always returned. An EISAID
* is converted to a string.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id)
{
union acpi_operand_object *obj_desc;
struct acpica_device_id *hid;
u32 length;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_HID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the size of the String to be returned, includes null terminator */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
length = ACPI_EISAID_STRING_SIZE;
} else {
length = obj_desc->string.length + 1;
}
/* Allocate a buffer for the HID */
hid =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
(acpi_size) length);
if (!hid) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for the string starts after DEVICE_ID struct */
hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id));
/* Convert EISAID to a string or simply copy existing string */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer);
}
hid->length = length;
*return_id = hid;
cleanup:
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
*
* PARAMETERS: device_node - Node for the device
* return_id - Where the string UID is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _UID control method that returns the unique
* ID of the device. The UID is either a 64-bit Integer (NOT an
* EISAID) or a string. Always returns a string. A 64-bit integer
* is converted to a decimal string.
*
* NOTE: Internal function, no parameter validation
*
******************************************************************************/
acpi_status
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpica_device_id **return_id)
{
union acpi_operand_object *obj_desc;
struct acpica_device_id *uid;
u32 length;
acpi_status status;
ACPI_FUNCTION_TRACE(ut_execute_UID);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
&obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the size of the String to be returned, includes null terminator */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
length = ACPI_MAX64_DECIMAL_DIGITS + 1;
} else {
length = obj_desc->string.length + 1;
}
/* Allocate a buffer for the UID */
uid =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) +
(acpi_size) length);
if (!uid) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for the string starts after DEVICE_ID struct */
uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id));
/* Convert an Integer to string, or just copy an existing string */
if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
} else {
acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer);
}
uid->length = length;
*return_id = uid;
cleanup:
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CID
*
* PARAMETERS: device_node - Node for the device
* return_cid_list - Where the CID list is returned
*
* RETURN: Status, list of CID strings
*
* DESCRIPTION: Executes the _CID control method that returns one or more
* compatible hardware IDs for the device.
*
* NOTE: Internal function, no parameter validation
*
* A _CID method can return either a single compatible ID or a package of
* compatible IDs. Each compatible ID can be one of the following:
* 1) Integer (32 bit compressed EISA ID) or
* 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
*
* The Integer CIDs are converted to string format by this function.
*
******************************************************************************/
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpica_device_id_list **return_cid_list)
{
union acpi_operand_object **cid_objects;
union acpi_operand_object *obj_desc;
struct acpica_device_id_list *cid_list;
char *next_id_string;
u32 string_area_size;
u32 length;
u32 cid_list_size;
acpi_status status;
u32 count;
u32 i;
ACPI_FUNCTION_TRACE(ut_execute_CID);
/* Evaluate the _CID method for this device */
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
| ACPI_BTYPE_PACKAGE, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Get the count and size of the returned _CIDs. _CID can return either
* a Package of Integers/Strings or a single Integer or String.
* Note: This section also validates that all CID elements are of the
* correct type (Integer or String).
*/
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
count = obj_desc->package.count;
cid_objects = obj_desc->package.elements;
} else { /* Single Integer or String CID */
count = 1;
cid_objects = &obj_desc;
}
string_area_size = 0;
for (i = 0; i < count; i++) {
/* String lengths include null terminator */
switch (cid_objects[i]->common.type) {
case ACPI_TYPE_INTEGER:
string_area_size += ACPI_EISAID_STRING_SIZE;
break;
case ACPI_TYPE_STRING:
string_area_size += cid_objects[i]->string.length + 1;
break;
default:
status = AE_TYPE;
goto cleanup;
}
}
/*
* Now that we know the length of the CIDs, allocate return buffer:
* 1) Size of the base structure +
* 2) Size of the CID DEVICE_ID array +
* 3) Size of the actual CID strings
*/
cid_list_size = sizeof(struct acpica_device_id_list) +
((count - 1) * sizeof(struct acpica_device_id)) + string_area_size;
cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
if (!cid_list) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for CID strings starts after the CID DEVICE_ID array */
next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
((acpi_size) count * sizeof(struct acpica_device_id));
/* Copy/convert the CIDs to the return buffer */
for (i = 0; i < count; i++) {
if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
/* Convert the Integer (EISAID) CID to a string */
acpi_ex_eisa_id_to_string(next_id_string,
cid_objects[i]->integer.
value);
length = ACPI_EISAID_STRING_SIZE;
} else { /* ACPI_TYPE_STRING */
/* Copy the String CID from the returned object */
acpi_ut_copy_id_string(next_id_string,
cid_objects[i]->string.pointer);
length = cid_objects[i]->string.length + 1;
}
cid_list->ids[i].string = next_id_string;
cid_list->ids[i].length = length;
next_id_string += length;
}
/* Finish the CID list */
cid_list->count = count;
cid_list->list_size = cid_list_size;
*return_cid_list = cid_list;
cleanup:
/* On exit, we must delete the _CID return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
......@@ -99,33 +99,19 @@ static void acpi_ut_terminate(void)
*
* FUNCTION: acpi_ut_subsystem_shutdown
*
* PARAMETERS: none
* PARAMETERS: None
*
* RETURN: none
* RETURN: None
*
* DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex
* objects here -- because the AML debugger may be still running.
* DESCRIPTION: Shutdown the various components. Do not delete the mutex
* objects here, because the AML debugger may be still running.
*
******************************************************************************/
void acpi_ut_subsystem_shutdown(void)
{
ACPI_FUNCTION_TRACE(ut_subsystem_shutdown);
/* Just exit if subsystem is already shutdown */
if (acpi_gbl_shutdown) {
ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated"));
return_VOID;
}
/* Subsystem appears active, go ahead and shut it down */
acpi_gbl_shutdown = TRUE;
acpi_gbl_startup_flags = 0;
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n"));
#ifndef ACPI_ASL_COMPILER
/* Close the acpi_event Handling */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册