forked from Minki/linux
Merge branch 'acpica'
* acpica: (32 commits) ACPICA: Update version to 20170728 ACPICA: Revert "Update resource descriptor handling" ACPICA: Resources: Allow _DMA method in walk resources ACPICA: Ensure all instances of AE_AML_INTERNAL have error messages ACPICA: Implement deferred resolution of reference package elements ACPICA: Debugger: Improve support for Alias objects ACPICA: Interpreter: Update handling for Alias operator ACPICA: EFI/EDK2: Cleanup to enable /WX for MSVC builds ACPICA: acpidump: Add DSDT/FACS instance support for Linux and EFI ACPICA: CLib: Add short multiply/shift support ACPICA: EFI/EDK2: Sort acpi.h inclusion order ACPICA: Add a comment, no functional change ACPICA: Namespace: Update/fix an error message ACPICA: iASL: Add support for the SDEI table ACPICA: Divergences: reduce access size definitions ACPICA: Update version to 20170629 ACPICA: Update resource descriptor handling ACPICA: iasl: Update to IORT SMMUv3 disassembling ACPICA: Disassembler: skip parsing of incorrect external declarations ACPICA: iASL: Ensure that the target node is valid in acpi_ex_create_alias ...
This commit is contained in:
commit
b2a84eedca
@ -18,6 +18,7 @@ acpi-y := \
|
||||
dsmthdat.o \
|
||||
dsobject.o \
|
||||
dsopcode.o \
|
||||
dspkginit.o \
|
||||
dsutils.o \
|
||||
dswexec.o \
|
||||
dswload.o \
|
||||
|
@ -114,6 +114,8 @@ ac_get_all_tables_from_file(char *filename,
|
||||
u8 get_only_aml_tables,
|
||||
struct acpi_new_table_desc **return_list_head);
|
||||
|
||||
void ac_delete_table_list(struct acpi_new_table_desc *list_head);
|
||||
|
||||
u8 ac_is_file_binary(FILE * file);
|
||||
|
||||
acpi_status ac_validate_table_header(FILE * file, long table_offset);
|
||||
|
@ -237,6 +237,11 @@ acpi_ds_initialize_objects(u32 table_index,
|
||||
* dsobject - Parser/Interpreter interface - object initialization and conversion
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
union acpi_operand_object **obj_desc_ptr);
|
||||
|
||||
acpi_status
|
||||
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
u32 buffer_length,
|
||||
@ -258,6 +263,14 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
|
||||
struct acpi_namespace_node *node,
|
||||
union acpi_parse_object *op);
|
||||
|
||||
/*
|
||||
* dspkginit - Package object initialization
|
||||
*/
|
||||
acpi_status
|
||||
acpi_ds_init_package_element(u8 object_type,
|
||||
union acpi_operand_object *source_object,
|
||||
union acpi_generic_state *state, void *context);
|
||||
|
||||
/*
|
||||
* dsutils - Parser/Interpreter interface utility routines
|
||||
*/
|
||||
|
@ -199,6 +199,7 @@ struct acpi_namespace_node {
|
||||
#define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */
|
||||
#define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */
|
||||
|
||||
#define IMPLICIT_EXTERNAL 0x02 /* iASL only: This object created implicitly via External */
|
||||
#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */
|
||||
#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */
|
||||
#define ANOBJ_METHOD_SOME_NO_RETVAL 0x20 /* iASL only: Method has at least one return value */
|
||||
@ -604,7 +605,7 @@ struct acpi_update_state {
|
||||
* Pkg state - used to traverse nested package structures
|
||||
*/
|
||||
struct acpi_pkg_state {
|
||||
ACPI_STATE_COMMON u16 index;
|
||||
ACPI_STATE_COMMON u32 index;
|
||||
union acpi_operand_object *source_object;
|
||||
union acpi_operand_object *dest_object;
|
||||
struct acpi_walk_state *walk_state;
|
||||
@ -867,7 +868,7 @@ struct acpi_parse_obj_named {
|
||||
|
||||
/* This version is used by the iASL compiler only */
|
||||
|
||||
#define ACPI_MAX_PARSEOP_NAME 20
|
||||
#define ACPI_MAX_PARSEOP_NAME 20
|
||||
|
||||
struct acpi_parse_obj_asl {
|
||||
ACPI_PARSE_COMMON union acpi_parse_object *child;
|
||||
@ -907,7 +908,7 @@ union acpi_parse_object {
|
||||
struct asl_comment_state {
|
||||
u8 comment_type;
|
||||
u32 spaces_before;
|
||||
union acpi_parse_object *latest_parse_node;
|
||||
union acpi_parse_object *latest_parse_op;
|
||||
union acpi_parse_object *parsing_paren_brace_node;
|
||||
u8 capture_comments;
|
||||
};
|
||||
|
@ -122,7 +122,9 @@ struct acpi_object_integer {
|
||||
_type *pointer; \
|
||||
u32 length;
|
||||
|
||||
struct acpi_object_string { /* Null terminated, ASCII characters only */
|
||||
/* Null terminated, ASCII characters only */
|
||||
|
||||
struct acpi_object_string {
|
||||
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_BUFFER_INFO(char) /* String in AML stream or allocated string */
|
||||
};
|
||||
|
||||
@ -211,7 +213,9 @@ struct acpi_object_method {
|
||||
union acpi_operand_object *notify_list[2]; /* Handlers for system/device notifies */\
|
||||
union acpi_operand_object *handler; /* Handler for Address space */
|
||||
|
||||
struct acpi_object_notify_common { /* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
|
||||
/* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */
|
||||
|
||||
struct acpi_object_notify_common {
|
||||
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
|
||||
|
||||
struct acpi_object_device {
|
||||
@ -258,7 +262,9 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
|
||||
u8 access_length; /* For serial regions/fields */
|
||||
|
||||
|
||||
struct acpi_object_field_common { /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
|
||||
/* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
|
||||
|
||||
struct acpi_object_field_common {
|
||||
ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
|
||||
};
|
||||
|
||||
@ -333,11 +339,12 @@ struct acpi_object_addr_handler {
|
||||
struct acpi_object_reference {
|
||||
ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */
|
||||
u8 target_type; /* Used for Index Op */
|
||||
u8 reserved;
|
||||
u8 resolved; /* Reference has been resolved to a value */
|
||||
void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
|
||||
struct acpi_namespace_node *node; /* ref_of or Namepath */
|
||||
union acpi_operand_object **where; /* Target of Index */
|
||||
u8 *index_pointer; /* Used for Buffers and Strings */
|
||||
u8 *aml; /* Used for deferred resolution of the ref */
|
||||
u32 value; /* Used for Local/Arg/Index/ddb_handle */
|
||||
};
|
||||
|
||||
|
@ -76,7 +76,8 @@ void acpi_tb_release_temp_table(struct acpi_table_desc *table_desc);
|
||||
acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc);
|
||||
|
||||
acpi_status
|
||||
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature);
|
||||
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
|
||||
char *signature, u32 *table_index);
|
||||
|
||||
u8 acpi_tb_is_table_loaded(u32 table_index);
|
||||
|
||||
@ -132,6 +133,8 @@ acpi_tb_install_and_load_table(acpi_physical_address address,
|
||||
|
||||
acpi_status acpi_tb_unload_table(u32 table_index);
|
||||
|
||||
void acpi_tb_notify_table(u32 event, void *table);
|
||||
|
||||
void acpi_tb_terminate(void);
|
||||
|
||||
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);
|
||||
|
@ -516,7 +516,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
|
||||
|
||||
union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
|
||||
void *external_object,
|
||||
u16 index);
|
||||
u32 index);
|
||||
|
||||
acpi_status
|
||||
acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
|
||||
@ -538,6 +538,13 @@ acpi_status
|
||||
acpi_ut_short_divide(u64 in_dividend,
|
||||
u32 divisor, u64 *out_quotient, u32 *out_remainder);
|
||||
|
||||
acpi_status
|
||||
acpi_ut_short_multiply(u64 in_multiplicand, u32 multiplier, u64 *outproduct);
|
||||
|
||||
acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result);
|
||||
|
||||
acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result);
|
||||
|
||||
/*
|
||||
* utmisc
|
||||
*/
|
||||
|
@ -310,7 +310,7 @@ dump_node:
|
||||
}
|
||||
|
||||
else {
|
||||
acpi_os_printf("Object (%p) Pathname: %s\n",
|
||||
acpi_os_printf("Object %p: Namespace Node - Pathname: %s\n",
|
||||
node, (char *)ret_buf.pointer);
|
||||
}
|
||||
|
||||
@ -326,7 +326,7 @@ dump_node:
|
||||
|
||||
obj_desc = acpi_ns_get_attached_object(node);
|
||||
if (obj_desc) {
|
||||
acpi_os_printf("\nAttached Object (%p):\n", obj_desc);
|
||||
acpi_os_printf("\nAttached Object %p:", obj_desc);
|
||||
if (!acpi_os_readable
|
||||
(obj_desc, sizeof(union acpi_operand_object))) {
|
||||
acpi_os_printf
|
||||
@ -335,9 +335,36 @@ dump_node:
|
||||
return;
|
||||
}
|
||||
|
||||
acpi_ut_debug_dump_buffer((void *)obj_desc,
|
||||
sizeof(union acpi_operand_object),
|
||||
display, ACPI_UINT32_MAX);
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(((struct acpi_namespace_node *)
|
||||
obj_desc)) ==
|
||||
ACPI_DESC_TYPE_NAMED) {
|
||||
acpi_os_printf(" Namespace Node - ");
|
||||
status =
|
||||
acpi_get_name((struct acpi_namespace_node *)
|
||||
obj_desc,
|
||||
ACPI_FULL_PATHNAME_NO_TRAILING,
|
||||
&ret_buf);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_os_printf
|
||||
("Could not convert name to pathname\n");
|
||||
} else {
|
||||
acpi_os_printf("Pathname: %s",
|
||||
(char *)ret_buf.pointer);
|
||||
}
|
||||
|
||||
acpi_os_printf("\n");
|
||||
acpi_ut_debug_dump_buffer((void *)obj_desc,
|
||||
sizeof(struct
|
||||
acpi_namespace_node),
|
||||
display, ACPI_UINT32_MAX);
|
||||
} else {
|
||||
acpi_os_printf("\n");
|
||||
acpi_ut_debug_dump_buffer((void *)obj_desc,
|
||||
sizeof(union
|
||||
acpi_operand_object),
|
||||
display, ACPI_UINT32_MAX);
|
||||
}
|
||||
|
||||
acpi_ex_dump_object_descriptor(obj_desc, 1);
|
||||
}
|
||||
}
|
||||
|
@ -184,6 +184,7 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
|
||||
/* Execute flag should always be set when this function is entered */
|
||||
|
||||
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
|
||||
ACPI_ERROR((AE_INFO, "Parse execute mode is not set"));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
@ -556,6 +557,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Parse deferred mode is not set"));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,6 @@
|
||||
#define _COMPONENT ACPI_DISPATCHER
|
||||
ACPI_MODULE_NAME("dsobject")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
union acpi_operand_object **obj_desc_ptr);
|
||||
|
||||
#ifndef ACPI_NO_METHOD_EXECUTION
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -73,15 +67,13 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
* Simple objects are any objects other than a package object!
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_status
|
||||
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
union acpi_operand_object **obj_desc_ptr)
|
||||
{
|
||||
union acpi_operand_object *obj_desc;
|
||||
acpi_status status;
|
||||
acpi_object_type type;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_build_internal_object);
|
||||
|
||||
@ -89,140 +81,47 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
|
||||
/*
|
||||
* This is a named object reference. If this name was
|
||||
* previously looked up in the namespace, it was stored in this op.
|
||||
* Otherwise, go ahead and look it up now
|
||||
* previously looked up in the namespace, it was stored in
|
||||
* this op. Otherwise, go ahead and look it up now
|
||||
*/
|
||||
if (!op->common.node) {
|
||||
status = acpi_ns_lookup(walk_state->scope_info,
|
||||
op->common.value.string,
|
||||
ACPI_TYPE_ANY,
|
||||
ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT |
|
||||
ACPI_NS_DONT_OPEN_SCOPE, NULL,
|
||||
ACPI_CAST_INDIRECT_PTR(struct
|
||||
acpi_namespace_node,
|
||||
&(op->
|
||||
common.
|
||||
node)));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
|
||||
/* Check if we are resolving a named reference within a package */
|
||||
/* Check if we are resolving a named reference within a package */
|
||||
|
||||
if ((status == AE_NOT_FOUND)
|
||||
&& (acpi_gbl_enable_interpreter_slack)
|
||||
&&
|
||||
((op->common.parent->common.aml_opcode ==
|
||||
AML_PACKAGE_OP)
|
||||
|| (op->common.parent->common.aml_opcode ==
|
||||
AML_VARIABLE_PACKAGE_OP))) {
|
||||
/*
|
||||
* We didn't find the target and we are populating elements
|
||||
* of a package - ignore if slack enabled. Some ASL code
|
||||
* contains dangling invalid references in packages and
|
||||
* expects that no exception will be issued. Leave the
|
||||
* element as a null element. It cannot be used, but it
|
||||
* can be overwritten by subsequent ASL code - this is
|
||||
* typically the case.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Ignoring unresolved reference in package [%4.4s]\n",
|
||||
walk_state->
|
||||
scope_info->scope.
|
||||
node->name.ascii));
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
} else {
|
||||
if ((op->common.parent->common.aml_opcode ==
|
||||
AML_PACKAGE_OP)
|
||||
|| (op->common.parent->common.aml_opcode ==
|
||||
AML_VARIABLE_PACKAGE_OP)) {
|
||||
/*
|
||||
* We won't resolve package elements here, we will do this
|
||||
* after all ACPI tables are loaded into the namespace. This
|
||||
* behavior supports both forward references to named objects
|
||||
* and external references to objects in other tables.
|
||||
*/
|
||||
goto create_new_object;
|
||||
} else {
|
||||
status = acpi_ns_lookup(walk_state->scope_info,
|
||||
op->common.value.string,
|
||||
ACPI_TYPE_ANY,
|
||||
ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT |
|
||||
ACPI_NS_DONT_OPEN_SCOPE,
|
||||
NULL,
|
||||
ACPI_CAST_INDIRECT_PTR
|
||||
(struct
|
||||
acpi_namespace_node,
|
||||
&(op->common.node)));
|
||||
if (ACPI_FAILURE(status)) {
|
||||
ACPI_ERROR_NAMESPACE(op->common.value.
|
||||
string, status);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
}
|
||||
|
||||
/* Special object resolution for elements of a package */
|
||||
|
||||
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
|
||||
(op->common.parent->common.aml_opcode ==
|
||||
AML_VARIABLE_PACKAGE_OP)) {
|
||||
/*
|
||||
* Attempt to resolve the node to a value before we insert it into
|
||||
* the package. If this is a reference to a common data type,
|
||||
* resolve it immediately. According to the ACPI spec, package
|
||||
* elements can only be "data objects" or method references.
|
||||
* Attempt to resolve to an Integer, Buffer, String or Package.
|
||||
* If cannot, return the named reference (for things like Devices,
|
||||
* Methods, etc.) Buffer Fields and Fields will resolve to simple
|
||||
* objects (int/buf/str/pkg).
|
||||
*
|
||||
* NOTE: References to things like Devices, Methods, Mutexes, etc.
|
||||
* will remain as named references. This behavior is not described
|
||||
* in the ACPI spec, but it appears to be an oversight.
|
||||
*/
|
||||
obj_desc =
|
||||
ACPI_CAST_PTR(union acpi_operand_object,
|
||||
op->common.node);
|
||||
|
||||
status =
|
||||
acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR
|
||||
(struct
|
||||
acpi_namespace_node,
|
||||
&obj_desc),
|
||||
walk_state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special handling for Alias objects. We need to setup the type
|
||||
* and the Op->Common.Node to point to the Alias target. Note,
|
||||
* Alias has at most one level of indirection internally.
|
||||
*/
|
||||
type = op->common.node->type;
|
||||
if (type == ACPI_TYPE_LOCAL_ALIAS) {
|
||||
type = obj_desc->common.type;
|
||||
op->common.node =
|
||||
ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
op->common.node->object);
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
/*
|
||||
* For these types, we need the actual node, not the subobject.
|
||||
* However, the subobject did not get an extra reference count above.
|
||||
*
|
||||
* TBD: should ex_resolve_node_to_value be changed to fix this?
|
||||
*/
|
||||
case ACPI_TYPE_DEVICE:
|
||||
case ACPI_TYPE_THERMAL:
|
||||
|
||||
acpi_ut_add_reference(op->common.node->object);
|
||||
|
||||
/*lint -fallthrough */
|
||||
/*
|
||||
* For these types, we need the actual node, not the subobject.
|
||||
* The subobject got an extra reference count in ex_resolve_node_to_value.
|
||||
*/
|
||||
case ACPI_TYPE_MUTEX:
|
||||
case ACPI_TYPE_METHOD:
|
||||
case ACPI_TYPE_POWER:
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
case ACPI_TYPE_EVENT:
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
/* We will create a reference object for these types below */
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other types - the node was resolved to an actual
|
||||
* object, we are done.
|
||||
*/
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create_new_object:
|
||||
|
||||
/* Create and init a new internal ACPI object */
|
||||
|
||||
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
|
||||
@ -240,7 +139,27 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
exit:
|
||||
/*
|
||||
* Handling for unresolved package reference elements.
|
||||
* These are elements that are namepaths.
|
||||
*/
|
||||
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
|
||||
(op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
|
||||
obj_desc->reference.resolved = TRUE;
|
||||
|
||||
if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
|
||||
!obj_desc->reference.node) {
|
||||
/*
|
||||
* Name was unresolved above.
|
||||
* Get the prefix node for later lookup
|
||||
*/
|
||||
obj_desc->reference.node =
|
||||
walk_state->scope_info->scope.node;
|
||||
obj_desc->reference.aml = op->common.aml;
|
||||
obj_desc->reference.resolved = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
*obj_desc_ptr = obj_desc;
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
@ -349,200 +268,6 @@ acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_build_internal_package_obj
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
* op - Parser object to be translated
|
||||
* element_count - Number of elements in the package - this is
|
||||
* the num_elements argument to Package()
|
||||
* obj_desc_ptr - Where the ACPI internal object is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Translate a parser Op package object to the equivalent
|
||||
* namespace object
|
||||
*
|
||||
* NOTE: The number of elements in the package will be always be the num_elements
|
||||
* count, regardless of the number of elements in the package list. If
|
||||
* num_elements is smaller, only that many package list elements are used.
|
||||
* if num_elements is larger, the Package object is padded out with
|
||||
* objects of type Uninitialized (as per ACPI spec.)
|
||||
*
|
||||
* Even though the ASL compilers do not allow num_elements to be smaller
|
||||
* than the Package list length (for the fixed length package opcode), some
|
||||
* BIOS code modifies the AML on the fly to adjust the num_elements, and
|
||||
* this code compensates for that. This also provides compatibility with
|
||||
* other AML interpreters.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
u32 element_count,
|
||||
union acpi_operand_object **obj_desc_ptr)
|
||||
{
|
||||
union acpi_parse_object *arg;
|
||||
union acpi_parse_object *parent;
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
acpi_status status = AE_OK;
|
||||
u32 i;
|
||||
u16 index;
|
||||
u16 reference_count;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
|
||||
|
||||
/* Find the parent of a possibly nested package */
|
||||
|
||||
parent = op->common.parent;
|
||||
while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
|
||||
(parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
|
||||
parent = parent->common.parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are evaluating a Named package object "Name (xxxx, Package)",
|
||||
* the package object already exists, otherwise it must be created.
|
||||
*/
|
||||
obj_desc = *obj_desc_ptr;
|
||||
if (!obj_desc) {
|
||||
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
|
||||
*obj_desc_ptr = obj_desc;
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
obj_desc->package.node = parent->common.node;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the element array (array of pointers to the individual
|
||||
* objects) based on the num_elements parameter. Add an extra pointer slot
|
||||
* so that the list is always null terminated.
|
||||
*/
|
||||
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
|
||||
element_count +
|
||||
1) * sizeof(void *));
|
||||
|
||||
if (!obj_desc->package.elements) {
|
||||
acpi_ut_delete_object_desc(obj_desc);
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
obj_desc->package.count = element_count;
|
||||
|
||||
/*
|
||||
* Initialize the elements of the package, up to the num_elements count.
|
||||
* Package is automatically padded with uninitialized (NULL) elements
|
||||
* if num_elements is greater than the package list length. Likewise,
|
||||
* Package is truncated if num_elements is less than the list length.
|
||||
*/
|
||||
arg = op->common.value.arg;
|
||||
arg = arg->common.next;
|
||||
for (i = 0; arg && (i < element_count); i++) {
|
||||
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
|
||||
if (arg->common.node->type == ACPI_TYPE_METHOD) {
|
||||
/*
|
||||
* A method reference "looks" to the parser to be a method
|
||||
* invocation, so we special case it here
|
||||
*/
|
||||
arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
|
||||
status =
|
||||
acpi_ds_build_internal_object(walk_state,
|
||||
arg,
|
||||
&obj_desc->
|
||||
package.
|
||||
elements[i]);
|
||||
} else {
|
||||
/* This package element is already built, just get it */
|
||||
|
||||
obj_desc->package.elements[i] =
|
||||
ACPI_CAST_PTR(union acpi_operand_object,
|
||||
arg->common.node);
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
acpi_ds_build_internal_object(walk_state, arg,
|
||||
&obj_desc->package.
|
||||
elements[i]);
|
||||
}
|
||||
|
||||
if (*obj_desc_ptr) {
|
||||
|
||||
/* Existing package, get existing reference count */
|
||||
|
||||
reference_count =
|
||||
(*obj_desc_ptr)->common.reference_count;
|
||||
if (reference_count > 1) {
|
||||
|
||||
/* Make new element ref count match original ref count */
|
||||
|
||||
for (index = 0; index < (reference_count - 1);
|
||||
index++) {
|
||||
acpi_ut_add_reference((obj_desc->
|
||||
package.
|
||||
elements[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
/* Check for match between num_elements and actual length of package_list */
|
||||
|
||||
if (arg) {
|
||||
/*
|
||||
* num_elements was exhausted, but there are remaining elements in the
|
||||
* 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, we just print a 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 */
|
||||
|
||||
i++;
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
ACPI_INFO(("Actual Package length (%u) is larger than "
|
||||
"NumElements field (%u), truncated",
|
||||
i, element_count));
|
||||
} else if (i < element_count) {
|
||||
/*
|
||||
* Arg list (elements) was exhausted, but we did not reach num_elements count.
|
||||
* Note: this is not an error, the package is padded out with NULLs.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Package List length (%u) smaller than NumElements "
|
||||
"count (%u), padded with null elements\n",
|
||||
i, element_count));
|
||||
}
|
||||
|
||||
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
|
||||
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_create_node
|
||||
@ -662,11 +387,20 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
|
||||
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
/*
|
||||
* Defer evaluation of Package term_arg operand
|
||||
* Defer evaluation of Package term_arg operand and all
|
||||
* package elements. (01/2017): We defer the element
|
||||
* resolution to allow forward references from the package
|
||||
* in order to provide compatibility with other ACPI
|
||||
* implementations.
|
||||
*/
|
||||
obj_desc->package.node =
|
||||
ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
walk_state->operands[0]);
|
||||
|
||||
if (!op->named.data) {
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
obj_desc->package.aml_start = op->named.data;
|
||||
obj_desc->package.aml_length = op->named.length;
|
||||
break;
|
||||
@ -818,9 +552,11 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
|
||||
/* Node was saved in Op */
|
||||
|
||||
obj_desc->reference.node = op->common.node;
|
||||
obj_desc->reference.object =
|
||||
op->common.node->object;
|
||||
obj_desc->reference.class = ACPI_REFCLASS_NAME;
|
||||
if (op->common.node) {
|
||||
obj_desc->reference.object =
|
||||
op->common.node->object;
|
||||
}
|
||||
break;
|
||||
|
||||
case AML_DEBUG_OP:
|
||||
|
@ -599,6 +599,15 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
|
||||
*/
|
||||
walk_state->operand_index = walk_state->num_operands;
|
||||
|
||||
/* Ignore if child is not valid */
|
||||
|
||||
if (!op->common.value.arg) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Dispatch: Missing child while executing TermArg for %X",
|
||||
op->common.aml_opcode));
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
|
496
drivers/acpi/acpica/dspkginit.c
Normal file
496
drivers/acpi/acpica/dspkginit.c
Normal file
@ -0,0 +1,496 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: dspkginit - Completion of deferred package initialization
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2000 - 2017, 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 "amlcode.h"
|
||||
#include "acdispat.h"
|
||||
#include "acinterp.h"
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
ACPI_MODULE_NAME("dspkginit")
|
||||
|
||||
/* Local prototypes */
|
||||
static void
|
||||
acpi_ds_resolve_package_element(union acpi_operand_object **element);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_build_internal_package_obj
|
||||
*
|
||||
* PARAMETERS: walk_state - Current walk state
|
||||
* op - Parser object to be translated
|
||||
* element_count - Number of elements in the package - this is
|
||||
* the num_elements argument to Package()
|
||||
* obj_desc_ptr - Where the ACPI internal object is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Translate a parser Op package object to the equivalent
|
||||
* namespace object
|
||||
*
|
||||
* NOTE: The number of elements in the package will be always be the num_elements
|
||||
* count, regardless of the number of elements in the package list. If
|
||||
* num_elements is smaller, only that many package list elements are used.
|
||||
* if num_elements is larger, the Package object is padded out with
|
||||
* objects of type Uninitialized (as per ACPI spec.)
|
||||
*
|
||||
* Even though the ASL compilers do not allow num_elements to be smaller
|
||||
* than the Package list length (for the fixed length package opcode), some
|
||||
* BIOS code modifies the AML on the fly to adjust the num_elements, and
|
||||
* this code compensates for that. This also provides compatibility with
|
||||
* other AML interpreters.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
|
||||
union acpi_parse_object *op,
|
||||
u32 element_count,
|
||||
union acpi_operand_object **obj_desc_ptr)
|
||||
{
|
||||
union acpi_parse_object *arg;
|
||||
union acpi_parse_object *parent;
|
||||
union acpi_operand_object *obj_desc = NULL;
|
||||
acpi_status status = AE_OK;
|
||||
u16 reference_count;
|
||||
u32 index;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
|
||||
|
||||
/* Find the parent of a possibly nested package */
|
||||
|
||||
parent = op->common.parent;
|
||||
while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
|
||||
(parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
|
||||
parent = parent->common.parent;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are evaluating a Named package object of the form:
|
||||
* Name (xxxx, Package)
|
||||
* the package object already exists, otherwise it must be created.
|
||||
*/
|
||||
obj_desc = *obj_desc_ptr;
|
||||
if (!obj_desc) {
|
||||
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE);
|
||||
*obj_desc_ptr = obj_desc;
|
||||
if (!obj_desc) {
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
obj_desc->package.node = parent->common.node;
|
||||
}
|
||||
|
||||
if (obj_desc->package.flags & AOPOBJ_DATA_VALID) { /* Just in case */
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate the element array (array of pointers to the individual
|
||||
* objects) based on the num_elements parameter. Add an extra pointer slot
|
||||
* so that the list is always null terminated.
|
||||
*/
|
||||
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
|
||||
element_count +
|
||||
1) * sizeof(void *));
|
||||
|
||||
if (!obj_desc->package.elements) {
|
||||
acpi_ut_delete_object_desc(obj_desc);
|
||||
return_ACPI_STATUS(AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
obj_desc->package.count = element_count;
|
||||
arg = op->common.value.arg;
|
||||
arg = arg->common.next;
|
||||
|
||||
if (arg) {
|
||||
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the elements of the package, up to the num_elements count.
|
||||
* Package is automatically padded with uninitialized (NULL) elements
|
||||
* if num_elements is greater than the package list length. Likewise,
|
||||
* Package is truncated if num_elements is less than the list length.
|
||||
*/
|
||||
for (i = 0; arg && (i < element_count); i++) {
|
||||
if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
|
||||
if (arg->common.node->type == ACPI_TYPE_METHOD) {
|
||||
/*
|
||||
* A method reference "looks" to the parser to be a method
|
||||
* invocation, so we special case it here
|
||||
*/
|
||||
arg->common.aml_opcode = AML_INT_NAMEPATH_OP;
|
||||
status =
|
||||
acpi_ds_build_internal_object(walk_state,
|
||||
arg,
|
||||
&obj_desc->
|
||||
package.
|
||||
elements[i]);
|
||||
} else {
|
||||
/* This package element is already built, just get it */
|
||||
|
||||
obj_desc->package.elements[i] =
|
||||
ACPI_CAST_PTR(union acpi_operand_object,
|
||||
arg->common.node);
|
||||
}
|
||||
} else {
|
||||
status =
|
||||
acpi_ds_build_internal_object(walk_state, arg,
|
||||
&obj_desc->package.
|
||||
elements[i]);
|
||||
if (status == AE_NOT_FOUND) {
|
||||
ACPI_ERROR((AE_INFO, "%-48s",
|
||||
"****DS namepath not found"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize this package element. This function handles the
|
||||
* resolution of named references within the package.
|
||||
*/
|
||||
acpi_ds_init_package_element(0,
|
||||
obj_desc->package.
|
||||
elements[i], NULL,
|
||||
&obj_desc->package.
|
||||
elements[i]);
|
||||
}
|
||||
|
||||
if (*obj_desc_ptr) {
|
||||
|
||||
/* Existing package, get existing reference count */
|
||||
|
||||
reference_count =
|
||||
(*obj_desc_ptr)->common.reference_count;
|
||||
if (reference_count > 1) {
|
||||
|
||||
/* Make new element ref count match original ref count */
|
||||
/* TBD: Probably need an acpi_ut_add_references function */
|
||||
|
||||
for (index = 0;
|
||||
index < ((u32)reference_count - 1);
|
||||
index++) {
|
||||
acpi_ut_add_reference((obj_desc->
|
||||
package.
|
||||
elements[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
/* Check for match between num_elements and actual length of package_list */
|
||||
|
||||
if (arg) {
|
||||
/*
|
||||
* num_elements was exhausted, but there are remaining elements in
|
||||
* the 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, we just print a message and no
|
||||
* exception is returned. This provides compatibility with other
|
||||
* ACPI implementations. Some firmware implementations will alter
|
||||
* the num_elements on the fly, possibly 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 */
|
||||
|
||||
i++;
|
||||
arg = arg->common.next;
|
||||
}
|
||||
|
||||
ACPI_INFO(("Actual Package length (%u) is larger than "
|
||||
"NumElements field (%u), truncated",
|
||||
i, element_count));
|
||||
} else if (i < element_count) {
|
||||
/*
|
||||
* Arg list (elements) was exhausted, but we did not reach
|
||||
* num_elements count.
|
||||
*
|
||||
* Note: this is not an error, the package is padded out
|
||||
* with NULLs.
|
||||
*/
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Package List length (%u) smaller than NumElements "
|
||||
"count (%u), padded with null elements\n",
|
||||
i, element_count));
|
||||
}
|
||||
|
||||
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
|
||||
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_init_package_element
|
||||
*
|
||||
* PARAMETERS: acpi_pkg_callback
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Resolve a named reference element within a package object
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ds_init_package_element(u8 object_type,
|
||||
union acpi_operand_object *source_object,
|
||||
union acpi_generic_state *state, void *context)
|
||||
{
|
||||
union acpi_operand_object **element_ptr;
|
||||
|
||||
if (!source_object) {
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code is a bit of a hack to workaround a (current)
|
||||
* limitation of the acpi_pkg_callback interface. We need a pointer
|
||||
* to the location within the element array because a new object
|
||||
* may be created and stored there.
|
||||
*/
|
||||
if (context) {
|
||||
|
||||
/* A direct call was made to this function */
|
||||
|
||||
element_ptr = (union acpi_operand_object **)context;
|
||||
} else {
|
||||
/* Call came from acpi_ut_walk_package_tree */
|
||||
|
||||
element_ptr = state->pkg.this_target_obj;
|
||||
}
|
||||
|
||||
/* We are only interested in reference objects/elements */
|
||||
|
||||
if (source_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) {
|
||||
|
||||
/* Attempt to resolve the (named) reference to a namespace node */
|
||||
|
||||
acpi_ds_resolve_package_element(element_ptr);
|
||||
} else if (source_object->common.type == ACPI_TYPE_PACKAGE) {
|
||||
source_object->package.flags |= AOPOBJ_DATA_VALID;
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ds_resolve_package_element
|
||||
*
|
||||
* PARAMETERS: element_ptr - Pointer to a reference object
|
||||
*
|
||||
* RETURN: Possible new element is stored to the indirect element_ptr
|
||||
*
|
||||
* DESCRIPTION: Resolve a package element that is a reference to a named
|
||||
* object.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void
|
||||
acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
|
||||
{
|
||||
acpi_status status;
|
||||
union acpi_generic_state scope_info;
|
||||
union acpi_operand_object *element = *element_ptr;
|
||||
struct acpi_namespace_node *resolved_node;
|
||||
char *external_path = NULL;
|
||||
acpi_object_type type;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ds_resolve_package_element);
|
||||
|
||||
/* Check if reference element is already resolved */
|
||||
|
||||
if (element->reference.resolved) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* Element must be a reference object of correct type */
|
||||
|
||||
scope_info.scope.node = element->reference.node; /* Prefix node */
|
||||
|
||||
status = acpi_ns_lookup(&scope_info, (char *)element->reference.aml, /* Pointer to AML path */
|
||||
ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
|
||||
ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
|
||||
NULL, &resolved_node);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
|
||||
(char *)element->reference.
|
||||
aml, NULL, &external_path);
|
||||
|
||||
ACPI_EXCEPTION((AE_INFO, status,
|
||||
"Could not find/resolve named package element: %s",
|
||||
external_path));
|
||||
|
||||
ACPI_FREE(external_path);
|
||||
*element_ptr = NULL;
|
||||
return_VOID;
|
||||
} else if (resolved_node->type == ACPI_TYPE_ANY) {
|
||||
|
||||
/* Named reference not resolved, return a NULL package element */
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Could not resolve named package element [%4.4s] in [%4.4s]",
|
||||
resolved_node->name.ascii,
|
||||
scope_info.scope.node->name.ascii));
|
||||
*element_ptr = NULL;
|
||||
return_VOID;
|
||||
}
|
||||
#if 0
|
||||
else if (resolved_node->flags & ANOBJ_TEMPORARY) {
|
||||
/*
|
||||
* A temporary node found here indicates that the reference is
|
||||
* to a node that was created within this method. We are not
|
||||
* going to allow it (especially if the package is returned
|
||||
* from the method) -- the temporary node will be deleted out
|
||||
* from under the method. (05/2017).
|
||||
*/
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Package element refers to a temporary name [%4.4s], "
|
||||
"inserting a NULL element",
|
||||
resolved_node->name.ascii));
|
||||
*element_ptr = NULL;
|
||||
return_VOID;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Special handling for Alias objects. We need resolved_node to point
|
||||
* to the Alias target. This effectively "resolves" the alias.
|
||||
*/
|
||||
if (resolved_node->type == ACPI_TYPE_LOCAL_ALIAS) {
|
||||
resolved_node = ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
resolved_node->object);
|
||||
}
|
||||
|
||||
/* Update the reference object */
|
||||
|
||||
element->reference.resolved = TRUE;
|
||||
element->reference.node = resolved_node;
|
||||
type = element->reference.node->type;
|
||||
|
||||
/*
|
||||
* Attempt to resolve the node to a value before we insert it into
|
||||
* the package. If this is a reference to a common data type,
|
||||
* resolve it immediately. According to the ACPI spec, package
|
||||
* elements can only be "data objects" or method references.
|
||||
* Attempt to resolve to an Integer, Buffer, String or Package.
|
||||
* If cannot, return the named reference (for things like Devices,
|
||||
* Methods, etc.) Buffer Fields and Fields will resolve to simple
|
||||
* objects (int/buf/str/pkg).
|
||||
*
|
||||
* NOTE: References to things like Devices, Methods, Mutexes, etc.
|
||||
* will remain as named references. This behavior is not described
|
||||
* in the ACPI spec, but it appears to be an oversight.
|
||||
*/
|
||||
status = acpi_ex_resolve_node_to_value(&resolved_node, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_VOID;
|
||||
}
|
||||
#if 0
|
||||
/* TBD - alias support */
|
||||
/*
|
||||
* Special handling for Alias objects. We need to setup the type
|
||||
* and the Op->Common.Node to point to the Alias target. Note,
|
||||
* Alias has at most one level of indirection internally.
|
||||
*/
|
||||
type = op->common.node->type;
|
||||
if (type == ACPI_TYPE_LOCAL_ALIAS) {
|
||||
type = obj_desc->common.type;
|
||||
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
op->common.node->object);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
/*
|
||||
* These object types are a result of named references, so we will
|
||||
* leave them as reference objects. In other words, these types
|
||||
* have no intrinsic "value".
|
||||
*/
|
||||
case ACPI_TYPE_DEVICE:
|
||||
case ACPI_TYPE_THERMAL:
|
||||
|
||||
/* TBD: This may not be necesssary */
|
||||
|
||||
acpi_ut_add_reference(resolved_node->object);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_MUTEX:
|
||||
case ACPI_TYPE_METHOD:
|
||||
case ACPI_TYPE_POWER:
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
case ACPI_TYPE_EVENT:
|
||||
case ACPI_TYPE_REGION:
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* For all other types - the node was resolved to an actual
|
||||
* operand object with a value, return the object
|
||||
*/
|
||||
*element_ptr = (union acpi_operand_object *)resolved_node;
|
||||
break;
|
||||
}
|
||||
|
||||
return_VOID;
|
||||
}
|
@ -87,32 +87,27 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
|
||||
target_node->object);
|
||||
}
|
||||
|
||||
/*
|
||||
* For objects that can never change (i.e., the NS node will
|
||||
* permanently point to the same object), we can simply attach
|
||||
* the object to the new NS node. For other objects (such as
|
||||
* Integers, buffers, etc.), we have to point the Alias node
|
||||
* to the original Node.
|
||||
*/
|
||||
/* Ensure that the target node is valid */
|
||||
|
||||
if (!target_node) {
|
||||
return_ACPI_STATUS(AE_NULL_OBJECT);
|
||||
}
|
||||
|
||||
/* Construct the alias object (a namespace node) */
|
||||
|
||||
switch (target_node->type) {
|
||||
|
||||
/* For these types, the sub-object can change dynamically via a Store */
|
||||
|
||||
case ACPI_TYPE_INTEGER:
|
||||
case ACPI_TYPE_STRING:
|
||||
case ACPI_TYPE_BUFFER:
|
||||
case ACPI_TYPE_PACKAGE:
|
||||
case ACPI_TYPE_BUFFER_FIELD:
|
||||
case ACPI_TYPE_METHOD:
|
||||
/*
|
||||
* These types open a new scope, so we need the NS node in order to access
|
||||
* any children.
|
||||
* Control method aliases need to be differentiated with
|
||||
* a special type
|
||||
*/
|
||||
case ACPI_TYPE_DEVICE:
|
||||
case ACPI_TYPE_POWER:
|
||||
case ACPI_TYPE_PROCESSOR:
|
||||
case ACPI_TYPE_THERMAL:
|
||||
case ACPI_TYPE_LOCAL_SCOPE:
|
||||
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* All other object types.
|
||||
*
|
||||
* The new alias has the type ALIAS and points to the original
|
||||
* NS node, not the object itself.
|
||||
*/
|
||||
@ -120,35 +115,12 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
|
||||
alias_node->object =
|
||||
ACPI_CAST_PTR(union acpi_operand_object, target_node);
|
||||
break;
|
||||
|
||||
case ACPI_TYPE_METHOD:
|
||||
/*
|
||||
* Control method aliases need to be differentiated
|
||||
*/
|
||||
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
|
||||
alias_node->object =
|
||||
ACPI_CAST_PTR(union acpi_operand_object, target_node);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Attach the original source object to the new Alias Node */
|
||||
|
||||
/*
|
||||
* The new alias assumes the type of the target, and it points
|
||||
* to the same object. The reference count of the object has an
|
||||
* additional reference to prevent deletion out from under either the
|
||||
* target node or the alias Node
|
||||
*/
|
||||
status = acpi_ns_attach_object(alias_node,
|
||||
acpi_ns_get_attached_object
|
||||
(target_node),
|
||||
target_node->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Since both operands are Nodes, we don't need to delete them */
|
||||
|
||||
alias_node->object =
|
||||
ACPI_CAST_PTR(union acpi_operand_object, target_node);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ static struct acpi_exdump_info acpi_ex_dump_package[6] = {
|
||||
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL},
|
||||
{ACPI_EXD_NODE, ACPI_EXD_OFFSET(package.node), "Parent Node"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"},
|
||||
{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Elements"},
|
||||
{ACPI_EXD_UINT32, ACPI_EXD_OFFSET(package.count), "Element Count"},
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"},
|
||||
{ACPI_EXD_PACKAGE, 0, NULL}
|
||||
};
|
||||
@ -384,6 +384,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
|
||||
count = info->offset;
|
||||
|
||||
while (count) {
|
||||
if (!obj_desc) {
|
||||
return;
|
||||
}
|
||||
|
||||
target = ACPI_ADD_PTR(u8, obj_desc, info->offset);
|
||||
name = info->name;
|
||||
|
||||
@ -469,9 +473,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
|
||||
start = *ACPI_CAST_PTR(void *, target);
|
||||
next = start;
|
||||
|
||||
acpi_os_printf("%20s : %p", name, next);
|
||||
acpi_os_printf("%20s : %p ", name, next);
|
||||
if (next) {
|
||||
acpi_os_printf("(%s %2.2X)",
|
||||
acpi_os_printf("%s (Type %2.2X)",
|
||||
acpi_ut_get_object_type_name
|
||||
(next), next->common.type);
|
||||
|
||||
@ -493,6 +497,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
acpi_os_printf("- No attached objects");
|
||||
}
|
||||
|
||||
acpi_os_printf("\n");
|
||||
@ -1129,7 +1135,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
|
||||
|
||||
default:
|
||||
|
||||
acpi_os_printf("[Unknown Type] %X\n", obj_desc->common.type);
|
||||
acpi_os_printf("[%s] Type: %2.2X\n",
|
||||
acpi_ut_get_type_name(obj_desc->common.type),
|
||||
obj_desc->common.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1167,11 +1175,17 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
|
||||
acpi_ex_dump_namespace_node((struct acpi_namespace_node *)
|
||||
obj_desc, flags);
|
||||
|
||||
acpi_os_printf("\nAttached Object (%p):\n",
|
||||
((struct acpi_namespace_node *)obj_desc)->
|
||||
object);
|
||||
|
||||
obj_desc = ((struct acpi_namespace_node *)obj_desc)->object;
|
||||
if (!obj_desc) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
acpi_os_printf("\nAttached Object %p", obj_desc);
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) == ACPI_DESC_TYPE_NAMED) {
|
||||
acpi_os_printf(" - Namespace Node");
|
||||
}
|
||||
|
||||
acpi_os_printf(":\n");
|
||||
goto dump_object;
|
||||
}
|
||||
|
||||
@ -1191,6 +1205,10 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
|
||||
|
||||
dump_object:
|
||||
|
||||
if (!obj_desc) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
/* Common Fields */
|
||||
|
||||
acpi_ex_dump_object(obj_desc, acpi_ex_dump_common);
|
||||
|
@ -265,6 +265,8 @@ acpi_ex_do_logical_numeric_op(u16 opcode,
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid numeric logical opcode: %X", opcode));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
@ -345,6 +347,9 @@ acpi_ex_do_logical_op(u16 opcode,
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid object type for logical operator: %X",
|
||||
operand0->common.type));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
@ -388,6 +393,8 @@ acpi_ex_do_logical_op(u16 opcode,
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid comparison opcode: %X", opcode));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
@ -456,6 +463,8 @@ acpi_ex_do_logical_op(u16 opcode,
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid comparison opcode: %X", opcode));
|
||||
status = AE_AML_INTERNAL;
|
||||
break;
|
||||
}
|
||||
|
@ -414,6 +414,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid object type: %X",
|
||||
(operand[0])->common.type));
|
||||
status = AE_AML_INTERNAL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ acpi_hw_get_access_bit_width(u64 address,
|
||||
ACPI_IS_ALIGNED(reg->bit_width, 8)) {
|
||||
access_bit_width = reg->bit_width;
|
||||
} else if (reg->access_width) {
|
||||
access_bit_width = (1 << (reg->access_width + 2));
|
||||
access_bit_width = ACPI_ACCESS_BIT_WIDTH(reg->access_width);
|
||||
} else {
|
||||
access_bit_width =
|
||||
ACPI_ROUND_UP_POWER_OF_TWO_8(reg->bit_offset +
|
||||
|
@ -72,13 +72,16 @@ static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
|
||||
static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
|
||||
{ACPI_STRUCT_INIT(legacy_function,
|
||||
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep)),
|
||||
ACPI_STRUCT_INIT(extended_function, acpi_hw_extended_sleep) },
|
||||
ACPI_STRUCT_INIT(extended_function,
|
||||
acpi_hw_extended_sleep)},
|
||||
{ACPI_STRUCT_INIT(legacy_function,
|
||||
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep)),
|
||||
ACPI_STRUCT_INIT(extended_function, acpi_hw_extended_wake_prep) },
|
||||
ACPI_STRUCT_INIT(extended_function,
|
||||
acpi_hw_extended_wake_prep)},
|
||||
{ACPI_STRUCT_INIT(legacy_function,
|
||||
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake)),
|
||||
ACPI_STRUCT_INIT(extended_function, acpi_hw_extended_wake) }
|
||||
ACPI_STRUCT_INIT(extended_function,
|
||||
acpi_hw_extended_wake)}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -292,6 +292,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
|
||||
{
|
||||
acpi_status status;
|
||||
char *path = pathname;
|
||||
char *external_path;
|
||||
struct acpi_namespace_node *prefix_node;
|
||||
struct acpi_namespace_node *current_node = NULL;
|
||||
struct acpi_namespace_node *this_node = NULL;
|
||||
@ -427,13 +428,22 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
|
||||
num_carats++;
|
||||
this_node = this_node->parent;
|
||||
if (!this_node) {
|
||||
/*
|
||||
* Current scope has no parent scope. Externalize
|
||||
* the internal path for error message.
|
||||
*/
|
||||
status =
|
||||
acpi_ns_externalize_name
|
||||
(ACPI_UINT32_MAX, pathname, NULL,
|
||||
&external_path);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"%s: Path has too many parent prefixes (^)",
|
||||
external_path));
|
||||
|
||||
/* Current scope has no parent scope */
|
||||
ACPI_FREE(external_path);
|
||||
}
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"%s: Path has too many parent prefixes (^) "
|
||||
"- reached beyond root node",
|
||||
pathname));
|
||||
return_ACPI_STATUS(AE_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@ -634,6 +644,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
|
||||
this_node->object;
|
||||
}
|
||||
}
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
if (!acpi_gbl_disasm_flag &&
|
||||
(this_node->flags & ANOBJ_IS_EXTERNAL)) {
|
||||
this_node->flags |= IMPLICIT_EXTERNAL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Special handling for the last segment (num_segments == 0) */
|
||||
|
@ -69,9 +69,14 @@ void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)
|
||||
u8 user_arg_type;
|
||||
u32 i;
|
||||
|
||||
/* If not a predefined name, cannot typecheck args */
|
||||
|
||||
if (!info->predefined) {
|
||||
/*
|
||||
* If not a predefined name, cannot typecheck args, because
|
||||
* we have no idea what argument types are expected.
|
||||
* Also, ignore typecheck if warnings/errors if this method
|
||||
* has already been evaluated at least once -- in order
|
||||
* to suppress repetitive messages.
|
||||
*/
|
||||
if (!info->predefined || (info->node->flags & ANOBJ_EVALUATED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -93,6 +98,10 @@ void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)
|
||||
acpi_ut_get_type_name
|
||||
(user_arg_type),
|
||||
acpi_ut_get_type_name(arg_type)));
|
||||
|
||||
/* Prevent any additional typechecking for this method */
|
||||
|
||||
info->node->flags |= ANOBJ_EVALUATED;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,7 +130,7 @@ acpi_ns_check_acpi_compliance(char *pathname,
|
||||
u32 aml_param_count;
|
||||
u32 required_param_count;
|
||||
|
||||
if (!predefined) {
|
||||
if (!predefined || (node->flags & ANOBJ_EVALUATED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -215,6 +224,10 @@ acpi_ns_check_argument_count(char *pathname,
|
||||
u32 aml_param_count;
|
||||
u32 required_param_count;
|
||||
|
||||
if (node->flags & ANOBJ_EVALUATED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!predefined) {
|
||||
/*
|
||||
* Not a predefined name. Check the incoming user argument count
|
||||
|
@ -396,6 +396,20 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
|
||||
|
||||
info->package_init++;
|
||||
status = acpi_ds_get_package_arguments(obj_desc);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve all named references in package objects (and all
|
||||
* sub-packages). This action has been deferred until the entire
|
||||
* namespace has been loaded, in order to support external and
|
||||
* forward references from individual package elements (05/2017).
|
||||
*/
|
||||
status = acpi_ut_walk_package_tree(obj_desc, NULL,
|
||||
acpi_ds_init_package_element,
|
||||
NULL);
|
||||
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -89,7 +89,14 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
|
||||
{
|
||||
acpi_size size;
|
||||
|
||||
ACPI_FUNCTION_ENTRY();
|
||||
/* Validate the Node */
|
||||
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Invalid/cached reference target node: %p, descriptor type %d",
|
||||
node, ACPI_GET_DESCRIPTOR_TYPE(node)));
|
||||
return (0);
|
||||
}
|
||||
|
||||
size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
|
||||
return (size);
|
||||
|
@ -614,6 +614,8 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info,
|
||||
|
||||
default: /* Should not get here, type was validated by caller */
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Invalid Package type: %X",
|
||||
package->ret_info.type));
|
||||
return (AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
|
@ -164,6 +164,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
INCREMENT_ARG_LIST(walk_state->arg_types);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Final argument count: %u pass %u\n",
|
||||
walk_state->arg_count,
|
||||
walk_state->pass_number));
|
||||
|
||||
/*
|
||||
* Handle executable code at "module-level". This refers to
|
||||
* executable opcodes that appear outside of any control method.
|
||||
@ -277,6 +282,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
|
||||
AML_NAME_OP)
|
||||
&& (walk_state->pass_number <=
|
||||
ACPI_IMODE_LOAD_PASS2)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
|
||||
walk_state->pass_number,
|
||||
aml_op_start));
|
||||
|
||||
/*
|
||||
* Skip parsing of Buffers and Packages because we don't have
|
||||
* enough info in the first pass to parse them correctly.
|
||||
@ -570,6 +580,10 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
|
||||
|
||||
/* Check for arguments that need to be processed */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
|
||||
"Parseloop: argument count: %u\n",
|
||||
walk_state->arg_count));
|
||||
|
||||
if (walk_state->arg_count) {
|
||||
/*
|
||||
* There are arguments (complex ones), push Op and
|
||||
|
@ -359,6 +359,32 @@ acpi_ps_create_op(struct acpi_walk_state *walk_state,
|
||||
acpi_ps_build_named_op(walk_state, aml_op_start, op,
|
||||
&named_op);
|
||||
acpi_ps_free_op(op);
|
||||
|
||||
#ifdef ACPI_ASL_COMPILER
|
||||
if (acpi_gbl_disasm_flag
|
||||
&& walk_state->opcode == AML_EXTERNAL_OP
|
||||
&& status == AE_NOT_FOUND) {
|
||||
/*
|
||||
* If parsing of AML_EXTERNAL_OP's name path fails, then skip
|
||||
* past this opcode and keep parsing. This is a much better
|
||||
* alternative than to abort the entire disassembler. At this
|
||||
* point, the parser_state is at the end of the namepath of the
|
||||
* external declaration opcode. Setting walk_state->Aml to
|
||||
* walk_state->parser_state.Aml + 2 moves increments the
|
||||
* walk_state->Aml past the object type and the paramcount of the
|
||||
* external opcode. For the error message, only print the AML
|
||||
* offset. We could attempt to print the name but this may cause
|
||||
* a segmentation fault when printing the namepath because the
|
||||
* AML may be incorrect.
|
||||
*/
|
||||
acpi_os_printf
|
||||
("// Invalid external declaration at AML offset 0x%x.\n",
|
||||
walk_state->aml -
|
||||
walk_state->parser_state.aml_start);
|
||||
walk_state->aml = walk_state->parser_state.aml + 2;
|
||||
return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE);
|
||||
}
|
||||
#endif
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
@ -615,7 +615,7 @@ ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)
|
||||
* device we are querying
|
||||
* name - Method name of the resources we want.
|
||||
* (METHOD_NAME__CRS, METHOD_NAME__PRS, or
|
||||
* METHOD_NAME__AEI)
|
||||
* METHOD_NAME__AEI or METHOD_NAME__DMA)
|
||||
* user_function - Called for each resource
|
||||
* context - Passed to user_function
|
||||
*
|
||||
@ -641,11 +641,12 @@ acpi_walk_resources(acpi_handle device_handle,
|
||||
if (!device_handle || !user_function || !name ||
|
||||
(!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
|
||||
!ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) &&
|
||||
!ACPI_COMPARE_NAME(name, METHOD_NAME__AEI))) {
|
||||
!ACPI_COMPARE_NAME(name, METHOD_NAME__AEI) &&
|
||||
!ACPI_COMPARE_NAME(name, METHOD_NAME__DMA))) {
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Get the _CRS/_PRS/_AEI resource list */
|
||||
/* Get the _CRS/_PRS/_AEI/_DMA resource list */
|
||||
|
||||
buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
|
||||
status = acpi_rs_get_method_data(device_handle, name, &buffer);
|
||||
|
@ -50,6 +50,57 @@
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbdata")
|
||||
|
||||
/* Local prototypes */
|
||||
static acpi_status
|
||||
acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index);
|
||||
|
||||
static u8
|
||||
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_compare_tables
|
||||
*
|
||||
* PARAMETERS: table_desc - Table 1 descriptor to be compared
|
||||
* table_index - Index of table 2 to be compared
|
||||
*
|
||||
* RETURN: TRUE if both tables are identical.
|
||||
*
|
||||
* DESCRIPTION: This function compares a table with another table that has
|
||||
* already been installed in the root table list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u8
|
||||
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u8 is_identical;
|
||||
struct acpi_table_header *table;
|
||||
u32 table_length;
|
||||
u8 table_flags;
|
||||
|
||||
status =
|
||||
acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
|
||||
&table, &table_length, &table_flags);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a table match on the entire table length,
|
||||
* not just the header.
|
||||
*/
|
||||
is_identical = (u8)((table_desc->length != table_length ||
|
||||
memcmp(table_desc->pointer, table, table_length)) ?
|
||||
FALSE : TRUE);
|
||||
|
||||
/* Release the acquired table */
|
||||
|
||||
acpi_tb_release_table(table, table_length, table_flags);
|
||||
return (is_identical);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_init_table_descriptor
|
||||
@ -64,6 +115,7 @@ ACPI_MODULE_NAME("tbdata")
|
||||
* DESCRIPTION: Initialize a new table descriptor
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
|
||||
acpi_physical_address address,
|
||||
@ -338,7 +390,7 @@ void acpi_tb_invalidate_table(struct acpi_table_desc *table_desc)
|
||||
acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
|
||||
{
|
||||
|
||||
if (!table_desc->pointer && !acpi_gbl_verify_table_checksum) {
|
||||
if (!table_desc->pointer && !acpi_gbl_enable_table_validation) {
|
||||
/*
|
||||
* Only validates the header of the table.
|
||||
* Note that Length contains the size of the mapping after invoking
|
||||
@ -354,22 +406,100 @@ acpi_status acpi_tb_validate_temp_table(struct acpi_table_desc *table_desc)
|
||||
return (acpi_tb_validate_table(table_desc));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_check_duplication
|
||||
*
|
||||
* PARAMETERS: table_desc - Table descriptor
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Avoid installing duplicated tables. However table override and
|
||||
* user aided dynamic table load is allowed, thus comparing the
|
||||
* address of the table is not sufficient, and checking the entire
|
||||
* table content is required.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static acpi_status
|
||||
acpi_tb_check_duplication(struct acpi_table_desc *table_desc, u32 *table_index)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_check_duplication);
|
||||
|
||||
/* Check if table is already registered */
|
||||
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
|
||||
|
||||
/* Do not compare with unverified tables */
|
||||
|
||||
if (!
|
||||
(acpi_gbl_root_table_list.tables[i].
|
||||
flags & ACPI_TABLE_IS_VERIFIED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a table match on the entire table length,
|
||||
* not just the header.
|
||||
*/
|
||||
if (!acpi_tb_compare_tables(table_desc, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the current mechanism does not unregister a table if it is
|
||||
* dynamically unloaded. The related namespace entries are deleted,
|
||||
* but the table remains in the root table list.
|
||||
*
|
||||
* The assumption here is that the number of different tables that
|
||||
* will be loaded is actually small, and there is minimal overhead
|
||||
* in just keeping the table in case it is needed again.
|
||||
*
|
||||
* If this assumption changes in the future (perhaps on large
|
||||
* machines with many table load/unload operations), tables will
|
||||
* need to be unregistered when they are unloaded, and slots in the
|
||||
* root table list should be reused when empty.
|
||||
*/
|
||||
if (acpi_gbl_root_table_list.tables[i].flags &
|
||||
ACPI_TABLE_IS_LOADED) {
|
||||
|
||||
/* Table is still loaded, this is an error */
|
||||
|
||||
return_ACPI_STATUS(AE_ALREADY_EXISTS);
|
||||
} else {
|
||||
*table_index = i;
|
||||
return_ACPI_STATUS(AE_CTRL_TERMINATE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Indicate no duplication to the caller */
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_verify_temp_table
|
||||
*
|
||||
* PARAMETERS: table_desc - Table descriptor
|
||||
* signature - Table signature to verify
|
||||
* table_index - Where the table index is returned
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: This function is called to validate and verify the table, the
|
||||
* returned table descriptor is in "VALIDATED" state.
|
||||
* Note that 'TableIndex' is required to be set to !NULL to
|
||||
* enable duplication check.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
|
||||
acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
|
||||
char *signature, u32 *table_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
@ -392,9 +522,10 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
|
||||
goto invalidate_and_exit;
|
||||
}
|
||||
|
||||
/* Verify the checksum */
|
||||
if (acpi_gbl_enable_table_validation) {
|
||||
|
||||
/* Verify the checksum */
|
||||
|
||||
if (acpi_gbl_verify_table_checksum) {
|
||||
status =
|
||||
acpi_tb_verify_checksum(table_desc->pointer,
|
||||
table_desc->length);
|
||||
@ -411,9 +542,34 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
|
||||
|
||||
goto invalidate_and_exit;
|
||||
}
|
||||
|
||||
/* Avoid duplications */
|
||||
|
||||
if (table_index) {
|
||||
status =
|
||||
acpi_tb_check_duplication(table_desc, table_index);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (status != AE_CTRL_TERMINATE) {
|
||||
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
|
||||
"%4.4s 0x%8.8X%8.8X"
|
||||
" Table is duplicated",
|
||||
acpi_ut_valid_nameseg
|
||||
(table_desc->signature.
|
||||
ascii) ? table_desc->
|
||||
signature.
|
||||
ascii : "????",
|
||||
ACPI_FORMAT_UINT64
|
||||
(table_desc->address)));
|
||||
}
|
||||
|
||||
goto invalidate_and_exit;
|
||||
}
|
||||
}
|
||||
|
||||
table_desc->flags |= ACPI_TABLE_IS_VERIFIED;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
return_ACPI_STATUS(status);
|
||||
|
||||
invalidate_and_exit:
|
||||
acpi_tb_invalidate_table(table_desc);
|
||||
@ -436,6 +592,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
{
|
||||
struct acpi_table_desc *tables;
|
||||
u32 table_count;
|
||||
u32 current_table_count, max_table_count;
|
||||
u32 i;
|
||||
|
||||
ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
|
||||
|
||||
@ -455,8 +613,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
table_count = acpi_gbl_root_table_list.current_table_count;
|
||||
}
|
||||
|
||||
tables = ACPI_ALLOCATE_ZEROED(((acpi_size)table_count +
|
||||
ACPI_ROOT_TABLE_SIZE_INCREMENT) *
|
||||
max_table_count = table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
|
||||
tables = ACPI_ALLOCATE_ZEROED(((acpi_size)max_table_count) *
|
||||
sizeof(struct acpi_table_desc));
|
||||
if (!tables) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
@ -466,9 +624,16 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
|
||||
/* Copy and free the previous table array */
|
||||
|
||||
current_table_count = 0;
|
||||
if (acpi_gbl_root_table_list.tables) {
|
||||
memcpy(tables, acpi_gbl_root_table_list.tables,
|
||||
(acpi_size)table_count * sizeof(struct acpi_table_desc));
|
||||
for (i = 0; i < table_count; i++) {
|
||||
if (acpi_gbl_root_table_list.tables[i].address) {
|
||||
memcpy(tables + current_table_count,
|
||||
acpi_gbl_root_table_list.tables + i,
|
||||
sizeof(struct acpi_table_desc));
|
||||
current_table_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
|
||||
ACPI_FREE(acpi_gbl_root_table_list.tables);
|
||||
@ -476,8 +641,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
|
||||
}
|
||||
|
||||
acpi_gbl_root_table_list.tables = tables;
|
||||
acpi_gbl_root_table_list.max_table_count =
|
||||
table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
|
||||
acpi_gbl_root_table_list.max_table_count = max_table_count;
|
||||
acpi_gbl_root_table_list.current_table_count = current_table_count;
|
||||
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
@ -818,13 +983,9 @@ acpi_tb_load_table(u32 table_index, struct acpi_namespace_node *parent_node)
|
||||
acpi_ev_update_gpes(owner_id);
|
||||
}
|
||||
|
||||
/* Invoke table handler if present */
|
||||
|
||||
if (acpi_gbl_table_handler) {
|
||||
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
|
||||
acpi_gbl_table_handler_context);
|
||||
}
|
||||
/* Invoke table handler */
|
||||
|
||||
acpi_tb_notify_table(ACPI_TABLE_EVENT_LOAD, table);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@ -894,15 +1055,11 @@ acpi_status acpi_tb_unload_table(u32 table_index)
|
||||
return_ACPI_STATUS(AE_NOT_EXIST);
|
||||
}
|
||||
|
||||
/* Invoke table handler if present */
|
||||
/* Invoke table handler */
|
||||
|
||||
if (acpi_gbl_table_handler) {
|
||||
status = acpi_get_table_by_index(table_index, &table);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
|
||||
table,
|
||||
acpi_gbl_table_handler_context);
|
||||
}
|
||||
status = acpi_get_table_by_index(table_index, &table);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
acpi_tb_notify_table(ACPI_TABLE_EVENT_UNLOAD, table);
|
||||
}
|
||||
|
||||
/* Delete the portion of the namespace owned by this table */
|
||||
@ -918,3 +1075,26 @@ acpi_status acpi_tb_unload_table(u32 table_index)
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL(acpi_tb_unload_table)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_notify_table
|
||||
*
|
||||
* PARAMETERS: event - Table event
|
||||
* table - Validated table pointer
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
* DESCRIPTION: Notify a table event to the users.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void acpi_tb_notify_table(u32 event, void *table)
|
||||
{
|
||||
/* Invoke table handler if present */
|
||||
|
||||
if (acpi_gbl_table_handler) {
|
||||
(void)acpi_gbl_table_handler(event, table,
|
||||
acpi_gbl_table_handler_context);
|
||||
}
|
||||
}
|
||||
|
@ -48,54 +48,6 @@
|
||||
#define _COMPONENT ACPI_TABLES
|
||||
ACPI_MODULE_NAME("tbinstal")
|
||||
|
||||
/* Local prototypes */
|
||||
static u8
|
||||
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_compare_tables
|
||||
*
|
||||
* PARAMETERS: table_desc - Table 1 descriptor to be compared
|
||||
* table_index - Index of table 2 to be compared
|
||||
*
|
||||
* RETURN: TRUE if both tables are identical.
|
||||
*
|
||||
* DESCRIPTION: This function compares a table with another table that has
|
||||
* already been installed in the root table list.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static u8
|
||||
acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
u8 is_identical;
|
||||
struct acpi_table_header *table;
|
||||
u32 table_length;
|
||||
u8 table_flags;
|
||||
|
||||
status =
|
||||
acpi_tb_acquire_table(&acpi_gbl_root_table_list.tables[table_index],
|
||||
&table, &table_length, &table_flags);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a table match on the entire table length,
|
||||
* not just the header.
|
||||
*/
|
||||
is_identical = (u8)((table_desc->length != table_length ||
|
||||
memcmp(table_desc->pointer, table, table_length)) ?
|
||||
FALSE : TRUE);
|
||||
|
||||
/* Release the acquired table */
|
||||
|
||||
acpi_tb_release_table(table, table_length, table_flags);
|
||||
return (is_identical);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_tb_install_table_with_override
|
||||
@ -112,7 +64,6 @@ acpi_tb_compare_tables(struct acpi_table_desc *table_desc, u32 table_index)
|
||||
* table array.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
|
||||
u8 override, u32 *table_index)
|
||||
@ -210,95 +161,29 @@ acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
goto release_and_exit;
|
||||
}
|
||||
|
||||
/* Validate and verify a table before installation */
|
||||
|
||||
status = acpi_tb_verify_temp_table(&new_table_desc, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
goto release_and_exit;
|
||||
}
|
||||
|
||||
/* Acquire the table lock */
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
if (reload) {
|
||||
/*
|
||||
* Validate the incoming table signature.
|
||||
*
|
||||
* 1) Originally, we checked the table signature for "SSDT" or "PSDT".
|
||||
* 2) We added support for OEMx tables, signature "OEM".
|
||||
* 3) Valid tables were encountered with a null signature, so we just
|
||||
* gave up on validating the signature, (05/2008).
|
||||
* 4) We encountered non-AML tables such as the MADT, which caused
|
||||
* interpreter errors and kernel faults. So now, we once again allow
|
||||
* only "SSDT", "OEMx", and now, also a null signature. (05/2011).
|
||||
*/
|
||||
if ((new_table_desc.signature.ascii[0] != 0x00) &&
|
||||
(!ACPI_COMPARE_NAME
|
||||
(&new_table_desc.signature, ACPI_SIG_SSDT))
|
||||
&& (strncmp(new_table_desc.signature.ascii, "OEM", 3))) {
|
||||
ACPI_BIOS_ERROR((AE_INFO,
|
||||
"Table has invalid signature [%4.4s] (0x%8.8X), "
|
||||
"must be SSDT or OEMx",
|
||||
acpi_ut_valid_nameseg(new_table_desc.
|
||||
signature.
|
||||
ascii) ?
|
||||
new_table_desc.signature.
|
||||
ascii : "????",
|
||||
new_table_desc.signature.integer));
|
||||
/* Validate and verify a table before installation */
|
||||
|
||||
status = AE_BAD_SIGNATURE;
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Check if table is already registered */
|
||||
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
|
||||
++i) {
|
||||
status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (status == AE_CTRL_TERMINATE) {
|
||||
/*
|
||||
* Check for a table match on the entire table length,
|
||||
* not just the header.
|
||||
* Table was unloaded, allow it to be reloaded.
|
||||
* As we are going to return AE_OK to the caller, we should
|
||||
* take the responsibility of freeing the input descriptor.
|
||||
* Refill the input descriptor to ensure
|
||||
* acpi_tb_install_table_with_override() can be called again to
|
||||
* indicate the re-installation.
|
||||
*/
|
||||
if (!acpi_tb_compare_tables(&new_table_desc, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: the current mechanism does not unregister a table if it is
|
||||
* dynamically unloaded. The related namespace entries are deleted,
|
||||
* but the table remains in the root table list.
|
||||
*
|
||||
* The assumption here is that the number of different tables that
|
||||
* will be loaded is actually small, and there is minimal overhead
|
||||
* in just keeping the table in case it is needed again.
|
||||
*
|
||||
* If this assumption changes in the future (perhaps on large
|
||||
* machines with many table load/unload operations), tables will
|
||||
* need to be unregistered when they are unloaded, and slots in the
|
||||
* root table list should be reused when empty.
|
||||
*/
|
||||
if (acpi_gbl_root_table_list.tables[i].flags &
|
||||
ACPI_TABLE_IS_LOADED) {
|
||||
|
||||
/* Table is still loaded, this is an error */
|
||||
|
||||
status = AE_ALREADY_EXISTS;
|
||||
goto unlock_and_exit;
|
||||
} else {
|
||||
/*
|
||||
* Table was unloaded, allow it to be reloaded.
|
||||
* As we are going to return AE_OK to the caller, we should
|
||||
* take the responsibility of freeing the input descriptor.
|
||||
* Refill the input descriptor to ensure
|
||||
* acpi_tb_install_table_with_override() can be called again to
|
||||
* indicate the re-installation.
|
||||
*/
|
||||
acpi_tb_uninstall_table(&new_table_desc);
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
*table_index = i;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
acpi_tb_uninstall_table(&new_table_desc);
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
*table_index = i;
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
|
||||
/* Add the table to the global root table list */
|
||||
@ -306,14 +191,10 @@ acpi_tb_install_standard_table(acpi_physical_address address,
|
||||
acpi_tb_install_table_with_override(&new_table_desc, override,
|
||||
table_index);
|
||||
|
||||
/* Invoke table handler if present */
|
||||
/* Invoke table handler */
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
if (acpi_gbl_table_handler) {
|
||||
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_INSTALL,
|
||||
new_table_desc.pointer,
|
||||
acpi_gbl_table_handler_context);
|
||||
}
|
||||
acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer);
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
unlock_and_exit:
|
||||
@ -382,9 +263,11 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
|
||||
|
||||
finish_override:
|
||||
|
||||
/* Validate and verify a table before overriding */
|
||||
|
||||
status = acpi_tb_verify_temp_table(&new_table_desc, NULL);
|
||||
/*
|
||||
* Validate and verify a table before overriding, no nested table
|
||||
* duplication check as it's too complicated and unnecessary.
|
||||
*/
|
||||
status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
@ -167,7 +167,8 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
|
||||
acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
|
||||
{
|
||||
acpi_status status;
|
||||
u32 i;
|
||||
struct acpi_table_desc *table_desc;
|
||||
u32 i, j;
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
|
||||
|
||||
@ -179,6 +180,8 @@ acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
|
||||
return_ACPI_STATUS(AE_SUPPORT);
|
||||
}
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/*
|
||||
* Ensure OS early boot logic, which is required by some hosts. If the
|
||||
* table state is reported to be wrong, developers should fix the
|
||||
@ -186,17 +189,39 @@ acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
|
||||
* early stage.
|
||||
*/
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
|
||||
if (acpi_gbl_root_table_list.tables[i].pointer) {
|
||||
table_desc = &acpi_gbl_root_table_list.tables[i];
|
||||
if (table_desc->pointer) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Table [%4.4s] is not invalidated during early boot stage",
|
||||
acpi_gbl_root_table_list.tables[i].
|
||||
signature.ascii));
|
||||
table_desc->signature.ascii));
|
||||
}
|
||||
}
|
||||
|
||||
if (!acpi_gbl_enable_table_validation) {
|
||||
/*
|
||||
* Now it's safe to do full table validation. We can do deferred
|
||||
* table initilization here once the flag is set.
|
||||
*/
|
||||
acpi_gbl_enable_table_validation = TRUE;
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
|
||||
++i) {
|
||||
table_desc = &acpi_gbl_root_table_list.tables[i];
|
||||
if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) {
|
||||
status =
|
||||
acpi_tb_verify_temp_table(table_desc, NULL,
|
||||
&j);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
acpi_tb_uninstall_table(table_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
|
||||
|
||||
status = acpi_tb_resize_root_table_list();
|
||||
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
|
||||
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@ -369,6 +394,10 @@ void acpi_put_table(struct acpi_table_header *table)
|
||||
|
||||
ACPI_FUNCTION_TRACE(acpi_put_table);
|
||||
|
||||
if (!table) {
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
|
||||
|
||||
/* Walk the root table list */
|
||||
|
@ -206,7 +206,7 @@ acpi_status acpi_tb_load_namespace(void)
|
||||
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
|
||||
table = &acpi_gbl_root_table_list.tables[i];
|
||||
|
||||
if (!acpi_gbl_root_table_list.tables[i].address ||
|
||||
if (!table->address ||
|
||||
(!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_SSDT)
|
||||
&& !ACPI_COMPARE_NAME(table->signature.ascii,
|
||||
ACPI_SIG_PSDT)
|
||||
|
@ -69,8 +69,10 @@ static const char acpi_gbl_hex_to_ascii[] = {
|
||||
|
||||
char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
|
||||
{
|
||||
u64 index;
|
||||
|
||||
return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
|
||||
acpi_ut_short_shift_right(integer, position, &index);
|
||||
return (acpi_gbl_hex_to_ascii[index & 0xF]);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -47,15 +47,6 @@
|
||||
#define _COMPONENT ACPI_UTILITIES
|
||||
ACPI_MODULE_NAME("utmath")
|
||||
|
||||
/*
|
||||
* Optional support for 64-bit double-precision integer divide. This code
|
||||
* is configurable and is implemented in order to support 32-bit kernel
|
||||
* environments where a 64-bit double-precision math library is not available.
|
||||
*
|
||||
* Support for a more normal 64-bit divide/modulo (with check for a divide-
|
||||
* by-zero) appears after this optional section of code.
|
||||
*/
|
||||
#ifndef ACPI_USE_NATIVE_DIVIDE
|
||||
/* Structures used only for 64-bit divide */
|
||||
typedef struct uint64_struct {
|
||||
u32 lo;
|
||||
@ -69,6 +60,217 @@ typedef union uint64_overlay {
|
||||
|
||||
} uint64_overlay;
|
||||
|
||||
/*
|
||||
* Optional support for 64-bit double-precision integer multiply and shift.
|
||||
* This code is configurable and is implemented in order to support 32-bit
|
||||
* kernel environments where a 64-bit double-precision math library is not
|
||||
* available.
|
||||
*/
|
||||
#ifndef ACPI_USE_NATIVE_MATH64
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_multiply
|
||||
*
|
||||
* PARAMETERS: multiplicand - 64-bit multiplicand
|
||||
* multiplier - 32-bit multiplier
|
||||
* out_product - Pointer to where the product is returned
|
||||
*
|
||||
* DESCRIPTION: Perform a short multiply.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
|
||||
{
|
||||
union uint64_overlay multiplicand_ovl;
|
||||
union uint64_overlay product;
|
||||
u32 carry32;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_multiply);
|
||||
|
||||
multiplicand_ovl.full = multiplicand;
|
||||
|
||||
/*
|
||||
* The Product is 64 bits, the carry is always 32 bits,
|
||||
* and is generated by the second multiply.
|
||||
*/
|
||||
ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.hi, multiplier,
|
||||
product.part.hi, carry32);
|
||||
|
||||
ACPI_MUL_64_BY_32(0, multiplicand_ovl.part.lo, multiplier,
|
||||
product.part.lo, carry32);
|
||||
|
||||
product.part.hi += carry32;
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_product) {
|
||||
*out_product = product.full;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_shift_left
|
||||
*
|
||||
* PARAMETERS: operand - 64-bit shift operand
|
||||
* count - 32-bit shift count
|
||||
* out_result - Pointer to where the result is returned
|
||||
*
|
||||
* DESCRIPTION: Perform a short left shift.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
|
||||
{
|
||||
union uint64_overlay operand_ovl;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_shift_left);
|
||||
|
||||
operand_ovl.full = operand;
|
||||
|
||||
if ((count & 63) >= 32) {
|
||||
operand_ovl.part.hi = operand_ovl.part.lo;
|
||||
operand_ovl.part.lo ^= operand_ovl.part.lo;
|
||||
count = (count & 63) - 32;
|
||||
}
|
||||
ACPI_SHIFT_LEFT_64_BY_32(operand_ovl.part.hi,
|
||||
operand_ovl.part.lo, count);
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_result) {
|
||||
*out_result = operand_ovl.full;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_shift_right
|
||||
*
|
||||
* PARAMETERS: operand - 64-bit shift operand
|
||||
* count - 32-bit shift count
|
||||
* out_result - Pointer to where the result is returned
|
||||
*
|
||||
* DESCRIPTION: Perform a short right shift.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
|
||||
{
|
||||
union uint64_overlay operand_ovl;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_shift_right);
|
||||
|
||||
operand_ovl.full = operand;
|
||||
|
||||
if ((count & 63) >= 32) {
|
||||
operand_ovl.part.lo = operand_ovl.part.hi;
|
||||
operand_ovl.part.hi ^= operand_ovl.part.hi;
|
||||
count = (count & 63) - 32;
|
||||
}
|
||||
ACPI_SHIFT_RIGHT_64_BY_32(operand_ovl.part.hi,
|
||||
operand_ovl.part.lo, count);
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_result) {
|
||||
*out_result = operand_ovl.full;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
#else
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_multiply
|
||||
*
|
||||
* PARAMETERS: See function headers above
|
||||
*
|
||||
* DESCRIPTION: Native version of the ut_short_multiply function.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ut_short_multiply(u64 multiplicand, u32 multiplier, u64 *out_product)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_multiply);
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_product) {
|
||||
*out_product = multiplicand * multiplier;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_shift_left
|
||||
*
|
||||
* PARAMETERS: See function headers above
|
||||
*
|
||||
* DESCRIPTION: Native version of the ut_short_shift_left function.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_short_shift_left(u64 operand, u32 count, u64 *out_result)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_shift_left);
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_result) {
|
||||
*out_result = operand << count;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_shift_right
|
||||
*
|
||||
* PARAMETERS: See function headers above
|
||||
*
|
||||
* DESCRIPTION: Native version of the ut_short_shift_right function.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status acpi_ut_short_shift_right(u64 operand, u32 count, u64 *out_result)
|
||||
{
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_short_shift_right);
|
||||
|
||||
/* Return only what was requested */
|
||||
|
||||
if (out_result) {
|
||||
*out_result = operand >> count;
|
||||
}
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Optional support for 64-bit double-precision integer divide. This code
|
||||
* is configurable and is implemented in order to support 32-bit kernel
|
||||
* environments where a 64-bit double-precision math library is not available.
|
||||
*
|
||||
* Support for a more normal 64-bit divide/modulo (with check for a divide-
|
||||
* by-zero) appears after this optional section of code.
|
||||
*/
|
||||
#ifndef ACPI_USE_NATIVE_DIVIDE
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_divide
|
||||
@ -258,6 +460,7 @@ acpi_ut_divide(u64 in_dividend,
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: acpi_ut_short_divide, acpi_ut_divide
|
||||
@ -272,6 +475,7 @@ acpi_ut_divide(u64 in_dividend,
|
||||
* perform the divide.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
acpi_status
|
||||
acpi_ut_short_divide(u64 in_dividend,
|
||||
u32 divisor, u64 *out_quotient, u32 *out_remainder)
|
||||
|
@ -224,7 +224,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Walk through a package
|
||||
* DESCRIPTION: Walk through a package, including subpackages
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -236,8 +236,8 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
|
||||
acpi_status status = AE_OK;
|
||||
union acpi_generic_state *state_list = NULL;
|
||||
union acpi_generic_state *state;
|
||||
u32 this_index;
|
||||
union acpi_operand_object *this_source_obj;
|
||||
u32 this_index;
|
||||
|
||||
ACPI_FUNCTION_TRACE(ut_walk_package_tree);
|
||||
|
||||
@ -251,8 +251,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
|
||||
/* Get one element of the package */
|
||||
|
||||
this_index = state->pkg.index;
|
||||
this_source_obj = (union acpi_operand_object *)
|
||||
this_source_obj =
|
||||
state->pkg.source_object->package.elements[this_index];
|
||||
state->pkg.this_target_obj =
|
||||
&state->pkg.source_object->package.elements[this_index];
|
||||
|
||||
/*
|
||||
* Check for:
|
||||
@ -339,6 +341,8 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
|
||||
|
||||
/* We should never get here */
|
||||
|
||||
ACPI_ERROR((AE_INFO, "State list did not terminate correctly"));
|
||||
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
|
@ -483,6 +483,11 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
|
||||
|
||||
/* A namespace node should never get here */
|
||||
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Received a namespace node [%4.4s] "
|
||||
"where an operand object is required",
|
||||
ACPI_CAST_PTR(struct acpi_namespace_node,
|
||||
internal_object)->name.ascii));
|
||||
return_ACPI_STATUS(AE_AML_INTERNAL);
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
|
||||
u64 number = 0;
|
||||
|
||||
while (isdigit((int)*string)) {
|
||||
number *= 10;
|
||||
acpi_ut_short_multiply(number, 10, &number);
|
||||
number += *(string++) - '0';
|
||||
}
|
||||
|
||||
@ -286,7 +286,7 @@ static char *acpi_ut_format_number(char *string,
|
||||
/* Generate full string in reverse order */
|
||||
|
||||
pos = acpi_ut_put_number(reversed_string, number, base, upper);
|
||||
i = ACPI_PTR_DIFF(pos, reversed_string);
|
||||
i = (s32)ACPI_PTR_DIFF(pos, reversed_string);
|
||||
|
||||
/* Printing 100 using %2d gives "100", not "00" */
|
||||
|
||||
@ -475,7 +475,7 @@ int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
|
||||
if (!s) {
|
||||
s = "<NULL>";
|
||||
}
|
||||
length = acpi_ut_bound_string_length(s, precision);
|
||||
length = (s32)acpi_ut_bound_string_length(s, precision);
|
||||
if (!(type & ACPI_FORMAT_LEFT)) {
|
||||
while (length < width--) {
|
||||
pos =
|
||||
@ -579,7 +579,7 @@ int vsnprintf(char *string, acpi_size size, const char *format, va_list args)
|
||||
}
|
||||
}
|
||||
|
||||
return (ACPI_PTR_DIFF(pos, string));
|
||||
return ((int)ACPI_PTR_DIFF(pos, string));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -237,6 +237,13 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
|
||||
return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't attempt to perform any validation on the 2nd byte.
|
||||
* Although all known ASL compilers insert a zero for the 2nd
|
||||
* byte, it can also be a checksum (as per the ACPI spec),
|
||||
* and this is occasionally seen in the field. July 2017.
|
||||
*/
|
||||
|
||||
/* Return the pointer to the end_tag if requested */
|
||||
|
||||
if (!user_function) {
|
||||
|
@ -226,7 +226,7 @@ union acpi_generic_state *acpi_ut_create_update_state(union acpi_operand_object
|
||||
|
||||
union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
|
||||
void *external_object,
|
||||
u16 index)
|
||||
u32 index)
|
||||
{
|
||||
union acpi_generic_state *state;
|
||||
|
||||
|
@ -276,8 +276,8 @@ static u64 acpi_ut_strtoul_base10(char *string, u32 flags)
|
||||
|
||||
/* Convert and insert (add) the decimal digit */
|
||||
|
||||
next_value =
|
||||
(return_value * 10) + (ascii_digit - ACPI_ASCII_ZERO);
|
||||
acpi_ut_short_multiply(return_value, 10, &next_value);
|
||||
next_value += (ascii_digit - ACPI_ASCII_ZERO);
|
||||
|
||||
/* Check for overflow (32 or 64 bit) - return current converted value */
|
||||
|
||||
@ -335,9 +335,8 @@ static u64 acpi_ut_strtoul_base16(char *string, u32 flags)
|
||||
|
||||
/* Convert and insert the hex digit */
|
||||
|
||||
return_value =
|
||||
(return_value << 4) |
|
||||
acpi_ut_ascii_char_to_hex(ascii_digit);
|
||||
acpi_ut_short_shift_left(return_value, 4, &return_value);
|
||||
return_value |= acpi_ut_ascii_char_to_hex(ascii_digit);
|
||||
|
||||
string++;
|
||||
valid_digits++;
|
||||
|
@ -591,6 +591,10 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
if (!acpi_gbl_global_list) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
element = acpi_gbl_global_list->list_head;
|
||||
while (element) {
|
||||
if ((element->component & component) &&
|
||||
@ -602,7 +606,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
|
||||
|
||||
if (element->size <
|
||||
sizeof(struct acpi_common_descriptor)) {
|
||||
acpi_os_printf("%p Length 0x%04X %9.9s-%u "
|
||||
acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
|
||||
"[Not a Descriptor - too small]\n",
|
||||
descriptor, element->size,
|
||||
element->module, element->line);
|
||||
@ -612,7 +616,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
|
||||
if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
|
||||
ACPI_DESC_TYPE_CACHED) {
|
||||
acpi_os_printf
|
||||
("%p Length 0x%04X %9.9s-%u [%s] ",
|
||||
("%p Length 0x%04X %9.9s-%4.4u [%s] ",
|
||||
descriptor, element->size,
|
||||
element->module, element->line,
|
||||
acpi_ut_get_descriptor_name
|
||||
@ -705,6 +709,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
|
||||
element = element->next;
|
||||
}
|
||||
|
||||
exit:
|
||||
(void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
|
||||
|
||||
/* Print summary */
|
||||
|
@ -995,9 +995,6 @@ void __init acpi_early_init(void)
|
||||
|
||||
printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION);
|
||||
|
||||
/* It's safe to verify table checksums during late stage */
|
||||
acpi_gbl_verify_table_checksum = TRUE;
|
||||
|
||||
/* enable workarounds, unless strict ACPI spec. compliance */
|
||||
if (!acpi_strict)
|
||||
acpi_gbl_enable_interpreter_slack = TRUE;
|
||||
|
@ -105,16 +105,17 @@ int __init parse_spcr(bool earlycon)
|
||||
}
|
||||
|
||||
if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
|
||||
switch (table->serial_port.access_width) {
|
||||
switch (ACPI_ACCESS_BIT_WIDTH((
|
||||
table->serial_port.access_width))) {
|
||||
default:
|
||||
pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n");
|
||||
case ACPI_ACCESS_SIZE_BYTE:
|
||||
case 8:
|
||||
iotype = "mmio";
|
||||
break;
|
||||
case ACPI_ACCESS_SIZE_WORD:
|
||||
case 16:
|
||||
iotype = "mmio16";
|
||||
break;
|
||||
case ACPI_ACCESS_SIZE_DWORD:
|
||||
case 32:
|
||||
iotype = "mmio32";
|
||||
break;
|
||||
}
|
||||
|
@ -740,10 +740,10 @@ int __init acpi_table_init(void)
|
||||
|
||||
if (acpi_verify_table_checksum) {
|
||||
pr_info("Early table checksum verification enabled\n");
|
||||
acpi_gbl_verify_table_checksum = TRUE;
|
||||
acpi_gbl_enable_table_validation = TRUE;
|
||||
} else {
|
||||
pr_info("Early table checksum verification disabled\n");
|
||||
acpi_gbl_verify_table_checksum = FALSE;
|
||||
acpi_gbl_enable_table_validation = FALSE;
|
||||
}
|
||||
|
||||
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#define METHOD_NAME__CLS "_CLS"
|
||||
#define METHOD_NAME__CRS "_CRS"
|
||||
#define METHOD_NAME__DDN "_DDN"
|
||||
#define METHOD_NAME__DMA "_DMA"
|
||||
#define METHOD_NAME__HID "_HID"
|
||||
#define METHOD_NAME__INI "_INI"
|
||||
#define METHOD_NAME__PLD "_PLD"
|
||||
|
@ -58,10 +58,10 @@
|
||||
#include <acpi/actypes.h> /* ACPICA data types and structures */
|
||||
#include <acpi/acexcep.h> /* ACPICA exceptions */
|
||||
#include <acpi/actbl.h> /* ACPI table definitions */
|
||||
#include <acpi/acoutput.h> /* Error output and Debug macros */
|
||||
#include <acpi/acrestyp.h> /* Resource Descriptor structs */
|
||||
#include <acpi/platform/acenvex.h> /* Extra environment-specific items */
|
||||
#include <acpi/acoutput.h> /* Error output and Debug macros */
|
||||
#include <acpi/acpiosxf.h> /* OSL interfaces (ACPICA-to-OS) */
|
||||
#include <acpi/acpixf.h> /* ACPI core subsystem external interfaces */
|
||||
#include <acpi/platform/acenvex.h> /* Extra environment-specific items */
|
||||
|
||||
#endif /* __ACPI_H__ */
|
||||
|
@ -46,7 +46,7 @@
|
||||
|
||||
/* Current ACPICA subsystem version in YYYYMMDD format */
|
||||
|
||||
#define ACPI_CA_VERSION 0x20170531
|
||||
#define ACPI_CA_VERSION 0x20170728
|
||||
|
||||
#include <acpi/acconfig.h>
|
||||
#include <acpi/actypes.h>
|
||||
@ -160,13 +160,14 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_create_osi_method, TRUE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_use_default_register_widths, TRUE);
|
||||
|
||||
/*
|
||||
* Whether or not to verify the table checksum before installation. Set
|
||||
* this to TRUE to verify the table checksum before install it to the table
|
||||
* manager. Note that enabling this option causes errors to happen in some
|
||||
* OSPMs during early initialization stages. Default behavior is to do such
|
||||
* verification.
|
||||
* Whether or not to validate (map) an entire table to verify
|
||||
* checksum/duplication in early stage before install. Set this to TRUE to
|
||||
* allow early table validation before install it to the table manager.
|
||||
* Note that enabling this option causes errors to happen in some OSPMs
|
||||
* during early initialization stages. Default behavior is to allow such
|
||||
* validation.
|
||||
*/
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_verify_table_checksum, TRUE);
|
||||
ACPI_INIT_GLOBAL(u8, acpi_gbl_enable_table_validation, TRUE);
|
||||
|
||||
/*
|
||||
* Optionally enable output from the AML Debug Object.
|
||||
|
@ -377,13 +377,6 @@ struct acpi_resource_generic_register {
|
||||
u64 address;
|
||||
};
|
||||
|
||||
/* Generic Address Space Access Sizes */
|
||||
#define ACPI_ACCESS_SIZE_UNDEFINED 0
|
||||
#define ACPI_ACCESS_SIZE_BYTE 1
|
||||
#define ACPI_ACCESS_SIZE_WORD 2
|
||||
#define ACPI_ACCESS_SIZE_DWORD 3
|
||||
#define ACPI_ACCESS_SIZE_QWORD 4
|
||||
|
||||
struct acpi_resource_gpio {
|
||||
u8 revision_id;
|
||||
u8 connection_type;
|
||||
|
@ -394,6 +394,7 @@ struct acpi_table_desc {
|
||||
#define ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL (1) /* Physical address, internally mapped */
|
||||
#define ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL (2) /* Virtual address, internallly allocated */
|
||||
#define ACPI_TABLE_ORIGIN_MASK (3)
|
||||
#define ACPI_TABLE_IS_VERIFIED (4)
|
||||
#define ACPI_TABLE_IS_LOADED (8)
|
||||
|
||||
/*
|
||||
|
@ -76,6 +76,7 @@
|
||||
#define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */
|
||||
#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
|
||||
#define ACPI_SIG_MTMR "MTMR" /* MID Timer table */
|
||||
#define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */
|
||||
#define ACPI_SIG_SLIC "SLIC" /* Software Licensing Description Table */
|
||||
#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */
|
||||
#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */
|
||||
@ -664,7 +665,7 @@ struct acpi_ibft_target {
|
||||
* IORT - IO Remapping Table
|
||||
*
|
||||
* Conforms to "IO Remapping Table System Software on ARM Platforms",
|
||||
* Document number: ARM DEN 0049B, October 2015
|
||||
* Document number: ARM DEN 0049C, May 2017
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -779,6 +780,8 @@ struct acpi_iort_smmu {
|
||||
#define ACPI_IORT_SMMU_V2 0x00000001 /* Generic SMMUv2 */
|
||||
#define ACPI_IORT_SMMU_CORELINK_MMU400 0x00000002 /* ARM Corelink MMU-400 */
|
||||
#define ACPI_IORT_SMMU_CORELINK_MMU500 0x00000003 /* ARM Corelink MMU-500 */
|
||||
#define ACPI_IORT_SMMU_CORELINK_MMU401 0x00000004 /* ARM Corelink MMU-401 */
|
||||
#define ACPI_IORT_SMMU_CAVIUM_THUNDERX 0x00000005 /* Cavium thunder_x SMMUv2 */
|
||||
|
||||
/* Masks for Flags field above */
|
||||
|
||||
@ -799,17 +802,27 @@ struct acpi_iort_smmu_v3 {
|
||||
u32 flags;
|
||||
u32 reserved;
|
||||
u64 vatos_address;
|
||||
u32 model; /* O: generic SMMUv3 */
|
||||
u32 model;
|
||||
u32 event_gsiv;
|
||||
u32 pri_gsiv;
|
||||
u32 gerr_gsiv;
|
||||
u32 sync_gsiv;
|
||||
u8 pxm;
|
||||
u8 reserved1;
|
||||
u16 reserved2;
|
||||
};
|
||||
|
||||
/* Values for Model field above */
|
||||
|
||||
#define ACPI_IORT_SMMU_V3_GENERIC 0x00000000 /* Generic SMMUv3 */
|
||||
#define ACPI_IORT_SMMU_V3_HISILICON_HI161X 0x00000001 /* hi_silicon Hi161x SMMUv3 */
|
||||
#define ACPI_IORT_SMMU_V3_CAVIUM_CN99XX 0x00000002 /* Cavium CN99xx SMMUv3 */
|
||||
|
||||
/* Masks for Flags field above */
|
||||
|
||||
#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1)
|
||||
#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (1<<1)
|
||||
#define ACPI_IORT_SMMU_V3_PXM_VALID (1<<3)
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -1120,6 +1133,19 @@ struct acpi_mtmr_entry {
|
||||
u32 irq;
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* SDEI - Software Delegated Exception Interface Descriptor Table
|
||||
*
|
||||
* Conforms to "Software Delegated Exception Interface (SDEI)" ARM DEN0054A,
|
||||
* May 8th, 2017. Copyright 2017 ARM Ltd.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
struct acpi_table_sdei {
|
||||
struct acpi_table_header header; /* Common ACPI table header */
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* SLIC - Software Licensing Description Table
|
||||
|
@ -166,6 +166,7 @@ typedef u64 acpi_physical_address;
|
||||
#define ACPI_SIZE_MAX ACPI_UINT64_MAX
|
||||
|
||||
#define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */
|
||||
#define ACPI_USE_NATIVE_MATH64 /* Has native 64-bit integer support */
|
||||
|
||||
/*
|
||||
* In the case of the Itanium Processor Family (IPF), the hardware does not
|
||||
@ -554,6 +555,13 @@ typedef u64 acpi_integer;
|
||||
#define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, 8))
|
||||
#define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8))
|
||||
|
||||
/*
|
||||
* Algorithm to obtain access bit width.
|
||||
* Can be used with access_width of struct acpi_generic_address and access_size of
|
||||
* struct acpi_resource_generic_register.
|
||||
*/
|
||||
#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + 2))
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Miscellaneous constants
|
||||
|
@ -288,6 +288,11 @@
|
||||
#define ACPI_INLINE
|
||||
#endif
|
||||
|
||||
/* Use ordered initialization if compiler doesn't support designated. */
|
||||
#ifndef ACPI_STRUCT_INIT
|
||||
#define ACPI_STRUCT_INIT(field, value) value
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Configurable calling conventions:
|
||||
*
|
||||
@ -382,8 +387,4 @@
|
||||
#define ACPI_INIT_FUNCTION
|
||||
#endif
|
||||
|
||||
#ifndef ACPI_STRUCT_INIT
|
||||
#define ACPI_STRUCT_INIT(field, value) value
|
||||
#endif
|
||||
|
||||
#endif /* __ACENV_H__ */
|
||||
|
@ -84,4 +84,8 @@ typedef __builtin_va_list va_list;
|
||||
|
||||
#define COMPILER_VA_MACRO 1
|
||||
|
||||
/* GCC supports native multiply/shift on 32-bit platforms */
|
||||
|
||||
#define ACPI_USE_NATIVE_MATH64
|
||||
|
||||
#endif /* __ACGCC_H__ */
|
||||
|
@ -128,6 +128,7 @@
|
||||
/* Host-dependent types and defines for in-kernel ACPICA */
|
||||
|
||||
#define ACPI_MACHINE_WIDTH BITS_PER_LONG
|
||||
#define ACPI_USE_NATIVE_MATH64
|
||||
#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol);
|
||||
#define strtoul simple_strtoul
|
||||
|
||||
@ -178,6 +179,9 @@
|
||||
#define ACPI_MSG_BIOS_ERROR KERN_ERR "ACPI BIOS Error (bug): "
|
||||
#define ACPI_MSG_BIOS_WARNING KERN_WARNING "ACPI BIOS Warning (bug): "
|
||||
|
||||
/*
|
||||
* Linux wants to use designated initializers for function pointer structs.
|
||||
*/
|
||||
#define ACPI_STRUCT_INIT(field, value) .field = value
|
||||
|
||||
#else /* !__KERNEL__ */
|
||||
@ -213,6 +217,7 @@
|
||||
#define COMPILER_DEPENDENT_INT64 long long
|
||||
#define COMPILER_DEPENDENT_UINT64 unsigned long long
|
||||
#define ACPI_USE_NATIVE_DIVIDE
|
||||
#define ACPI_USE_NATIVE_MATH64
|
||||
#endif
|
||||
|
||||
#ifndef __cdecl
|
||||
|
@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)
|
||||
|
||||
/* Skip NULL entries in RSDT/XSDT */
|
||||
|
||||
if (!table_address) {
|
||||
if (table_address == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
|
||||
u8 number_of_tables;
|
||||
u8 item_size;
|
||||
u32 current_instance = 0;
|
||||
acpi_physical_address table_address = 0;
|
||||
acpi_physical_address table_address;
|
||||
acpi_physical_address first_table_address = 0;
|
||||
u32 table_length = 0;
|
||||
acpi_status status = AE_OK;
|
||||
u32 i;
|
||||
@ -820,9 +821,10 @@ osl_get_bios_table(char *signature,
|
||||
ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) ||
|
||||
ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
|
||||
ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
|
||||
if (instance > 0) {
|
||||
return (AE_LIMIT);
|
||||
}
|
||||
|
||||
find_next_instance:
|
||||
|
||||
table_address = 0;
|
||||
|
||||
/*
|
||||
* Get the appropriate address, either 32-bit or 64-bit. Be very
|
||||
@ -830,41 +832,66 @@ osl_get_bios_table(char *signature,
|
||||
* Note: The 64-bit addresses have priority.
|
||||
*/
|
||||
if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
|
||||
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) &&
|
||||
gbl_fadt->Xdsdt) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->Xdsdt;
|
||||
} else
|
||||
if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT)
|
||||
&& gbl_fadt->dsdt) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->dsdt;
|
||||
if (current_instance < 2) {
|
||||
if ((gbl_fadt->header.length >=
|
||||
MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
|
||||
&& current_instance == 0) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->
|
||||
Xdsdt;
|
||||
} else
|
||||
if ((gbl_fadt->header.length >=
|
||||
MIN_FADT_FOR_DSDT)
|
||||
&& gbl_fadt->dsdt !=
|
||||
first_table_address) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->
|
||||
dsdt;
|
||||
}
|
||||
}
|
||||
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
|
||||
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) &&
|
||||
gbl_fadt->Xfacs) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->Xfacs;
|
||||
} else
|
||||
if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS)
|
||||
&& gbl_fadt->facs) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->facs;
|
||||
if (current_instance < 2) {
|
||||
if ((gbl_fadt->header.length >=
|
||||
MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
|
||||
&& current_instance == 0) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->
|
||||
Xfacs;
|
||||
} else
|
||||
if ((gbl_fadt->header.length >=
|
||||
MIN_FADT_FOR_FACS)
|
||||
&& gbl_fadt->facs !=
|
||||
first_table_address) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_fadt->
|
||||
facs;
|
||||
}
|
||||
}
|
||||
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
|
||||
if (!gbl_revision) {
|
||||
return (AE_BAD_SIGNATURE);
|
||||
}
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_rsdp.
|
||||
xsdt_physical_address;
|
||||
if (current_instance == 0) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_rsdp.
|
||||
xsdt_physical_address;
|
||||
}
|
||||
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_rsdp.
|
||||
rsdt_physical_address;
|
||||
if (current_instance == 0) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_rsdp.
|
||||
rsdt_physical_address;
|
||||
}
|
||||
} else {
|
||||
table_address = (acpi_physical_address)gbl_rsdp_address;
|
||||
signature = ACPI_SIG_RSDP;
|
||||
if (current_instance == 0) {
|
||||
table_address =
|
||||
(acpi_physical_address)gbl_rsdp_address;
|
||||
signature = ACPI_SIG_RSDP;
|
||||
}
|
||||
}
|
||||
|
||||
if (table_address == 0) {
|
||||
goto exit_find_table;
|
||||
}
|
||||
|
||||
/* Now we can get the requested special table */
|
||||
@ -875,6 +902,18 @@ osl_get_bios_table(char *signature,
|
||||
}
|
||||
|
||||
table_length = ap_get_table_length(mapped_table);
|
||||
if (first_table_address == 0) {
|
||||
first_table_address = table_address;
|
||||
}
|
||||
|
||||
/* Match table instance */
|
||||
|
||||
if (current_instance != instance) {
|
||||
osl_unmap_table(mapped_table);
|
||||
mapped_table = NULL;
|
||||
current_instance++;
|
||||
goto find_next_instance;
|
||||
}
|
||||
} else { /* Case for a normal ACPI table */
|
||||
|
||||
if (osl_can_use_xsdt()) {
|
||||
@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,
|
||||
|
||||
/* Skip NULL entries in RSDT/XSDT */
|
||||
|
||||
if (!table_address) {
|
||||
if (table_address == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
|
||||
}
|
||||
}
|
||||
|
||||
exit_find_table:
|
||||
|
||||
if (!mapped_table) {
|
||||
return (AE_LIMIT);
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ static int ap_is_existing_file(char *pathname);
|
||||
|
||||
static int ap_is_existing_file(char *pathname)
|
||||
{
|
||||
#ifndef _GNU_EFI
|
||||
#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
|
||||
struct stat stat_info;
|
||||
|
||||
if (!stat(pathname, &stat_info)) {
|
||||
|
@ -300,7 +300,7 @@ static int ap_do_options(int argc, char **argv)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef _GNU_EFI
|
||||
#if !defined(_GNU_EFI) && !defined(_EDK2_EFI)
|
||||
int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
|
||||
#else
|
||||
int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
|
||||
|
Loading…
Reference in New Issue
Block a user