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:
Rafael J. Wysocki 2017-09-03 23:53:05 +02:00
commit b2a84eedca
55 changed files with 1475 additions and 676 deletions

View file

@ -18,6 +18,7 @@ acpi-y := \
dsmthdat.o \ dsmthdat.o \
dsobject.o \ dsobject.o \
dsopcode.o \ dsopcode.o \
dspkginit.o \
dsutils.o \ dsutils.o \
dswexec.o \ dswexec.o \
dswload.o \ dswload.o \

View file

@ -114,6 +114,8 @@ ac_get_all_tables_from_file(char *filename,
u8 get_only_aml_tables, u8 get_only_aml_tables,
struct acpi_new_table_desc **return_list_head); 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); u8 ac_is_file_binary(FILE * file);
acpi_status ac_validate_table_header(FILE * file, long table_offset); acpi_status ac_validate_table_header(FILE * file, long table_offset);

View file

@ -237,6 +237,11 @@ acpi_ds_initialize_objects(u32 table_index,
* dsobject - Parser/Interpreter interface - object initialization and conversion * dsobject - Parser/Interpreter interface - object initialization and conversion
*/ */
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);
acpi_status
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, union acpi_parse_object *op,
u32 buffer_length, u32 buffer_length,
@ -258,6 +263,14 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state,
struct acpi_namespace_node *node, struct acpi_namespace_node *node,
union acpi_parse_object *op); 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 * dsutils - Parser/Interpreter interface utility routines
*/ */

View file

@ -199,6 +199,7 @@ struct acpi_namespace_node {
#define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */ #define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */
#define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (install_method) */ #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_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_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 */ #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 * Pkg state - used to traverse nested package structures
*/ */
struct acpi_pkg_state { struct acpi_pkg_state {
ACPI_STATE_COMMON u16 index; ACPI_STATE_COMMON u32 index;
union acpi_operand_object *source_object; union acpi_operand_object *source_object;
union acpi_operand_object *dest_object; union acpi_operand_object *dest_object;
struct acpi_walk_state *walk_state; struct acpi_walk_state *walk_state;
@ -907,7 +908,7 @@ union acpi_parse_object {
struct asl_comment_state { struct asl_comment_state {
u8 comment_type; u8 comment_type;
u32 spaces_before; 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; union acpi_parse_object *parsing_paren_brace_node;
u8 capture_comments; u8 capture_comments;
}; };

View file

@ -122,7 +122,9 @@ struct acpi_object_integer {
_type *pointer; \ _type *pointer; \
u32 length; 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 */ 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 *notify_list[2]; /* Handlers for system/device notifies */\
union acpi_operand_object *handler; /* Handler for Address space */ 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}; ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
struct acpi_object_device { struct acpi_object_device {
@ -258,7 +262,9 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
u8 access_length; /* For serial regions/fields */ 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) */ 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 { struct acpi_object_reference {
ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */ ACPI_OBJECT_COMMON_HEADER u8 class; /* Reference Class */
u8 target_type; /* Used for Index Op */ 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 */ void *object; /* name_op=>HANDLE to obj, index_op=>union acpi_operand_object */
struct acpi_namespace_node *node; /* ref_of or Namepath */ struct acpi_namespace_node *node; /* ref_of or Namepath */
union acpi_operand_object **where; /* Target of Index */ union acpi_operand_object **where; /* Target of Index */
u8 *index_pointer; /* Used for Buffers and Strings */ 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 */ u32 value; /* Used for Local/Arg/Index/ddb_handle */
}; };

View file

@ -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_validate_temp_table(struct acpi_table_desc *table_desc);
acpi_status 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); 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); acpi_status acpi_tb_unload_table(u32 table_index);
void acpi_tb_notify_table(u32 event, void *table);
void acpi_tb_terminate(void); void acpi_tb_terminate(void);
acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index); acpi_status acpi_tb_delete_namespace_by_owner(u32 table_index);

View file

@ -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, union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
void *external_object, void *external_object,
u16 index); u32 index);
acpi_status acpi_status
acpi_ut_create_update_state_and_push(union acpi_operand_object *object, 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, acpi_ut_short_divide(u64 in_dividend,
u32 divisor, u64 *out_quotient, u32 *out_remainder); 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 * utmisc
*/ */

View file

@ -310,7 +310,7 @@ dump_node:
} }
else { else {
acpi_os_printf("Object (%p) Pathname: %s\n", acpi_os_printf("Object %p: Namespace Node - Pathname: %s\n",
node, (char *)ret_buf.pointer); node, (char *)ret_buf.pointer);
} }
@ -326,7 +326,7 @@ dump_node:
obj_desc = acpi_ns_get_attached_object(node); obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) { if (obj_desc) {
acpi_os_printf("\nAttached Object (%p):\n", obj_desc); acpi_os_printf("\nAttached Object %p:", obj_desc);
if (!acpi_os_readable if (!acpi_os_readable
(obj_desc, sizeof(union acpi_operand_object))) { (obj_desc, sizeof(union acpi_operand_object))) {
acpi_os_printf acpi_os_printf
@ -335,9 +335,36 @@ dump_node:
return; return;
} }
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, acpi_ut_debug_dump_buffer((void *)obj_desc,
sizeof(union acpi_operand_object), sizeof(struct
acpi_namespace_node),
display, ACPI_UINT32_MAX); 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); acpi_ex_dump_object_descriptor(obj_desc, 1);
} }
} }

View file

@ -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 */ /* Execute flag should always be set when this function is entered */
if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
ACPI_ERROR((AE_INFO, "Parse execute mode is not set"));
return_ACPI_STATUS(AE_AML_INTERNAL); 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); return_ACPI_STATUS(AE_OK);
} }
ACPI_ERROR((AE_INFO, "Parse deferred mode is not set"));
return_ACPI_STATUS(AE_AML_INTERNAL); return_ACPI_STATUS(AE_AML_INTERNAL);
} }

View file

@ -52,12 +52,6 @@
#define _COMPONENT ACPI_DISPATCHER #define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dsobject") 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 #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! * Simple objects are any objects other than a package object!
* *
******************************************************************************/ ******************************************************************************/
acpi_status
static acpi_status
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
union acpi_parse_object *op, union acpi_parse_object *op,
union acpi_operand_object **obj_desc_ptr) union acpi_operand_object **obj_desc_ptr)
{ {
union acpi_operand_object *obj_desc; union acpi_operand_object *obj_desc;
acpi_status status; acpi_status status;
acpi_object_type type;
ACPI_FUNCTION_TRACE(ds_build_internal_object); 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) { if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
/* /*
* This is a named object reference. If this name was * This is a named object reference. If this name was
* previously looked up in the namespace, it was stored in this op. * previously looked up in the namespace, it was stored in
* Otherwise, go ahead and look it up now * this op. Otherwise, go ahead and look it up now
*/ */
if (!op->common.node) { if (!op->common.node) {
/* Check if we are resolving a named reference within a package */
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, status = acpi_ns_lookup(walk_state->scope_info,
op->common.value.string, op->common.value.string,
ACPI_TYPE_ANY, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE, ACPI_IMODE_EXECUTE,
ACPI_NS_SEARCH_PARENT | ACPI_NS_SEARCH_PARENT |
ACPI_NS_DONT_OPEN_SCOPE, NULL, ACPI_NS_DONT_OPEN_SCOPE,
ACPI_CAST_INDIRECT_PTR(struct NULL,
acpi_namespace_node, ACPI_CAST_INDIRECT_PTR
&(op->
common.
node)));
if (ACPI_FAILURE(status)) {
/* 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 {
ACPI_ERROR_NAMESPACE(op->common.value.
string, 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 (struct
acpi_namespace_node, acpi_namespace_node,
&obj_desc), &(op->common.node)));
walk_state);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(op->common.value.
string, status);
return_ACPI_STATUS(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 */ /* Create and init a new internal ACPI object */
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info 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); 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; *obj_desc_ptr = obj_desc;
return_ACPI_STATUS(status); 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); 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 * 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: 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 = obj_desc->package.node =
ACPI_CAST_PTR(struct acpi_namespace_node, ACPI_CAST_PTR(struct acpi_namespace_node,
walk_state->operands[0]); 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_start = op->named.data;
obj_desc->package.aml_length = op->named.length; obj_desc->package.aml_length = op->named.length;
break; break;
@ -818,9 +552,11 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
/* Node was saved in Op */ /* Node was saved in Op */
obj_desc->reference.node = op->common.node; obj_desc->reference.node = op->common.node;
obj_desc->reference.class = ACPI_REFCLASS_NAME;
if (op->common.node) {
obj_desc->reference.object = obj_desc->reference.object =
op->common.node->object; op->common.node->object;
obj_desc->reference.class = ACPI_REFCLASS_NAME; }
break; break;
case AML_DEBUG_OP: case AML_DEBUG_OP:

View file

@ -599,6 +599,15 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
*/ */
walk_state->operand_index = walk_state->num_operands; 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); status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);

View 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;
}

View file

@ -87,32 +87,27 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
target_node->object); target_node->object);
} }
/* /* Ensure that the target node is valid */
* For objects that can never change (i.e., the NS node will
* permanently point to the same object), we can simply attach if (!target_node) {
* the object to the new NS node. For other objects (such as return_ACPI_STATUS(AE_NULL_OBJECT);
* Integers, buffers, etc.), we have to point the Alias node }
* to the original Node.
*/ /* Construct the alias object (a namespace node) */
switch (target_node->type) { switch (target_node->type) {
case ACPI_TYPE_METHOD:
/* 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:
/* /*
* These types open a new scope, so we need the NS node in order to access * Control method aliases need to be differentiated with
* any children. * a special type
*/ */
case ACPI_TYPE_DEVICE: alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
case ACPI_TYPE_POWER: break;
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL: default:
case ACPI_TYPE_LOCAL_SCOPE:
/* /*
* All other object types.
*
* The new alias has the type ALIAS and points to the original * The new alias has the type ALIAS and points to the original
* NS node, not the object itself. * 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 = alias_node->object =
ACPI_CAST_PTR(union acpi_operand_object, target_node); ACPI_CAST_PTR(union acpi_operand_object, target_node);
break; 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 */ /* 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); return_ACPI_STATUS(status);
} }

View file

@ -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_INIT, ACPI_EXD_TABLE_SIZE(acpi_ex_dump_package), NULL},
{ACPI_EXD_NODE, ACPI_EXD_OFFSET(package.node), "Parent Node"}, {ACPI_EXD_NODE, ACPI_EXD_OFFSET(package.node), "Parent Node"},
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET(package.flags), "Flags"}, {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_POINTER, ACPI_EXD_OFFSET(package.elements), "Element List"},
{ACPI_EXD_PACKAGE, 0, NULL} {ACPI_EXD_PACKAGE, 0, NULL}
}; };
@ -384,6 +384,10 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
count = info->offset; count = info->offset;
while (count) { while (count) {
if (!obj_desc) {
return;
}
target = ACPI_ADD_PTR(u8, obj_desc, info->offset); target = ACPI_ADD_PTR(u8, obj_desc, info->offset);
name = info->name; name = info->name;
@ -471,7 +475,7 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
acpi_os_printf("%20s : %p ", name, next); acpi_os_printf("%20s : %p ", name, next);
if (next) { if (next) {
acpi_os_printf("(%s %2.2X)", acpi_os_printf("%s (Type %2.2X)",
acpi_ut_get_object_type_name acpi_ut_get_object_type_name
(next), next->common.type); (next), next->common.type);
@ -493,6 +497,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc,
break; break;
} }
} }
} else {
acpi_os_printf("- No attached objects");
} }
acpi_os_printf("\n"); acpi_os_printf("\n");
@ -1129,7 +1135,9 @@ acpi_ex_dump_package_obj(union acpi_operand_object *obj_desc,
default: 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; 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 *) acpi_ex_dump_namespace_node((struct acpi_namespace_node *)
obj_desc, flags); 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; 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; goto dump_object;
} }
@ -1191,6 +1205,10 @@ acpi_ex_dump_object_descriptor(union acpi_operand_object *obj_desc, u32 flags)
dump_object: dump_object:
if (!obj_desc) {
return_VOID;
}
/* Common Fields */ /* Common Fields */
acpi_ex_dump_object(obj_desc, acpi_ex_dump_common); acpi_ex_dump_object(obj_desc, acpi_ex_dump_common);

View file

@ -265,6 +265,8 @@ acpi_ex_do_logical_numeric_op(u16 opcode,
default: default:
ACPI_ERROR((AE_INFO,
"Invalid numeric logical opcode: %X", opcode));
status = AE_AML_INTERNAL; status = AE_AML_INTERNAL;
break; break;
} }
@ -345,6 +347,9 @@ acpi_ex_do_logical_op(u16 opcode,
default: default:
ACPI_ERROR((AE_INFO,
"Invalid object type for logical operator: %X",
operand0->common.type));
status = AE_AML_INTERNAL; status = AE_AML_INTERNAL;
break; break;
} }
@ -388,6 +393,8 @@ acpi_ex_do_logical_op(u16 opcode,
default: default:
ACPI_ERROR((AE_INFO,
"Invalid comparison opcode: %X", opcode));
status = AE_AML_INTERNAL; status = AE_AML_INTERNAL;
break; break;
} }
@ -456,6 +463,8 @@ acpi_ex_do_logical_op(u16 opcode,
default: default:
ACPI_ERROR((AE_INFO,
"Invalid comparison opcode: %X", opcode));
status = AE_AML_INTERNAL; status = AE_AML_INTERNAL;
break; break;
} }

View file

@ -414,6 +414,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
default: default:
ACPI_ERROR((AE_INFO,
"Invalid object type: %X",
(operand[0])->common.type));
status = AE_AML_INTERNAL; status = AE_AML_INTERNAL;
goto cleanup; goto cleanup;
} }

View file

@ -107,7 +107,7 @@ acpi_hw_get_access_bit_width(u64 address,
ACPI_IS_ALIGNED(reg->bit_width, 8)) { ACPI_IS_ALIGNED(reg->bit_width, 8)) {
access_bit_width = reg->bit_width; access_bit_width = reg->bit_width;
} else if (reg->access_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 { } else {
access_bit_width = access_bit_width =
ACPI_ROUND_UP_POWER_OF_TWO_8(reg->bit_offset + ACPI_ROUND_UP_POWER_OF_TWO_8(reg->bit_offset +

View file

@ -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[] = { static struct acpi_sleep_functions acpi_sleep_dispatch[] = {
{ACPI_STRUCT_INIT(legacy_function, {ACPI_STRUCT_INIT(legacy_function,
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_sleep)), 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_STRUCT_INIT(legacy_function,
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake_prep)), 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_STRUCT_INIT(legacy_function,
ACPI_HW_OPTIONAL_FUNCTION(acpi_hw_legacy_wake)), 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)}
}; };
/* /*

View file

@ -292,6 +292,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
{ {
acpi_status status; acpi_status status;
char *path = pathname; char *path = pathname;
char *external_path;
struct acpi_namespace_node *prefix_node; struct acpi_namespace_node *prefix_node;
struct acpi_namespace_node *current_node = NULL; struct acpi_namespace_node *current_node = NULL;
struct acpi_namespace_node *this_node = NULL; struct acpi_namespace_node *this_node = NULL;
@ -427,13 +428,22 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
num_carats++; num_carats++;
this_node = this_node->parent; this_node = this_node->parent;
if (!this_node) { if (!this_node) {
/*
/* Current scope has no parent scope */ * 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, ACPI_ERROR((AE_INFO,
"%s: Path has too many parent prefixes (^) " "%s: Path has too many parent prefixes (^)",
"- reached beyond root node", external_path));
pathname));
ACPI_FREE(external_path);
}
return_ACPI_STATUS(AE_NOT_FOUND); return_ACPI_STATUS(AE_NOT_FOUND);
} }
} }
@ -634,6 +644,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
this_node->object; 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) */ /* Special handling for the last segment (num_segments == 0) */

View file

@ -69,9 +69,14 @@ void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)
u8 user_arg_type; u8 user_arg_type;
u32 i; u32 i;
/* If not a predefined name, cannot typecheck args */ /*
* If not a predefined name, cannot typecheck args, because
if (!info->predefined) { * 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; return;
} }
@ -93,6 +98,10 @@ void acpi_ns_check_argument_types(struct acpi_evaluate_info *info)
acpi_ut_get_type_name acpi_ut_get_type_name
(user_arg_type), (user_arg_type),
acpi_ut_get_type_name(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 aml_param_count;
u32 required_param_count; u32 required_param_count;
if (!predefined) { if (!predefined || (node->flags & ANOBJ_EVALUATED)) {
return; return;
} }
@ -215,6 +224,10 @@ acpi_ns_check_argument_count(char *pathname,
u32 aml_param_count; u32 aml_param_count;
u32 required_param_count; u32 required_param_count;
if (node->flags & ANOBJ_EVALUATED) {
return;
}
if (!predefined) { if (!predefined) {
/* /*
* Not a predefined name. Check the incoming user argument count * Not a predefined name. Check the incoming user argument count

View file

@ -396,6 +396,20 @@ acpi_ns_init_one_object(acpi_handle obj_handle,
info->package_init++; info->package_init++;
status = acpi_ds_get_package_arguments(obj_desc); 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; break;
default: default:

View file

@ -89,7 +89,14 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node)
{ {
acpi_size size; 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); size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
return (size); return (size);

View file

@ -614,6 +614,8 @@ acpi_ns_check_package_list(struct acpi_evaluate_info *info,
default: /* Should not get here, type was validated by caller */ 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); return (AE_AML_INTERNAL);
} }

View file

@ -164,6 +164,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
INCREMENT_ARG_LIST(walk_state->arg_types); 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 * Handle executable code at "module-level". This refers to
* executable opcodes that appear outside of any control method. * 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) AML_NAME_OP)
&& (walk_state->pass_number <= && (walk_state->pass_number <=
ACPI_IMODE_LOAD_PASS2)) { 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 * Skip parsing of Buffers and Packages because we don't have
* enough info in the first pass to parse them correctly. * 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 */ /* 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) { if (walk_state->arg_count) {
/* /*
* There are arguments (complex ones), push Op and * There are arguments (complex ones), push Op and

View file

@ -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, acpi_ps_build_named_op(walk_state, aml_op_start, op,
&named_op); &named_op);
acpi_ps_free_op(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)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }

View file

@ -615,7 +615,7 @@ ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)
* device we are querying * device we are querying
* name - Method name of the resources we want. * name - Method name of the resources we want.
* (METHOD_NAME__CRS, METHOD_NAME__PRS, or * (METHOD_NAME__CRS, METHOD_NAME__PRS, or
* METHOD_NAME__AEI) * METHOD_NAME__AEI or METHOD_NAME__DMA)
* user_function - Called for each resource * user_function - Called for each resource
* context - Passed to user_function * context - Passed to user_function
* *
@ -641,11 +641,12 @@ acpi_walk_resources(acpi_handle device_handle,
if (!device_handle || !user_function || !name || if (!device_handle || !user_function || !name ||
(!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) && (!ACPI_COMPARE_NAME(name, METHOD_NAME__CRS) &&
!ACPI_COMPARE_NAME(name, METHOD_NAME__PRS) && !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); 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; buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
status = acpi_rs_get_method_data(device_handle, name, &buffer); status = acpi_rs_get_method_data(device_handle, name, &buffer);

View file

@ -50,6 +50,57 @@
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbdata") 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 * FUNCTION: acpi_tb_init_table_descriptor
@ -64,6 +115,7 @@ ACPI_MODULE_NAME("tbdata")
* DESCRIPTION: Initialize a new table descriptor * DESCRIPTION: Initialize a new table descriptor
* *
******************************************************************************/ ******************************************************************************/
void void
acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc, acpi_tb_init_table_descriptor(struct acpi_table_desc *table_desc,
acpi_physical_address address, 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) 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. * Only validates the header of the table.
* Note that Length contains the size of the mapping after invoking * 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)); 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 * FUNCTION: acpi_tb_verify_temp_table
* *
* PARAMETERS: table_desc - Table descriptor * PARAMETERS: table_desc - Table descriptor
* signature - Table signature to verify * signature - Table signature to verify
* table_index - Where the table index is returned
* *
* RETURN: Status * RETURN: Status
* *
* DESCRIPTION: This function is called to validate and verify the table, the * DESCRIPTION: This function is called to validate and verify the table, the
* returned table descriptor is in "VALIDATED" state. * returned table descriptor is in "VALIDATED" state.
* Note that 'TableIndex' is required to be set to !NULL to
* enable duplication check.
* *
*****************************************************************************/ *****************************************************************************/
acpi_status 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; 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; goto invalidate_and_exit;
} }
if (acpi_gbl_enable_table_validation) {
/* Verify the checksum */ /* Verify the checksum */
if (acpi_gbl_verify_table_checksum) {
status = status =
acpi_tb_verify_checksum(table_desc->pointer, acpi_tb_verify_checksum(table_desc->pointer,
table_desc->length); table_desc->length);
@ -411,9 +542,34 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc, char *signature)
goto invalidate_and_exit; 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)));
} }
return_ACPI_STATUS(AE_OK); goto invalidate_and_exit;
}
}
table_desc->flags |= ACPI_TABLE_IS_VERIFIED;
}
return_ACPI_STATUS(status);
invalidate_and_exit: invalidate_and_exit:
acpi_tb_invalidate_table(table_desc); acpi_tb_invalidate_table(table_desc);
@ -436,6 +592,8 @@ acpi_status acpi_tb_resize_root_table_list(void)
{ {
struct acpi_table_desc *tables; struct acpi_table_desc *tables;
u32 table_count; u32 table_count;
u32 current_table_count, max_table_count;
u32 i;
ACPI_FUNCTION_TRACE(tb_resize_root_table_list); 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; table_count = acpi_gbl_root_table_list.current_table_count;
} }
tables = ACPI_ALLOCATE_ZEROED(((acpi_size)table_count + max_table_count = table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT;
ACPI_ROOT_TABLE_SIZE_INCREMENT) * tables = ACPI_ALLOCATE_ZEROED(((acpi_size)max_table_count) *
sizeof(struct acpi_table_desc)); sizeof(struct acpi_table_desc));
if (!tables) { if (!tables) {
ACPI_ERROR((AE_INFO, ACPI_ERROR((AE_INFO,
@ -466,9 +624,16 @@ acpi_status acpi_tb_resize_root_table_list(void)
/* Copy and free the previous table array */ /* Copy and free the previous table array */
current_table_count = 0;
if (acpi_gbl_root_table_list.tables) { if (acpi_gbl_root_table_list.tables) {
memcpy(tables, acpi_gbl_root_table_list.tables, for (i = 0; i < table_count; i++) {
(acpi_size)table_count * sizeof(struct acpi_table_desc)); 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) { if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
ACPI_FREE(acpi_gbl_root_table_list.tables); 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.tables = tables;
acpi_gbl_root_table_list.max_table_count = acpi_gbl_root_table_list.max_table_count = max_table_count;
table_count + ACPI_ROOT_TABLE_SIZE_INCREMENT; acpi_gbl_root_table_list.current_table_count = current_table_count;
acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED; acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
return_ACPI_STATUS(AE_OK); 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); acpi_ev_update_gpes(owner_id);
} }
/* Invoke table handler if present */ /* Invoke table handler */
if (acpi_gbl_table_handler) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
acpi_gbl_table_handler_context);
}
acpi_tb_notify_table(ACPI_TABLE_EVENT_LOAD, table);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
@ -894,15 +1055,11 @@ acpi_status acpi_tb_unload_table(u32 table_index)
return_ACPI_STATUS(AE_NOT_EXIST); 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); status = acpi_get_table_by_index(table_index, &table);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD, acpi_tb_notify_table(ACPI_TABLE_EVENT_UNLOAD, table);
table,
acpi_gbl_table_handler_context);
}
} }
/* Delete the portion of the namespace owned by this 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) 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);
}
}

View file

@ -48,54 +48,6 @@
#define _COMPONENT ACPI_TABLES #define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbinstal") 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 * 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. * table array.
* *
******************************************************************************/ ******************************************************************************/
void void
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
u8 override, u32 *table_index) u8 override, u32 *table_index)
@ -210,81 +161,15 @@ acpi_tb_install_standard_table(acpi_physical_address address,
goto release_and_exit; 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 */ /* Acquire the table lock */
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
if (reload) { /* Validate and verify a table before installation */
/*
* 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));
status = AE_BAD_SIGNATURE; status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
goto unlock_and_exit; if (ACPI_FAILURE(status)) {
} if (status == AE_CTRL_TERMINATE) {
/* Check if table is already registered */
for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
++i) {
/*
* Check for a table match on the entire table length,
* not just the header.
*/
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. * Table was unloaded, allow it to be reloaded.
* As we are going to return AE_OK to the caller, we should * As we are going to return AE_OK to the caller, we should
@ -298,7 +183,7 @@ acpi_tb_install_standard_table(acpi_physical_address address,
*table_index = i; *table_index = i;
return_ACPI_STATUS(AE_OK); return_ACPI_STATUS(AE_OK);
} }
} goto unlock_and_exit;
} }
/* Add the table to the global root table list */ /* 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, acpi_tb_install_table_with_override(&new_table_desc, override,
table_index); table_index);
/* Invoke table handler if present */ /* Invoke table handler */
(void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
if (acpi_gbl_table_handler) { acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer);
(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_INSTALL,
new_table_desc.pointer,
acpi_gbl_table_handler_context);
}
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
unlock_and_exit: unlock_and_exit:
@ -382,9 +263,11 @@ void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
finish_override: finish_override:
/* Validate and verify a table before overriding */ /*
* Validate and verify a table before overriding, no nested table
status = acpi_tb_verify_temp_table(&new_table_desc, NULL); * duplication check as it's too complicated and unnecessary.
*/
status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return; return;
} }

View file

@ -167,7 +167,8 @@ ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void) acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
{ {
acpi_status status; acpi_status status;
u32 i; struct acpi_table_desc *table_desc;
u32 i, j;
ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); 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); 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 * Ensure OS early boot logic, which is required by some hosts. If the
* table state is reported to be wrong, developers should fix 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. * early stage.
*/ */
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { 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, ACPI_ERROR((AE_INFO,
"Table [%4.4s] is not invalidated during early boot stage", "Table [%4.4s] is not invalidated during early boot stage",
acpi_gbl_root_table_list.tables[i]. table_desc->signature.ascii));
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; acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
status = acpi_tb_resize_root_table_list(); 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); return_ACPI_STATUS(status);
} }
@ -369,6 +394,10 @@ void acpi_put_table(struct acpi_table_header *table)
ACPI_FUNCTION_TRACE(acpi_put_table); ACPI_FUNCTION_TRACE(acpi_put_table);
if (!table) {
return_VOID;
}
(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
/* Walk the root table list */ /* Walk the root table list */

View file

@ -206,7 +206,7 @@ acpi_status acpi_tb_load_namespace(void)
for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
table = &acpi_gbl_root_table_list.tables[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_SSDT)
&& !ACPI_COMPARE_NAME(table->signature.ascii, && !ACPI_COMPARE_NAME(table->signature.ascii,
ACPI_SIG_PSDT) ACPI_SIG_PSDT)

View file

@ -69,8 +69,10 @@ static const char acpi_gbl_hex_to_ascii[] = {
char acpi_ut_hex_to_ascii_char(u64 integer, u32 position) 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]);
} }
/******************************************************************************* /*******************************************************************************

View file

@ -47,15 +47,6 @@
#define _COMPONENT ACPI_UTILITIES #define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME("utmath") 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 */ /* Structures used only for 64-bit divide */
typedef struct uint64_struct { typedef struct uint64_struct {
u32 lo; u32 lo;
@ -69,6 +60,217 @@ typedef union uint64_overlay {
} 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 * FUNCTION: acpi_ut_short_divide
@ -258,6 +460,7 @@ acpi_ut_divide(u64 in_dividend,
} }
#else #else
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ut_short_divide, acpi_ut_divide * FUNCTION: acpi_ut_short_divide, acpi_ut_divide
@ -272,6 +475,7 @@ acpi_ut_divide(u64 in_dividend,
* perform the divide. * perform the divide.
* *
******************************************************************************/ ******************************************************************************/
acpi_status acpi_status
acpi_ut_short_divide(u64 in_dividend, acpi_ut_short_divide(u64 in_dividend,
u32 divisor, u64 *out_quotient, u32 *out_remainder) u32 divisor, u64 *out_quotient, u32 *out_remainder)

View file

@ -224,7 +224,7 @@ acpi_ut_create_update_state_and_push(union acpi_operand_object *object,
* *
* RETURN: Status * 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; acpi_status status = AE_OK;
union acpi_generic_state *state_list = NULL; union acpi_generic_state *state_list = NULL;
union acpi_generic_state *state; union acpi_generic_state *state;
u32 this_index;
union acpi_operand_object *this_source_obj; union acpi_operand_object *this_source_obj;
u32 this_index;
ACPI_FUNCTION_TRACE(ut_walk_package_tree); 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 */ /* Get one element of the package */
this_index = state->pkg.index; 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.source_object->package.elements[this_index];
state->pkg.this_target_obj =
&state->pkg.source_object->package.elements[this_index];
/* /*
* Check for: * Check for:
@ -339,6 +341,8 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object,
/* We should never get here */ /* We should never get here */
ACPI_ERROR((AE_INFO, "State list did not terminate correctly"));
return_ACPI_STATUS(AE_AML_INTERNAL); return_ACPI_STATUS(AE_AML_INTERNAL);
} }

View file

@ -483,6 +483,11 @@ acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object,
/* A namespace node should never get here */ /* 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); return_ACPI_STATUS(AE_AML_INTERNAL);
} }

View file

@ -176,7 +176,7 @@ const char *acpi_ut_scan_number(const char *string, u64 *number_ptr)
u64 number = 0; u64 number = 0;
while (isdigit((int)*string)) { while (isdigit((int)*string)) {
number *= 10; acpi_ut_short_multiply(number, 10, &number);
number += *(string++) - '0'; number += *(string++) - '0';
} }
@ -286,7 +286,7 @@ static char *acpi_ut_format_number(char *string,
/* Generate full string in reverse order */ /* Generate full string in reverse order */
pos = acpi_ut_put_number(reversed_string, number, base, upper); 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" */ /* 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) { if (!s) {
s = "<NULL>"; s = "<NULL>";
} }
length = acpi_ut_bound_string_length(s, precision); length = (s32)acpi_ut_bound_string_length(s, precision);
if (!(type & ACPI_FORMAT_LEFT)) { if (!(type & ACPI_FORMAT_LEFT)) {
while (length < width--) { while (length < width--) {
pos = 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));
} }
/******************************************************************************* /*******************************************************************************

View file

@ -237,6 +237,13 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); 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 */ /* Return the pointer to the end_tag if requested */
if (!user_function) { if (!user_function) {

View file

@ -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, union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object,
void *external_object, void *external_object,
u16 index) u32 index)
{ {
union acpi_generic_state *state; union acpi_generic_state *state;

View file

@ -276,8 +276,8 @@ static u64 acpi_ut_strtoul_base10(char *string, u32 flags)
/* Convert and insert (add) the decimal digit */ /* Convert and insert (add) the decimal digit */
next_value = acpi_ut_short_multiply(return_value, 10, &next_value);
(return_value * 10) + (ascii_digit - ACPI_ASCII_ZERO); next_value += (ascii_digit - ACPI_ASCII_ZERO);
/* Check for overflow (32 or 64 bit) - return current converted value */ /* 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 */ /* Convert and insert the hex digit */
return_value = acpi_ut_short_shift_left(return_value, 4, &return_value);
(return_value << 4) | return_value |= acpi_ut_ascii_char_to_hex(ascii_digit);
acpi_ut_ascii_char_to_hex(ascii_digit);
string++; string++;
valid_digits++; valid_digits++;

View file

@ -591,6 +591,10 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
return_VOID; return_VOID;
} }
if (!acpi_gbl_global_list) {
goto exit;
}
element = acpi_gbl_global_list->list_head; element = acpi_gbl_global_list->list_head;
while (element) { while (element) {
if ((element->component & component) && if ((element->component & component) &&
@ -602,7 +606,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
if (element->size < if (element->size <
sizeof(struct acpi_common_descriptor)) { 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", "[Not a Descriptor - too small]\n",
descriptor, element->size, descriptor, element->size,
element->module, element->line); element->module, element->line);
@ -612,7 +616,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) != if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
ACPI_DESC_TYPE_CACHED) { ACPI_DESC_TYPE_CACHED) {
acpi_os_printf acpi_os_printf
("%p Length 0x%04X %9.9s-%u [%s] ", ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
descriptor, element->size, descriptor, element->size,
element->module, element->line, element->module, element->line,
acpi_ut_get_descriptor_name acpi_ut_get_descriptor_name
@ -705,6 +709,7 @@ void acpi_ut_dump_allocations(u32 component, const char *module)
element = element->next; element = element->next;
} }
exit:
(void)acpi_ut_release_mutex(ACPI_MTX_MEMORY); (void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
/* Print summary */ /* Print summary */

View file

@ -995,9 +995,6 @@ void __init acpi_early_init(void)
printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); 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 */ /* enable workarounds, unless strict ACPI spec. compliance */
if (!acpi_strict) if (!acpi_strict)
acpi_gbl_enable_interpreter_slack = TRUE; acpi_gbl_enable_interpreter_slack = TRUE;

View file

@ -105,16 +105,17 @@ int __init parse_spcr(bool earlycon)
} }
if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { 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: default:
pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n"); pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n");
case ACPI_ACCESS_SIZE_BYTE: case 8:
iotype = "mmio"; iotype = "mmio";
break; break;
case ACPI_ACCESS_SIZE_WORD: case 16:
iotype = "mmio16"; iotype = "mmio16";
break; break;
case ACPI_ACCESS_SIZE_DWORD: case 32:
iotype = "mmio32"; iotype = "mmio32";
break; break;
} }

View file

@ -740,10 +740,10 @@ int __init acpi_table_init(void)
if (acpi_verify_table_checksum) { if (acpi_verify_table_checksum) {
pr_info("Early table checksum verification enabled\n"); pr_info("Early table checksum verification enabled\n");
acpi_gbl_verify_table_checksum = TRUE; acpi_gbl_enable_table_validation = TRUE;
} else { } else {
pr_info("Early table checksum verification disabled\n"); 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); status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);

View file

@ -54,6 +54,7 @@
#define METHOD_NAME__CLS "_CLS" #define METHOD_NAME__CLS "_CLS"
#define METHOD_NAME__CRS "_CRS" #define METHOD_NAME__CRS "_CRS"
#define METHOD_NAME__DDN "_DDN" #define METHOD_NAME__DDN "_DDN"
#define METHOD_NAME__DMA "_DMA"
#define METHOD_NAME__HID "_HID" #define METHOD_NAME__HID "_HID"
#define METHOD_NAME__INI "_INI" #define METHOD_NAME__INI "_INI"
#define METHOD_NAME__PLD "_PLD" #define METHOD_NAME__PLD "_PLD"

View file

@ -58,10 +58,10 @@
#include <acpi/actypes.h> /* ACPICA data types and structures */ #include <acpi/actypes.h> /* ACPICA data types and structures */
#include <acpi/acexcep.h> /* ACPICA exceptions */ #include <acpi/acexcep.h> /* ACPICA exceptions */
#include <acpi/actbl.h> /* ACPI table definitions */ #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/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/acpiosxf.h> /* OSL interfaces (ACPICA-to-OS) */
#include <acpi/acpixf.h> /* ACPI core subsystem external interfaces */ #include <acpi/acpixf.h> /* ACPI core subsystem external interfaces */
#include <acpi/platform/acenvex.h> /* Extra environment-specific items */
#endif /* __ACPI_H__ */ #endif /* __ACPI_H__ */

View file

@ -46,7 +46,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */ /* Current ACPICA subsystem version in YYYYMMDD format */
#define ACPI_CA_VERSION 0x20170531 #define ACPI_CA_VERSION 0x20170728
#include <acpi/acconfig.h> #include <acpi/acconfig.h>
#include <acpi/actypes.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); ACPI_INIT_GLOBAL(u8, acpi_gbl_use_default_register_widths, TRUE);
/* /*
* Whether or not to verify the table checksum before installation. Set * Whether or not to validate (map) an entire table to verify
* this to TRUE to verify the table checksum before install it to the table * checksum/duplication in early stage before install. Set this to TRUE to
* manager. Note that enabling this option causes errors to happen in some * allow early table validation before install it to the table manager.
* OSPMs during early initialization stages. Default behavior is to do such * Note that enabling this option causes errors to happen in some OSPMs
* verification. * 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. * Optionally enable output from the AML Debug Object.

View file

@ -377,13 +377,6 @@ struct acpi_resource_generic_register {
u64 address; 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 { struct acpi_resource_gpio {
u8 revision_id; u8 revision_id;
u8 connection_type; u8 connection_type;

View file

@ -394,6 +394,7 @@ struct acpi_table_desc {
#define ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL (1) /* Physical address, internally mapped */ #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_INTERNAL_VIRTUAL (2) /* Virtual address, internallly allocated */
#define ACPI_TABLE_ORIGIN_MASK (3) #define ACPI_TABLE_ORIGIN_MASK (3)
#define ACPI_TABLE_IS_VERIFIED (4)
#define ACPI_TABLE_IS_LOADED (8) #define ACPI_TABLE_IS_LOADED (8)
/* /*

View file

@ -76,6 +76,7 @@
#define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */ #define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */
#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ #define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */
#define ACPI_SIG_MTMR "MTMR" /* MID Timer 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_SLIC "SLIC" /* Software Licensing Description Table */
#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ #define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */
#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ #define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */
@ -664,7 +665,7 @@ struct acpi_ibft_target {
* IORT - IO Remapping Table * IORT - IO Remapping Table
* *
* Conforms to "IO Remapping Table System Software on ARM Platforms", * 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_V2 0x00000001 /* Generic SMMUv2 */
#define ACPI_IORT_SMMU_CORELINK_MMU400 0x00000002 /* ARM Corelink MMU-400 */ #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_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 */ /* Masks for Flags field above */
@ -799,17 +802,27 @@ struct acpi_iort_smmu_v3 {
u32 flags; u32 flags;
u32 reserved; u32 reserved;
u64 vatos_address; u64 vatos_address;
u32 model; /* O: generic SMMUv3 */ u32 model;
u32 event_gsiv; u32 event_gsiv;
u32 pri_gsiv; u32 pri_gsiv;
u32 gerr_gsiv; u32 gerr_gsiv;
u32 sync_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 */ /* Masks for Flags field above */
#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1) #define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1)
#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (1<<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; 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 * SLIC - Software Licensing Description Table

View file

@ -166,6 +166,7 @@ typedef u64 acpi_physical_address;
#define ACPI_SIZE_MAX ACPI_UINT64_MAX #define ACPI_SIZE_MAX ACPI_UINT64_MAX
#define ACPI_USE_NATIVE_DIVIDE /* Has native 64-bit integer support */ #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 * 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_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)) #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 * Miscellaneous constants

View file

@ -288,6 +288,11 @@
#define ACPI_INLINE #define ACPI_INLINE
#endif #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: * Configurable calling conventions:
* *
@ -382,8 +387,4 @@
#define ACPI_INIT_FUNCTION #define ACPI_INIT_FUNCTION
#endif #endif
#ifndef ACPI_STRUCT_INIT
#define ACPI_STRUCT_INIT(field, value) value
#endif
#endif /* __ACENV_H__ */ #endif /* __ACENV_H__ */

View file

@ -84,4 +84,8 @@ typedef __builtin_va_list va_list;
#define COMPILER_VA_MACRO 1 #define COMPILER_VA_MACRO 1
/* GCC supports native multiply/shift on 32-bit platforms */
#define ACPI_USE_NATIVE_MATH64
#endif /* __ACGCC_H__ */ #endif /* __ACGCC_H__ */

View file

@ -128,6 +128,7 @@
/* Host-dependent types and defines for in-kernel ACPICA */ /* Host-dependent types and defines for in-kernel ACPICA */
#define ACPI_MACHINE_WIDTH BITS_PER_LONG #define ACPI_MACHINE_WIDTH BITS_PER_LONG
#define ACPI_USE_NATIVE_MATH64
#define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol); #define ACPI_EXPORT_SYMBOL(symbol) EXPORT_SYMBOL(symbol);
#define strtoul simple_strtoul #define strtoul simple_strtoul
@ -178,6 +179,9 @@
#define ACPI_MSG_BIOS_ERROR KERN_ERR "ACPI BIOS Error (bug): " #define ACPI_MSG_BIOS_ERROR KERN_ERR "ACPI BIOS Error (bug): "
#define ACPI_MSG_BIOS_WARNING KERN_WARNING "ACPI BIOS Warning (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 #define ACPI_STRUCT_INIT(field, value) .field = value
#else /* !__KERNEL__ */ #else /* !__KERNEL__ */
@ -213,6 +217,7 @@
#define COMPILER_DEPENDENT_INT64 long long #define COMPILER_DEPENDENT_INT64 long long
#define COMPILER_DEPENDENT_UINT64 unsigned long long #define COMPILER_DEPENDENT_UINT64 unsigned long long
#define ACPI_USE_NATIVE_DIVIDE #define ACPI_USE_NATIVE_DIVIDE
#define ACPI_USE_NATIVE_MATH64
#endif #endif
#ifndef __cdecl #ifndef __cdecl

View file

@ -759,7 +759,7 @@ static acpi_status osl_list_bios_tables(void)
/* Skip NULL entries in RSDT/XSDT */ /* Skip NULL entries in RSDT/XSDT */
if (!table_address) { if (table_address == 0) {
continue; continue;
} }
@ -808,7 +808,8 @@ osl_get_bios_table(char *signature,
u8 number_of_tables; u8 number_of_tables;
u8 item_size; u8 item_size;
u32 current_instance = 0; 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; u32 table_length = 0;
acpi_status status = AE_OK; acpi_status status = AE_OK;
u32 i; 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_XSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) ||
ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { 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 * Get the appropriate address, either 32-bit or 64-bit. Be very
@ -830,42 +832,67 @@ osl_get_bios_table(char *signature,
* Note: The 64-bit addresses have priority. * Note: The 64-bit addresses have priority.
*/ */
if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && if (current_instance < 2) {
gbl_fadt->Xdsdt) { if ((gbl_fadt->header.length >=
MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt
&& current_instance == 0) {
table_address = table_address =
(acpi_physical_address)gbl_fadt->Xdsdt; (acpi_physical_address)gbl_fadt->
Xdsdt;
} else } else
if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) if ((gbl_fadt->header.length >=
&& gbl_fadt->dsdt) { MIN_FADT_FOR_DSDT)
&& gbl_fadt->dsdt !=
first_table_address) {
table_address = table_address =
(acpi_physical_address)gbl_fadt->dsdt; (acpi_physical_address)gbl_fadt->
dsdt;
}
} }
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) {
if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && if (current_instance < 2) {
gbl_fadt->Xfacs) { if ((gbl_fadt->header.length >=
MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs
&& current_instance == 0) {
table_address = table_address =
(acpi_physical_address)gbl_fadt->Xfacs; (acpi_physical_address)gbl_fadt->
Xfacs;
} else } else
if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) if ((gbl_fadt->header.length >=
&& gbl_fadt->facs) { MIN_FADT_FOR_FACS)
&& gbl_fadt->facs !=
first_table_address) {
table_address = table_address =
(acpi_physical_address)gbl_fadt->facs; (acpi_physical_address)gbl_fadt->
facs;
}
} }
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) {
if (!gbl_revision) { if (!gbl_revision) {
return (AE_BAD_SIGNATURE); return (AE_BAD_SIGNATURE);
} }
if (current_instance == 0) {
table_address = table_address =
(acpi_physical_address)gbl_rsdp. (acpi_physical_address)gbl_rsdp.
xsdt_physical_address; xsdt_physical_address;
}
} else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) {
if (current_instance == 0) {
table_address = table_address =
(acpi_physical_address)gbl_rsdp. (acpi_physical_address)gbl_rsdp.
rsdt_physical_address; rsdt_physical_address;
}
} else { } else {
table_address = (acpi_physical_address)gbl_rsdp_address; if (current_instance == 0) {
table_address =
(acpi_physical_address)gbl_rsdp_address;
signature = ACPI_SIG_RSDP; signature = ACPI_SIG_RSDP;
} }
}
if (table_address == 0) {
goto exit_find_table;
}
/* Now we can get the requested special 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); 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 */ } else { /* Case for a normal ACPI table */
if (osl_can_use_xsdt()) { if (osl_can_use_xsdt()) {
@ -913,7 +952,7 @@ osl_get_bios_table(char *signature,
/* Skip NULL entries in RSDT/XSDT */ /* Skip NULL entries in RSDT/XSDT */
if (!table_address) { if (table_address == 0) {
continue; continue;
} }
@ -946,6 +985,8 @@ osl_get_bios_table(char *signature,
} }
} }
exit_find_table:
if (!mapped_table) { if (!mapped_table) {
return (AE_LIMIT); return (AE_LIMIT);
} }

View file

@ -61,7 +61,7 @@ static int ap_is_existing_file(char *pathname);
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; struct stat stat_info;
if (!stat(pathname, &stat_info)) { if (!stat(pathname, &stat_info)) {

View file

@ -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[]) int ACPI_SYSTEM_XFACE main(int argc, char *argv[])
#else #else
int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[]) int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])