Commit cca97b81 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: Fix for some local named nodes not marked temporary and to disallow duplicates

Fixed a problem with the CreateField, CreateXXXField (Bit, Byte,
Word, Dword, Qword), Field, BankField, and IndexField operators
when invoked from inside an executing control method. In this case,
these operators created namespace nodes that were incorrectly
left marked as permanent nodes instead of temporary nodes. This
could cause a problem if there is race condition between an
exiting control method and a running namespace walk. (Reported
by Linn Crosetto). Fixed a problem where the CreateField and
CreateXXXField operators would incorrectly allow duplicate names
(the name of the field) with no exception generated.
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 66e2c0bc
...@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ...@@ -89,12 +89,16 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
ACPI_FUNCTION_TRACE(ds_create_buffer_field); ACPI_FUNCTION_TRACE(ds_create_buffer_field);
/* Get the name_string argument */ /*
* Get the name_string argument (name of the new buffer_field)
*/
if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
/* For create_field, name is the 4th argument */
arg = acpi_ps_get_arg(op, 3); arg = acpi_ps_get_arg(op, 3);
} else { } else {
/* Create Bit/Byte/Word/Dword field */ /* For all other create_xXXField operators, name is the 3rd argument */
arg = acpi_ps_get_arg(op, 2); arg = acpi_ps_get_arg(op, 2);
} }
...@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ...@@ -107,26 +111,30 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
node = walk_state->deferred_node; node = walk_state->deferred_node;
status = AE_OK; status = AE_OK;
} else { } else {
/* /* Execute flag should always be set when this function is entered */
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the size if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
* operand), we want to lookup the name return_ACPI_STATUS(AE_AML_INTERNAL);
*/
if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
} else {
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
} }
/* /* Creating new namespace node, should not already exist */
* Enter the name_string into the namespace
*/ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node temporary if we are executing a method */
if (walk_state->method_node) {
flags |= ACPI_NS_TEMPORARY;
}
/* Enter the name_string into the namespace */
status = status =
acpi_ns_lookup(walk_state->scope_info, acpi_ns_lookup(walk_state->scope_info,
arg->common.value.string, ACPI_TYPE_ANY, arg->common.value.string, ACPI_TYPE_ANY,
ACPI_IMODE_LOAD_PASS1, flags, walk_state, ACPI_IMODE_LOAD_PASS1, flags, walk_state,
&(node)); &node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status); ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
...@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ...@@ -136,13 +144,13 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
/* /*
* We could put the returned object (Node) on the object stack for later, * We could put the returned object (Node) on the object stack for later,
* but for now, we will put it in the "op" object that the parser uses, * but for now, we will put it in the "op" object that the parser uses,
* so we can get it again at the end of this scope * so we can get it again at the end of this scope.
*/ */
op->common.node = node; op->common.node = node;
/* /*
* If there is no object attached to the node, this node was just created * If there is no object attached to the node, this node was just created
* and we need to create the field object. Otherwise, this was a lookup * and we need to create the field object. Otherwise, this was a lookup
* of an existing node and we don't want to create the field object again. * of an existing node and we don't want to create the field object again.
*/ */
obj_desc = acpi_ns_get_attached_object(node); obj_desc = acpi_ns_get_attached_object(node);
...@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, ...@@ -164,9 +172,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
} }
/* /*
* Remember location in AML stream of the field unit * Remember location in AML stream of the field unit opcode and operands --
* opcode and operands -- since the buffer and index * since the buffer and index operands must be evaluated.
* operands must be evaluated.
*/ */
second_desc = obj_desc->common.next_object; second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data; second_desc->extra.aml_start = op->named.data;
...@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ...@@ -261,7 +268,7 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
case AML_INT_NAMEDFIELD_OP: case AML_INT_NAMEDFIELD_OP:
/* Lookup the name */ /* Lookup the name, it should already exist */
status = acpi_ns_lookup(walk_state->scope_info, status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name, (char *)&arg->named.name,
...@@ -272,19 +279,16 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, ...@@ -272,19 +279,16 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info,
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name, ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status); status);
if (status != AE_ALREADY_EXISTS) { return_ACPI_STATUS(status);
return_ACPI_STATUS(status);
}
/* Already exists, ignore error */
} else { } else {
arg->common.node = info->field_node; arg->common.node = info->field_node;
info->field_bit_length = arg->common.value.size; info->field_bit_length = arg->common.value.size;
/* /*
* If there is no object attached to the node, this node was just created * If there is no object attached to the node, this node was
* and we need to create the field object. Otherwise, this was a lookup * just created and we need to create the field object.
* of an existing node and we don't want to create the field object again. * Otherwise, this was a lookup of an existing node and we
* don't want to create the field object again.
*/ */
if (!acpi_ns_get_attached_object if (!acpi_ns_get_attached_object
(info->field_node)) { (info->field_node)) {
...@@ -409,18 +413,23 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ...@@ -409,18 +413,23 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op);
/* /* Execute flag should always be set when this function is entered */
* During the load phase, we want to enter the name of the field into
* the namespace. During the execute phase (when we evaluate the bank_value if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) {
* operand), we want to lookup the name. if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) {
*/
if (walk_state->deferred_node) { /* bank_field Op is deferred, just return OK */
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
} else { return_ACPI_STATUS(AE_OK);
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | }
ACPI_NS_ERROR_IF_FOUND;
return_ACPI_STATUS(AE_AML_INTERNAL);
} }
/*
* Get the field_list argument for this opcode. This is the start of the
* list of field elements.
*/
switch (walk_state->opcode) { switch (walk_state->opcode) {
case AML_FIELD_OP: case AML_FIELD_OP:
arg = acpi_ps_get_arg(op, 2); arg = acpi_ps_get_arg(op, 2);
...@@ -441,18 +450,34 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ...@@ -441,18 +450,34 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
return_ACPI_STATUS(AE_BAD_PARAMETER); return_ACPI_STATUS(AE_BAD_PARAMETER);
} }
if (!arg) {
return_ACPI_STATUS(AE_AML_NO_OPERAND);
}
/* Creating new namespace node(s), should not already exist */
flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
ACPI_NS_ERROR_IF_FOUND;
/* Mark node(s) temporary if we are executing a method */
if (walk_state->method_node) {
flags |= ACPI_NS_TEMPORARY;
}
/* /*
* Walk the list of entries in the field_list * Walk the list of entries in the field_list
*/ */
while (arg) { while (arg) {
/*
/* Ignore OFFSET and ACCESSAS terms here */ * Ignore OFFSET and ACCESSAS terms here; we are only interested in the
* field names in order to enter them into the namespace.
*/
if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
status = acpi_ns_lookup(walk_state->scope_info, status = acpi_ns_lookup(walk_state->scope_info,
(char *)&arg->named.name, (char *)&arg->named.name, type,
type, ACPI_IMODE_LOAD_PASS1, ACPI_IMODE_LOAD_PASS1, flags,
flags, walk_state, &node); walk_state, &node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE((char *)&arg->named.name, ACPI_ERROR_NAMESPACE((char *)&arg->named.name,
status); status);
...@@ -468,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, ...@@ -468,7 +493,7 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
arg->common.node = node; arg->common.node = node;
} }
/* Move to next field in the list */ /* Get the next field element in the list */
arg = arg->common.next; arg = arg->common.next;
} }
......
...@@ -776,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, ...@@ -776,6 +776,12 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
acpi_ns_lookup(walk_state->scope_info, buffer_ptr, acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
object_type, ACPI_IMODE_LOAD_PASS2, flags, object_type, ACPI_IMODE_LOAD_PASS2, flags,
walk_state, &node); walk_state, &node);
if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"***New Node [%4.4s] %p is temporary\n",
acpi_ut_get_node_name(node), node));
}
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment