acpi_status acpi_ds_result_pop(union acpi_operand_object **object, struct acpi_walk_state *walk_state) { acpi_native_uint index; union acpi_generic_state *state; acpi_status status; ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; /* Incorrect state of result stack */ if (state && !walk_state->result_count) { ACPI_ERROR((AE_INFO, "No results on result stack")); return (AE_AML_INTERNAL); } if (!state && walk_state->result_count) { ACPI_ERROR((AE_INFO, "No result state for result stack")); return (AE_AML_INTERNAL); } /* Empty result stack */ if (!state) { ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } /* Return object of the top element and clean that top element result stack */ walk_state->result_count--; index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; *object = state->results.obj_desc[index]; if (!*object) { ACPI_ERROR((AE_INFO, "No result objects on result stack, State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } state->results.obj_desc[index] = NULL; if (index == 0) { status = acpi_ds_result_stack_pop(walk_state); if (ACPI_FAILURE(status)) { return (status); } } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, acpi_ut_get_object_type_name(*object), (u32) index, walk_state, walk_state->result_count)); return (AE_OK); }
acpi_status acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, union acpi_operand_object *original_object, union acpi_operand_object **obj_desc_ptr) { union acpi_operand_object *pkg_obj_desc; ACPI_FUNCTION_NAME(ns_wrap_with_package); /* * Create the new outer package and populate it. The new * package will have a single element, the lone sub-object. */ pkg_obj_desc = acpi_ut_create_package_object(1); if (!pkg_obj_desc) { return (AE_NO_MEMORY); } pkg_obj_desc->package.elements[0] = original_object; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Wrapped %s with expected Package object\n", info->full_pathname, acpi_ut_get_object_type_name(original_object))); /* Return the new object in the object pointer */ *obj_desc_ptr = pkg_obj_desc; info->return_flags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; return (AE_OK); }
acpi_status acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) { ACPI_FUNCTION_NAME(ds_obj_stack_push); /* Check for stack overflow */ if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { ACPI_ERROR((AE_INFO, "Object stack overflow! Obj=%p State=%p #Ops=%X", object, walk_state, walk_state->num_operands)); return (AE_STACK_OVERFLOW); } /* Put the object onto the stack */ walk_state->operands[walk_state->operand_index] = object; walk_state->num_operands++; /* For the usual order of filling the operand stack */ walk_state->operand_index++; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", object, acpi_ut_get_object_type_name((union acpi_operand_object *) object), walk_state, walk_state->num_operands)); return (AE_OK); }
acpi_status acpi_ds_result_push(union acpi_operand_object * object, struct acpi_walk_state * walk_state) { union acpi_generic_state *state; acpi_status status; acpi_native_uint index; ACPI_FUNCTION_NAME(ds_result_push); if (walk_state->result_count > walk_state->result_size) { ACPI_ERROR((AE_INFO, "Result stack is full")); return (AE_AML_INTERNAL); } else if (walk_state->result_count == walk_state->result_size) { /* Extend the result stack */ status = acpi_ds_result_stack_push(walk_state); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "Failed to extend the result stack")); return (status); } } if (!(walk_state->result_count < walk_state->result_size)) { ACPI_ERROR((AE_INFO, "No free elements in result stack")); return (AE_AML_INTERNAL); } state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } if (!object) { ACPI_ERROR((AE_INFO, "Null Object! Obj=%p State=%p Num=%X", object, walk_state, walk_state->result_count)); return (AE_BAD_PARAMETER); } /* Assign the address of object to the top free element of result stack */ index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; state->results.obj_desc[index] = object; walk_state->result_count++; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", object, acpi_ut_get_object_type_name((union acpi_operand_object *) object), walk_state, walk_state->result_count, walk_state->current_result)); return (AE_OK); }
acpi_status acpi_ds_result_pop_from_bottom(union acpi_operand_object ** object, struct acpi_walk_state * walk_state) { acpi_native_uint index; union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_pop_from_bottom); state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", walk_state)); return (AE_NOT_EXIST); } if (!state->results.num_results) { ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } /* Remove Bottom element */ *object = state->results.obj_desc[0]; /* Push entire stack down one element */ for (index = 0; index < state->results.num_results; index++) { state->results.obj_desc[index] = state->results.obj_desc[index + 1]; } state->results.num_results--; /* Check for a valid result object */ if (!*object) { ACPI_ERROR((AE_INFO, "Null operand! State=%p #Ops=%X Index=%X", walk_state, state->results.num_results, (u32) index)); return (AE_AML_NO_RETURN_VALUE); } ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Results=%p State=%p\n", *object, (*object) ? acpi_ut_get_object_type_name(*object) : "NULL", state, walk_state)); return (AE_OK); }
void acpi_db_decode_internal_object(union acpi_operand_object *obj_desc) { u32 i; if (!obj_desc) { acpi_os_printf(" Uninitialized"); return; } if (ACPI_GET_DESCRIPTOR_TYPE(obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf(" %p [%s]", obj_desc, acpi_ut_get_descriptor_name(obj_desc)); return; } acpi_os_printf(" %s", acpi_ut_get_object_type_name(obj_desc)); switch (obj_desc->common.type) { case ACPI_TYPE_INTEGER: acpi_os_printf(" %8.8X%8.8X", ACPI_FORMAT_UINT64(obj_desc->integer.value)); break; case ACPI_TYPE_STRING: acpi_os_printf("(%u) \"%.24s", obj_desc->string.length, obj_desc->string.pointer); if (obj_desc->string.length > 24) { acpi_os_printf("..."); } else { acpi_os_printf("\""); } break; case ACPI_TYPE_BUFFER: acpi_os_printf("(%u)", obj_desc->buffer.length); for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) { acpi_os_printf(" %2.2X", obj_desc->buffer.pointer[i]); } break; default: acpi_os_printf(" %p", obj_desc); break; } }
acpi_status acpi_ds_result_pop(union acpi_operand_object ** object, struct acpi_walk_state * walk_state) { acpi_native_uint index; union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_pop); state = walk_state->results; if (!state) { return (AE_OK); } if (!state->results.num_results) { ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); } /* Remove top element */ state->results.num_results--; for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) { /* Check for a valid result object */ if (state->results.obj_desc[index - 1]) { *object = state->results.obj_desc[index - 1]; state->results.obj_desc[index - 1] = NULL; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, (*object) ? acpi_ut_get_object_type_name(*object) : "NULL", (u32) index - 1, walk_state, state->results.num_results)); return (AE_OK); } } ACPI_ERROR((AE_INFO, "No result objects! State=%p", walk_state)); return (AE_AML_NO_RETURN_VALUE); }
acpi_status acpi_ds_result_remove(union acpi_operand_object **object, u32 index, struct acpi_walk_state *walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_remove); state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result object pushed! State=%p", walk_state)); return (AE_NOT_EXIST); } if (index >= ACPI_OBJ_MAX_OPERAND) { ACPI_ERROR((AE_INFO, "Index out of range: %X State=%p Num=%X", index, walk_state, state->results.num_results)); } /* Check for a valid result object */ if (!state->results.obj_desc[index]) { ACPI_ERROR((AE_INFO, "Null operand! State=%p #Ops=%X, Index=%X", walk_state, state->results.num_results, index)); return (AE_AML_NO_RETURN_VALUE); } /* Remove the object */ state->results.num_results--; *object = state->results.obj_desc[index]; state->results.obj_desc[index] = NULL; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, (*object) ? acpi_ut_get_object_type_name(*object) : "NULL", index, walk_state, state->results.num_results)); return (AE_OK); }
acpi_status acpi_ds_result_push(union acpi_operand_object * object, struct acpi_walk_state * walk_state) { union acpi_generic_state *state; ACPI_FUNCTION_NAME(ds_result_push); state = walk_state->results; if (!state) { ACPI_ERROR((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) { ACPI_ERROR((AE_INFO, "Result stack overflow: Obj=%p State=%p Num=%X", object, walk_state, state->results.num_results)); return (AE_STACK_OVERFLOW); } if (!object) { ACPI_ERROR((AE_INFO, "Null Object! Obj=%p State=%p Num=%X", object, walk_state, state->results.num_results)); return (AE_BAD_PARAMETER); } state->results.obj_desc[state->results.num_results] = object; state->results.num_results++; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", object, object ? acpi_ut_get_object_type_name((union acpi_operand_object *) object) : "NULL", walk_state, state->results.num_results, walk_state->current_result)); return (AE_OK); }
static acpi_status acpi_ex_setup_region(union acpi_operand_object *obj_desc, u32 field_datum_byte_offset) { acpi_status status = AE_OK; union acpi_operand_object *rgn_desc; u8 space_id; ACPI_FUNCTION_TRACE_U32(ex_setup_region, field_datum_byte_offset); rgn_desc = obj_desc->common_field.region_obj; /* We must have a valid region */ if (rgn_desc->common.type != ACPI_TYPE_REGION) { ACPI_ERROR((AE_INFO, "Needed Region, found type 0x%X (%s)", rgn_desc->common.type, acpi_ut_get_object_type_name(rgn_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } space_id = rgn_desc->region.space_id; /* Validate the Space ID */ if (!acpi_is_valid_space_id(space_id)) { ACPI_ERROR((AE_INFO, "Invalid/unknown Address Space ID: 0x%2.2X", space_id)); return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID); } /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_region_arguments(rgn_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Exit if Address/Length have been disallowed by the host OS */ if (rgn_desc->common.flags & AOPOBJ_INVALID) { return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); } /* * Exit now for SMBus, GSBus or IPMI address space, it has a non-linear * address space and the request cannot be directly validated */ if (space_id == ACPI_ADR_SPACE_SMBUS || space_id == ACPI_ADR_SPACE_GSBUS || space_id == ACPI_ADR_SPACE_IPMI) { /* SMBus or IPMI has a non-linear address space */ return_ACPI_STATUS(AE_OK); } #ifdef ACPI_UNDER_DEVELOPMENT /* * If the Field access is any_acc, we can now compute the optimal * access (because we know know the length of the parent region) */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } #endif /* * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + obj_desc->common_field.access_byte_width)) { if (acpi_gbl_enable_interpreter_slack) { /* * Slack mode only: We will go ahead and allow access to this * field if it is within the region length rounded up to the next * access width boundary. acpi_size cast for 64-bit compile. */ if (ACPI_ROUND_UP(rgn_desc->region.length, obj_desc->common_field. access_byte_width) >= ((acpi_size) obj_desc->common_field. base_byte_offset + obj_desc->common_field.access_byte_width + field_datum_byte_offset)) { return_ACPI_STATUS(AE_OK); } } if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { /* * This is the case where the access_type (acc_word, etc.) is wider * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ ACPI_ERROR((AE_INFO, "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)", acpi_ut_get_node_name(obj_desc-> common_field.node), obj_desc->common_field.access_byte_width, acpi_ut_get_node_name(rgn_desc->region. node), rgn_desc->region.length)); } /* * Offset rounded up to next multiple of field width * exceeds region length, indicate an error */ ACPI_ERROR((AE_INFO, "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)", acpi_ut_get_node_name(obj_desc->common_field.node), obj_desc->common_field.base_byte_offset, field_datum_byte_offset, obj_desc->common_field.access_byte_width, acpi_ut_get_node_name(rgn_desc->region.node), rgn_desc->region.length)); return_ACPI_STATUS(AE_AML_REGION_LIMIT); } return_ACPI_STATUS(AE_OK); }
static void acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index) { u32 i; ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", level, " ")); /* Display index for package output only */ if (index > 0) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "(%.2u) ", index - 1)); } if (!source_desc) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "<Null Object>\n")); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: ", acpi_ut_get_object_type_name (source_desc))); if (!acpi_ut_valid_internal_object(source_desc)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p, Invalid Internal Object!\n", source_desc)); return_VOID; } } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n", acpi_ut_get_type_name(((struct acpi_namespace_node *)source_desc)-> type), source_desc)); return_VOID; } else { return_VOID; } switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: /* Output correct integer width */ if (acpi_gbl_integer_byte_width == 4) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", (u32) source_desc->integer. value)); } else { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64(source_desc-> integer. value))); } break; case ACPI_TYPE_BUFFER: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER(source_desc->buffer.pointer, (source_desc->buffer.length < 32) ? source_desc->buffer.length : 32); break; case ACPI_TYPE_STRING: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", source_desc->string.length, source_desc->string.pointer)); break; case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X Elements]\n", source_desc->package.count)); /* Output the entire contents of the package */ for (i = 0; i < source_desc->package.count; i++) { acpi_ex_do_debug_object(source_desc->package. elements[i], level + 4, i + 1); } break; case ACPI_TYPE_LOCAL_REFERENCE: if (source_desc->reference.opcode == AML_INDEX_OP) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s, 0x%X]\n", acpi_ps_get_opcode_name (source_desc->reference.opcode), source_desc->reference.offset)); } else { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]\n", acpi_ps_get_opcode_name (source_desc->reference.opcode))); } if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == ACPI_DESC_TYPE_NAMED) { acpi_ex_do_debug_object(((struct acpi_namespace_node *) source_desc->reference. object)->object, level + 4, 0); } else { acpi_ex_do_debug_object(source_desc->reference. object, level + 4, 0); } } else if (source_desc->reference.node) { acpi_ex_do_debug_object((source_desc->reference.node)-> object, level + 4, 0); } break; default: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p %s\n", source_desc, acpi_ut_get_object_type_name (source_desc))); break; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); return_VOID; }
acpi_status acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, struct acpi_namespace_node *node, struct acpi_walk_state *walk_state, u8 implicit_conversion) { acpi_status status = AE_OK; union acpi_operand_object *target_desc; union acpi_operand_object *new_desc; acpi_object_type target_type; ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc); /* Get current type of the node, and object attached to Node */ target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); /* * Resolve the source object to an actual value * (If it is a reference object) */ status = acpi_ex_resolve_object(&source_desc, target_type, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* If no implicit conversion, drop into the default case below */ if ((!implicit_conversion) || (walk_state->opcode == AML_COPY_OP)) { /* Force execution of default (no implicit conversion) */ target_type = ACPI_TYPE_ANY; } /* Do the actual store operation */ switch (target_type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* For fields, copy the source data to the target field. */ status = acpi_ex_write_data_to_field(source_desc, target_desc, &walk_state->result_obj); break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These target types are all of type Integer/String/Buffer, and * therefore support implicit conversion before the store. * * Copy and/or convert the source object to a new target object */ status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (new_desc != target_desc) { /* * Store the new new_desc as the new value of the Name, and set * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * * Note: This may change the type of the node if an explicit store * has been performed such that the node/object type has been * changed. */ status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", acpi_ut_get_object_type_name (source_desc), acpi_ut_get_object_type_name (new_desc))); } break; default: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %s (%p) directly into node (%p) with no implicit conversion\n", acpi_ut_get_object_type_name(source_desc), source_desc, node)); /* No conversions for all other types. Just attach the source object */ status = acpi_ns_attach_object(node, source_desc, ACPI_GET_OBJECT_TYPE (source_desc)); break; } return_ACPI_STATUS(status); }
static acpi_status acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, union acpi_operand_object *index_desc, struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; union acpi_operand_object *obj_desc; union acpi_operand_object *new_desc; u8 value = 0; u32 i; ACPI_FUNCTION_TRACE(ex_store_object_to_index); /* * Destination must be a reference pointer, and * must point to either a buffer or a package */ switch (index_desc->reference.target_type) { case ACPI_TYPE_PACKAGE: /* * Storing to a package element. Copy the object and replace * any existing object with the new object. No implicit * conversion is performed. * * The object at *(index_desc->Reference.Where) is the * element within the package that is to be modified. * The parent package object is at index_desc->Reference.Object */ obj_desc = *(index_desc->reference.where); status = acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (obj_desc) { /* Decrement reference count by the ref count of the parent package */ for (i = 0; i < ((union acpi_operand_object *) index_desc->reference.object)->common. reference_count; i++) { acpi_ut_remove_reference(obj_desc); } } *(index_desc->reference.where) = new_desc; /* Increment ref count by the ref count of the parent package-1 */ for (i = 1; i < ((union acpi_operand_object *) index_desc->reference.object)->common. reference_count; i++) { acpi_ut_add_reference(new_desc); } break; case ACPI_TYPE_BUFFER_FIELD: /* * Store into a Buffer or String (not actually a real buffer_field) * at a location defined by an Index. * * The first 8-bit element of the source object is written to the * 8-bit Buffer location defined by the Index destination object, * according to the ACPI 2.0 specification. */ /* * Make sure the target is a Buffer or String. An error should * not happen here, since the reference_object was constructed * by the INDEX_OP code. */ obj_desc = index_desc->reference.object; if ((ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_BUFFER) && (ACPI_GET_OBJECT_TYPE(obj_desc) != ACPI_TYPE_STRING)) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* * The assignment of the individual elements will be slightly * different for each source type. */ switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: /* Use the least-significant byte of the integer */ value = (u8) (source_desc->integer.value); break; case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: /* Note: Takes advantage of common string/buffer fields */ value = source_desc->buffer.pointer[0]; break; default: /* All other types are invalid */ ACPI_ERROR((AE_INFO, "Source must be Integer/Buffer/String type, not %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* Store the source value into the target buffer byte */ obj_desc->buffer.pointer[index_desc->reference.offset] = value; break; default: ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField")); status = AE_AML_OPERAND_TYPE; break; } return_ACPI_STATUS(status); }
acpi_status acpi_ex_setup_region ( union acpi_operand_object *obj_desc, u32 field_datum_byte_offset) { acpi_status status = AE_OK; union acpi_operand_object *rgn_desc; ACPI_FUNCTION_TRACE_U32 ("ex_setup_region", field_datum_byte_offset); rgn_desc = obj_desc->common_field.region_obj; /* We must have a valid region */ if (ACPI_GET_OBJECT_TYPE (rgn_desc) != ACPI_TYPE_REGION) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Needed Region, found type %X (%s)\n", ACPI_GET_OBJECT_TYPE (rgn_desc), acpi_ut_get_object_type_name (rgn_desc))); return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ if (!(rgn_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_region_arguments (rgn_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { /* SMBus has a non-linear address space */ return_ACPI_STATUS (AE_OK); } #ifdef ACPI_UNDER_DEVELOPMENT /* * If the Field access is any_acc, we can now compute the optimal * access (because we know know the length of the parent region) */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } #endif /* * Validate the request. The entire request from the byte offset for a * length of one field datum (access width) must fit within the region. * (Region length is specified in bytes) */ if (rgn_desc->region.length < (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + obj_desc->common_field.access_byte_width)) { if (rgn_desc->region.length < obj_desc->common_field.access_byte_width) { /* * This is the case where the access_type (acc_word, etc.) is wider * than the region itself. For example, a region of length one * byte, and a field with Dword access specified. */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] access width (%d bytes) too large for region [%4.4s] (length %X)\n", obj_desc->common_field.node->name.ascii, obj_desc->common_field.access_byte_width, rgn_desc->region.node->name.ascii, rgn_desc->region.length)); } /* * Offset rounded up to next multiple of field width * exceeds region length, indicate an error */ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Field [%4.4s] Base+Offset+Width %X+%X+%X is beyond end of region [%4.4s] (length %X)\n", obj_desc->common_field.node->name.ascii, obj_desc->common_field.base_byte_offset, field_datum_byte_offset, obj_desc->common_field.access_byte_width, rgn_desc->region.node->name.ascii, rgn_desc->region.length)); #ifdef CONFIG_ACPI_RELAXED_AML { /* * Allow access to the field if it is within the region size * rounded up to a multiple of the access byte width. This * overcomes "off-by-one" programming errors in the AML often * found in Toshiba laptops. These errors were allowed by * the Microsoft ASL compiler. */ u32 rounded_length = ACPI_ROUND_UP(rgn_desc->region.length, obj_desc->common_field.access_byte_width); if (rounded_length < (obj_desc->common_field.base_byte_offset + field_datum_byte_offset + obj_desc->common_field.access_byte_width)) { return_ACPI_STATUS (AE_AML_REGION_LIMIT); } else { static int warn_once = 1; if (warn_once) { // Could also associate a flag with each field, and // warn once for each field. ACPI_REPORT_WARNING(( "The ACPI AML in your computer contains errors, " "please nag the manufacturer to correct it.\n")); ACPI_REPORT_WARNING(( "Allowing relaxed access to fields; " "turn on CONFIG_ACPI_DEBUG for details.\n")); warn_once = 0; } return_ACPI_STATUS (AE_OK); } } #else return_ACPI_STATUS (AE_AML_REGION_LIMIT); #endif } return_ACPI_STATUS (AE_OK); }
acpi_status acpi_ex_load_op(union acpi_operand_object *obj_desc, union acpi_operand_object *target, struct acpi_walk_state *walk_state) { acpi_status status; union acpi_operand_object *ddb_handle; union acpi_operand_object *buffer_desc = NULL; struct acpi_table_header *table_ptr = NULL; acpi_physical_address address; struct acpi_table_header table_header; acpi_integer temp; u32 i; ACPI_FUNCTION_TRACE(ex_load_op); /* Object can be either an op_region or a Field */ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_region_arguments(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Get the base physical address of the region */ address = obj_desc->region.address; /* Get part of the table header to get the table length */ table_header.length = 0; for (i = 0; i < 8; i++) { status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, &temp); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Get the one valid byte of the returned 64-bit value */ ACPI_CAST_PTR(u8, &table_header)[i] = (u8) temp; } /* Sanity check the table length */ if (table_header.length < sizeof(struct acpi_table_header)) { return_ACPI_STATUS(AE_BAD_HEADER); } /* Allocate a buffer for the entire table */ table_ptr = ACPI_ALLOCATE(table_header.length); if (!table_ptr) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Get the entire table from the op region */ for (i = 0; i < table_header.length; i++) { status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, &temp); if (ACPI_FAILURE(status)) { goto cleanup; } /* Get the one valid byte of the returned 64-bit value */ ACPI_CAST_PTR(u8, table_ptr)[i] = (u8) temp; } break; case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); /* * The length of the field must be at least as large as the table. * Read the entire field and thus the entire table. Buffer is * allocated during the read. */ status = acpi_ex_read_data_from_field(walk_state, obj_desc, &buffer_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } table_ptr = ACPI_CAST_PTR(struct acpi_table_header, buffer_desc->buffer.pointer); /* All done with the buffer_desc, delete it */ buffer_desc->buffer.pointer = NULL; acpi_ut_remove_reference(buffer_desc); /* Sanity check the table length */ if (table_ptr->length < sizeof(struct acpi_table_header)) { status = AE_BAD_HEADER; goto cleanup; } break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* The table must be either an SSDT or a PSDT or an OEMx */ if ((!ACPI_COMPARE_NAME(table_ptr->signature, PSDT_SIG)) && (!ACPI_COMPARE_NAME(table_ptr->signature, SSDT_SIG)) && (strncmp(table_ptr->signature, "OEM", 3))) { ACPI_ERROR((AE_INFO, "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx", table_ptr->signature)); status = AE_BAD_SIGNATURE; goto cleanup; } /* Install the new table into the local data structures */ status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ return_ACPI_STATUS(status); } /* Store the ddb_handle into the Target operand */ status = acpi_ex_store(ddb_handle, target, walk_state); if (ACPI_FAILURE(status)) { (void)acpi_ex_unload_table(ddb_handle); /* table_ptr was deallocated above */ return_ACPI_STATUS(status); } ACPI_INFO((AE_INFO, "Dynamic SSDT Load - OemId [%6.6s] OemTableId [%8.8s]", table_ptr->oem_id, table_ptr->oem_table_id)); cleanup: if (ACPI_FAILURE(status)) { ACPI_FREE(table_ptr); } return_ACPI_STATUS(status); }
static acpi_status acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, acpi_size * obj_length) { acpi_size length; acpi_size size; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); if (!internal_object) { *obj_length = sizeof(union acpi_object); return_ACPI_STATUS(AE_OK); } length = sizeof(union acpi_object); if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(status); } switch (internal_object->common.type) { case ACPI_TYPE_STRING: length += (acpi_size) internal_object->string.length + 1; break; case ACPI_TYPE_BUFFER: length += (acpi_size) internal_object->buffer.length; break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: break; case ACPI_TYPE_LOCAL_REFERENCE: switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: size = acpi_ns_get_pathname_length(internal_object-> reference.node); if (!size) { return_ACPI_STATUS(AE_BAD_PARAMETER); } length += ACPI_ROUND_UP_TO_NATIVE_WORD(size); break; default: ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported Reference Class [%s] %X in object %p", acpi_ut_get_reference_name(internal_object), internal_object->reference.class, internal_object)); status = AE_TYPE; break; } break; default: ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported type [%s] %X in object %p", acpi_ut_get_object_type_name(internal_object), internal_object->common.type, internal_object)); status = AE_TYPE; break; } *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(status); }
acpi_status acpi_ns_simple_repair(struct acpi_evaluate_info *info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_object = NULL; acpi_status status; const struct acpi_simple_repair_info *predefined; ACPI_FUNCTION_NAME(ns_simple_repair); /* * Special repairs for certain names that are in the repair table. * Check if this name is in the list of repairable names. */ predefined = acpi_ns_match_simple_repair(info->node, info->return_btype, package_index); if (predefined) { if (!return_object) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); } status = predefined->object_converter(info->node, return_object, &new_object); if (ACPI_FAILURE(status)) { /* A fatal error occurred during a conversion */ ACPI_EXCEPTION((AE_INFO, status, "During return object analysis")); return (status); } if (new_object) { goto object_repaired; } } /* * Do not perform simple object repair unless the return type is not * expected. */ if (info->return_btype & expected_btypes) { return (AE_OK); } /* * At this point, we know that the type of the returned object was not * one of the expected types for this predefined name. Attempt to * repair the object by converting it to one of the expected object * types for this predefined name. */ /* * If there is no return value, check if we require a return value for * this predefined name. Either one return value is expected, or none, * for both methods and other objects. * * Try to fix if there was no return object. Warning if failed to fix. */ if (!return_object) { if (expected_btypes && (!(expected_btypes & ACPI_RTYPE_NONE))) { if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, ACPI_WARN_ALWAYS, "Found unexpected NULL package element")); status = acpi_ns_repair_null_element(info, expected_btypes, package_index, return_object_ptr); if (ACPI_SUCCESS(status)) { return (AE_OK); /* Repair was successful */ } } else { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, ACPI_WARN_ALWAYS, "Missing expected return value")); } return (AE_AML_NO_RETURN_VALUE); } } if (expected_btypes & ACPI_RTYPE_INTEGER) { status = acpi_ns_convert_to_integer(return_object, &new_object); if (ACPI_SUCCESS(status)) { goto object_repaired; } } if (expected_btypes & ACPI_RTYPE_STRING) { status = acpi_ns_convert_to_string(return_object, &new_object); if (ACPI_SUCCESS(status)) { goto object_repaired; } } if (expected_btypes & ACPI_RTYPE_BUFFER) { status = acpi_ns_convert_to_buffer(return_object, &new_object); if (ACPI_SUCCESS(status)) { goto object_repaired; } } if (expected_btypes & ACPI_RTYPE_PACKAGE) { /* * A package is expected. We will wrap the existing object with a * new package object. It is often the case that if a variable-length * package is required, but there is only a single object needed, the * BIOS will return that object instead of wrapping it with a Package * object. Note: after the wrapping, the package will be validated * for correct contents (expected object type or types). */ status = acpi_ns_wrap_with_package(info, return_object, &new_object); if (ACPI_SUCCESS(status)) { /* * The original object just had its reference count * incremented for being inserted into the new package. */ *return_object_ptr = new_object; /* New Package object */ info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } } /* We cannot repair this object */ return (AE_AML_OPERAND_TYPE); object_repaired: /* Object was successfully repaired */ if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { /* * The original object is a package element. We need to * decrement the reference count of the original object, * for removing it from the package. * * However, if the original object was just wrapped with a * package object as part of the repair, we don't need to * change the reference count. */ if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) { new_object->common.reference_count = return_object->common.reference_count; if (return_object->common.reference_count > 1) { return_object->common.reference_count--; } } ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted %s to expected %s at Package index %u\n", info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object), package_index)); } else { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted %s to expected %s\n", info->full_pathname, acpi_ut_get_object_type_name(return_object), acpi_ut_get_object_type_name(new_object))); } /* Delete old object, install the new return object */ acpi_ut_remove_reference(return_object); *return_object_ptr = new_object; info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }
static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) { void *obj_pointer = NULL; union acpi_operand_object *handler_desc; union acpi_operand_object *second_desc; union acpi_operand_object *next_desc; ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); if (!object) { return_VOID; } /* * Must delete or free any pointers within the object that are not * actual ACPI objects (for example, a raw buffer pointer). */ switch (ACPI_GET_OBJECT_TYPE(object)) { case ACPI_TYPE_STRING: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n", object, object->string.pointer)); /* Free the actual string buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->string.pointer; } break; case ACPI_TYPE_BUFFER: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n", object, object->buffer.pointer)); /* Free the actual buffer */ if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { /* But only if it is NOT a pointer into an ACPI table */ obj_pointer = object->buffer.pointer; } break; case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n", object->package.count)); /* * Elements of the package are not handled here, they are deleted * separately */ /* Free the (variable length) element pointer array */ obj_pointer = object->package.elements; break; case ACPI_TYPE_DEVICE: if (object->device.gpe_block) { (void)acpi_ev_delete_gpe_block(object->device. gpe_block); } /* Walk the handler list for this device */ handler_desc = object->device.handler; while (handler_desc) { next_desc = handler_desc->address_space.next; acpi_ut_remove_reference(handler_desc); handler_desc = next_desc; } break; case ACPI_TYPE_MUTEX: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Mutex %p, OS Mutex %p\n", object, object->mutex.os_mutex)); if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) { /* Global Lock has extra semaphore */ (void) acpi_os_delete_semaphore (acpi_gbl_global_lock_semaphore); acpi_gbl_global_lock_semaphore = NULL; acpi_os_delete_mutex(object->mutex.os_mutex); acpi_gbl_global_lock_mutex = NULL; } else { acpi_ex_unlink_mutex(object); acpi_os_delete_mutex(object->mutex.os_mutex); } break; case ACPI_TYPE_EVENT: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Event %p, OS Semaphore %p\n", object, object->event.os_semaphore)); (void)acpi_os_delete_semaphore(object->event.os_semaphore); object->event.os_semaphore = NULL; break; case ACPI_TYPE_METHOD: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Method %p\n", object)); /* Delete the method mutex if it exists */ if (object->method.mutex) { acpi_os_delete_mutex(object->method.mutex->mutex. os_mutex); acpi_ut_delete_object_desc(object->method.mutex); object->method.mutex = NULL; } break; case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Region %p\n", object)); second_desc = acpi_ns_get_secondary_object(object); if (second_desc) { /* * Free the region_context if and only if the handler is one of the * default handlers -- and therefore, we created the context object * locally, it was not created by an external caller. */ handler_desc = object->region.handler; if (handler_desc) { if (handler_desc->address_space.handler_flags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { /* Deactivate region and free region context */ if (handler_desc->address_space.setup) { (void)handler_desc-> address_space.setup(object, ACPI_REGION_DEACTIVATE, handler_desc-> address_space. context, &second_desc-> extra. region_context); } } acpi_ut_remove_reference(handler_desc); } /* Now we can free the Extra object */ acpi_ut_delete_object_desc(second_desc); } break; case ACPI_TYPE_BUFFER_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Buffer Field %p\n", object)); second_desc = acpi_ns_get_secondary_object(object); if (second_desc) { acpi_ut_delete_object_desc(second_desc); } break; default: break; } /* Free any allocated memory (pointer within the object) found above */ if (obj_pointer) { ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", obj_pointer)); ACPI_FREE(obj_pointer); } /* Now the object can be safely deleted */ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", object, acpi_ut_get_object_type_name(object))); acpi_ut_delete_object_desc(object); return_VOID; }
acpi_status acpi_ut_evaluate_object(struct acpi_namespace_node * prefix_node, char *path, u32 expected_return_btypes, union acpi_operand_object **return_desc) { struct acpi_evaluate_info *info; acpi_status status; u32 return_btype; ACPI_FUNCTION_TRACE(ut_evaluate_object); /* Allocate the evaluation information block */ info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); if (!info) { return_ACPI_STATUS(AE_NO_MEMORY); } info->prefix_node = prefix_node; info->pathname = path; /* Evaluate the object/method */ status = acpi_ns_evaluate(info); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s.%s] was not found\n", acpi_ut_get_node_name(prefix_node), path)); } else { ACPI_ERROR_METHOD("Method execution failed", prefix_node, path, status); } goto cleanup; } /* Did we get a return object? */ if (!info->return_object) { if (expected_return_btypes) { ACPI_ERROR_METHOD("No object was returned from", prefix_node, path, AE_NOT_EXIST); status = AE_NOT_EXIST; } goto cleanup; } /* Map the return object type to the bitmapped type */ switch ((info->return_object)->common.type) { case ACPI_TYPE_INTEGER: return_btype = ACPI_BTYPE_INTEGER; break; case ACPI_TYPE_BUFFER: return_btype = ACPI_BTYPE_BUFFER; break; case ACPI_TYPE_STRING: return_btype = ACPI_BTYPE_STRING; break; case ACPI_TYPE_PACKAGE: return_btype = ACPI_BTYPE_PACKAGE; break; default: return_btype = 0; break; } if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { /* * We received a return object, but one was not expected. This can * happen frequently if the "implicit return" feature is enabled. * Just delete the return object and return AE_OK. */ acpi_ut_remove_reference(info->return_object); goto cleanup; } /* Is the return object one of the expected types? */ if (!(expected_return_btypes & return_btype)) { ACPI_ERROR_METHOD("Return object type is incorrect", prefix_node, path, AE_TYPE); ACPI_ERROR((AE_INFO, "Type returned from %s was incorrect: %s, expected Btypes: 0x%X", path, acpi_ut_get_object_type_name(info->return_object), expected_return_btypes)); /* On error exit, we must delete the return object */ acpi_ut_remove_reference(info->return_object); status = AE_TYPE; goto cleanup; } /* Object type is OK, return it */ *return_desc = info->return_object; cleanup: ACPI_FREE(info); return_ACPI_STATUS(status); }
acpi_status acpi_ns_repair_null_element(struct acpi_evaluate_info * info, u32 expected_btypes, u32 package_index, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; union acpi_operand_object *new_object; ACPI_FUNCTION_NAME(ns_repair_null_element); /* No repair needed if return object is non-NULL */ if (return_object) { return (AE_OK); } /* * Attempt to repair a NULL element of a Package object. This applies to * predefined names that return a fixed-length package and each element * is required. It does not apply to variable-length packages where NULL * elements are allowed, especially at the end of the package. */ if (expected_btypes & ACPI_RTYPE_INTEGER) { /* Need an integer - create a zero-value integer */ new_object = acpi_ut_create_integer_object((u64)0); } else if (expected_btypes & ACPI_RTYPE_STRING) { /* Need a string - create a NULL string */ new_object = acpi_ut_create_string_object(0); } else if (expected_btypes & ACPI_RTYPE_BUFFER) { /* Need a buffer - create a zero-length buffer */ new_object = acpi_ut_create_buffer_object(0); } else { /* Error for all other expected types */ return (AE_AML_OPERAND_TYPE); } if (!new_object) { return (AE_NO_MEMORY); } /* Set the reference count according to the parent Package object */ new_object->common.reference_count = info->parent_package->common.reference_count; ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Converted NULL package element to expected %s at index %u\n", info->full_pathname, acpi_ut_get_object_type_name(new_object), package_index)); *return_object_ptr = new_object; info->return_flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }
acpi_status acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc) { acpi_status status; u32 length; void *buffer; union acpi_operand_object *buffer_desc; u32 function; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); if (!source_desc || !obj_desc) { return_ACPI_STATUS(AE_AML_NO_OPERAND); } if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_field_arguments(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI)) { if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS) { length = ACPI_SMBUS_BUFFER_SIZE; function = ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { length = ACPI_GSBUS_BUFFER_SIZE; function = ACPI_WRITE | (obj_desc->field.attribute << 16); } else { length = ACPI_IPMI_BUFFER_SIZE; function = ACPI_WRITE; } if (source_desc->buffer.length < length) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u", length, source_desc->buffer.length)); return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); } buffer_desc = acpi_ut_create_buffer_object(length); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } buffer = buffer_desc->buffer.pointer; ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); status = acpi_ex_access_region(obj_desc, 0, (u64 *) buffer, function); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); } /* Get a pointer to the data to be written */ switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: buffer = source_desc->buffer.pointer; length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: buffer = source_desc->string.pointer; length = source_desc->string.length; break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(source_desc->common.type), source_desc->common.type, buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, acpi_ut_get_type_name(obj_desc->common.type), obj_desc->common.type, obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); status = acpi_ex_insert_into_field(obj_desc, buffer, length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); }
static acpi_status acpi_ds_init_buffer_field(u16 aml_opcode, union acpi_operand_object *obj_desc, union acpi_operand_object *buffer_desc, union acpi_operand_object *offset_desc, union acpi_operand_object *length_desc, union acpi_operand_object *result_desc) { u32 offset; u32 bit_offset; u32 bit_count; u8 field_flags; acpi_status status; ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); /* Host object must be a Buffer */ if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "Target of Create Field is not a Buffer object - %s", acpi_ut_get_object_type_name(buffer_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; } /* * The last parameter to all of these opcodes (result_desc) started * out as a name_string, and should therefore now be a NS node * after resolution in acpi_ex_resolve_operands(). */ if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR((AE_INFO, "(%s) destination not a NS Node [%s]", acpi_ps_get_opcode_name(aml_opcode), acpi_ut_get_descriptor_name(result_desc))); status = AE_AML_OPERAND_TYPE; goto cleanup; } offset = (u32) offset_desc->integer.value; /* * Setup the Bit offsets and counts, according to the opcode */ switch (aml_opcode) { case AML_CREATE_FIELD_OP: /* Offset is in bits, count is in bits */ field_flags = AML_FIELD_ACCESS_BYTE; bit_offset = offset; bit_count = (u32) length_desc->integer.value; /* Must have a valid (>0) bit count */ if (bit_count == 0) { ACPI_ERROR((AE_INFO, "Attempt to CreateField of length zero")); status = AE_AML_OPERAND_VALUE; goto cleanup; } break; case AML_CREATE_BIT_FIELD_OP: /* Offset is in bits, Field is one bit */ bit_offset = offset; bit_count = 1; field_flags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_BYTE_FIELD_OP: /* Offset is in bytes, field is one byte */ bit_offset = 8 * offset; bit_count = 8; field_flags = AML_FIELD_ACCESS_BYTE; break; case AML_CREATE_WORD_FIELD_OP: /* Offset is in bytes, field is one word */ bit_offset = 8 * offset; bit_count = 16; field_flags = AML_FIELD_ACCESS_WORD; break; case AML_CREATE_DWORD_FIELD_OP: /* Offset is in bytes, field is one dword */ bit_offset = 8 * offset; bit_count = 32; field_flags = AML_FIELD_ACCESS_DWORD; break; case AML_CREATE_QWORD_FIELD_OP: /* Offset is in bytes, field is one qword */ bit_offset = 8 * offset; bit_count = 64; field_flags = AML_FIELD_ACCESS_QWORD; break; default: ACPI_ERROR((AE_INFO, "Unknown field creation opcode 0x%02X", aml_opcode)); status = AE_AML_BAD_OPCODE; goto cleanup; } /* Entire field must fit within the current length of the buffer */ if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { ACPI_ERROR((AE_INFO, "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", acpi_ut_get_node_name(result_desc), bit_offset + bit_count, acpi_ut_get_node_name(buffer_desc->buffer.node), 8 * (u32) buffer_desc->buffer.length)); status = AE_AML_BUFFER_LIMIT; goto cleanup; } /* * Initialize areas of the field object that are common to all fields * For field_flags, use LOCK_RULE = 0 (NO_LOCK), * UPDATE_RULE = 0 (UPDATE_PRESERVE) */ status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, bit_offset, bit_count); if (ACPI_FAILURE(status)) { goto cleanup; } obj_desc->buffer_field.buffer_obj = buffer_desc; /* Reference count for buffer_desc inherits obj_desc count */ buffer_desc->common.reference_count = (u16) (buffer_desc->common.reference_count + obj_desc->common.reference_count); cleanup: /* Always delete the operands */ acpi_ut_remove_reference(offset_desc); acpi_ut_remove_reference(buffer_desc); if (aml_opcode == AML_CREATE_FIELD_OP) { acpi_ut_remove_reference(length_desc); } /* On failure, delete the result descriptor */ if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(result_desc); /* Result descriptor */ } else { /* Now the address and length are valid for this buffer_field */ obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; } return_ACPI_STATUS(status); }
acpi_status acpi_ex_convert_to_target_type(acpi_object_type destination_type, union acpi_operand_object *source_desc, union acpi_operand_object **result_desc, struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(ex_convert_to_target_type); /* Default behavior */ *result_desc = source_desc; /* * If required by the target, * perform implicit conversion on the source before we store it. */ switch (GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args)) { case ARGI_SIMPLE_TARGET: case ARGI_FIXED_TARGET: case ARGI_INTEGER_REF: /* Handles Increment, Decrement cases */ switch (destination_type) { case ACPI_TYPE_LOCAL_REGION_FIELD: /* * Named field can always handle conversions */ break; default: /* No conversion allowed for these types */ if (destination_type != ACPI_GET_OBJECT_TYPE(source_desc)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Explicit operator, will store (%s) over existing type (%s)\n", acpi_ut_get_object_type_name (source_desc), acpi_ut_get_type_name (destination_type))); status = AE_TYPE; } } break; case ARGI_TARGETREF: switch (destination_type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: /* * These types require an Integer operand. We can convert * a Buffer or a String to an Integer if necessary. */ status = acpi_ex_convert_to_integer(source_desc, result_desc, 16); break; case ACPI_TYPE_STRING: /* * The operand must be a String. We can convert an * Integer or Buffer if necessary */ status = acpi_ex_convert_to_string(source_desc, result_desc, ACPI_IMPLICIT_CONVERT_HEX); break; case ACPI_TYPE_BUFFER: /* * The operand must be a Buffer. We can convert an * Integer or String if necessary */ status = acpi_ex_convert_to_buffer(source_desc, result_desc); break; default: ACPI_ERROR((AE_INFO, "Bad destination type during conversion: %X", destination_type)); status = AE_AML_INTERNAL; break; } break; case ARGI_REFERENCE: /* * create_xxxx_field cases - we are storing the field object into the name */ break; default: ACPI_ERROR((AE_INFO, "Unknown Target type ID 0x%X AmlOpcode %X DestType %s", GET_CURRENT_ARG_TYPE(walk_state->op_info->runtime_args), walk_state->opcode, acpi_ut_get_type_name(destination_type))); status = AE_AML_INTERNAL; } /* * Source-to-Target conversion semantics: * * If conversion to the target type cannot be performed, then simply * overwrite the target with the new object and type. */ if (status == AE_TYPE) { status = AE_OK; } return_ACPI_STATUS(status); }
static void acpi_ex_dump_object(union acpi_operand_object *obj_desc, struct acpi_exdump_info *info) { u8 *target; char *name; u8 count; if (!info) { acpi_os_printf ("ExDumpObject: Display not implemented for object type %s\n", acpi_ut_get_object_type_name(obj_desc)); return; } /* First table entry must contain the table length (# of table entries) */ count = info->offset; while (count) { target = ACPI_ADD_PTR(u8, obj_desc, info->offset); name = info->name; switch (info->opcode) { case ACPI_EXD_INIT: break; case ACPI_EXD_TYPE: acpi_ex_out_string("Type", acpi_ut_get_object_type_name (obj_desc)); break; case ACPI_EXD_UINT8: acpi_os_printf("%20s : %2.2X\n", name, *target); break; case ACPI_EXD_UINT16: acpi_os_printf("%20s : %4.4X\n", name, ACPI_GET16(target)); break; case ACPI_EXD_UINT32: acpi_os_printf("%20s : %8.8X\n", name, ACPI_GET32(target)); break; case ACPI_EXD_UINT64: acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", ACPI_FORMAT_UINT64(ACPI_GET64(target))); break; case ACPI_EXD_POINTER: acpi_ex_out_pointer(name, *ACPI_CAST_PTR(void *, target)); break; case ACPI_EXD_ADDRESS: acpi_ex_out_address(name, *ACPI_CAST_PTR (acpi_physical_address, target)); break; case ACPI_EXD_STRING: acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf("\n"); break; case ACPI_EXD_BUFFER: ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, obj_desc->buffer.length); break; case ACPI_EXD_PACKAGE: /* Dump the package contents */ acpi_os_printf("\nPackage Contents:\n"); acpi_ex_dump_package_obj(obj_desc, 0, 0); break; case ACPI_EXD_FIELD: acpi_ex_dump_object(obj_desc, acpi_ex_dump_field_common); break; case ACPI_EXD_REFERENCE: acpi_ex_out_string("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))-> name); acpi_ex_dump_reference_obj(obj_desc); break; default: acpi_os_printf("**** Invalid table opcode [%X] ****\n", info->opcode); return; } info++; count--; } }
acpi_status acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, union acpi_operand_object *obj_desc, union acpi_operand_object **result_desc) { acpi_status status; u32 length; void *buffer; union acpi_operand_object *buffer_desc; u32 function; u16 accessor_type; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); /* Parameter validation */ if (!source_desc || !obj_desc) { return_ACPI_STATUS(AE_AML_NO_OPERAND); } if (obj_desc->common.type == ACPI_TYPE_BUFFER_FIELD) { /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_field_arguments(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS || obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_IPMI)) { /* * This is an SMBus, GSBus or IPMI write. We will bypass the entire field * mechanism and handoff the buffer directly to the handler. For * these address spaces, the buffer is bi-directional; on a write, * return data is returned in the same buffer. * * Source must be a buffer of sufficient size: * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. * * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function */ if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_SMBUS) { length = ACPI_SMBUS_BUFFER_SIZE; function = ACPI_WRITE | (obj_desc->field.attribute << 16); } else if (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) { accessor_type = obj_desc->field.attribute; length = acpi_ex_get_serial_access_length(accessor_type, obj_desc-> field. access_length); /* * Add additional 2 bytes for the generic_serial_bus data buffer: * * Status; (Byte 0 of the data buffer) * Length; (Byte 1 of the data buffer) * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer) */ length += 2; function = ACPI_WRITE | (accessor_type << 16); } else { /* IPMI */ length = ACPI_IPMI_BUFFER_SIZE; function = ACPI_WRITE; } if (source_desc->buffer.length < length) { ACPI_ERROR((AE_INFO, "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u", length, source_desc->buffer.length)); return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); } /* Create the bi-directional buffer */ buffer_desc = acpi_ut_create_buffer_object(length); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } buffer = buffer_desc->buffer.pointer; ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* * Perform the write (returns status and perhaps data in the * same buffer) */ status = acpi_ex_access_region(obj_desc, 0, (u64 *) buffer, function); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; return_ACPI_STATUS(status); } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) { /* * For GPIO (general_purpose_io), we will bypass the entire field * mechanism and handoff the bit address and bit width directly to * the handler. The Address will be the bit offset * from the previous Connection() operator, making it effectively a * pin number index. The bit_length is the length of the field, which * is thus the number of pins. */ if (source_desc->common.type != ACPI_TYPE_INTEGER) { return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n", acpi_ut_get_type_name(source_desc->common. type), source_desc->common.type, (u32)source_desc->integer.value, obj_desc->field.pin_number_index, obj_desc->field.bit_length)); buffer = &source_desc->integer.value; /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Perform the write */ status = acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, ACPI_WRITE); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); } /* Get a pointer to the data to be written */ switch (source_desc->common.type) { case ACPI_TYPE_INTEGER: buffer = &source_desc->integer.value; length = sizeof(source_desc->integer.value); break; case ACPI_TYPE_BUFFER: buffer = source_desc->buffer.pointer; length = source_desc->buffer.length; break; case ACPI_TYPE_STRING: buffer = source_desc->string.pointer; length = source_desc->string.length; break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", source_desc, acpi_ut_get_type_name(source_desc->common.type), source_desc->common.type, buffer, length)); ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "FieldWrite [TO]: Obj %p (%s:%X), BitLen %X, BitOff %X, ByteOff %X\n", obj_desc, acpi_ut_get_type_name(obj_desc->common.type), obj_desc->common.type, obj_desc->common_field.bit_length, obj_desc->common_field.start_field_bit_offset, obj_desc->common_field.base_byte_offset)); /* Lock entire transaction if requested */ acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); /* Write to the field */ status = acpi_ex_insert_into_field(obj_desc, buffer, length); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); return_ACPI_STATUS(status); }
acpi_status acpi_ex_store(union acpi_operand_object *source_desc, union acpi_operand_object *dest_desc, struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; union acpi_operand_object *ref_desc = dest_desc; ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc); /* Validate parameters */ if (!source_desc || !dest_desc) { ACPI_ERROR((AE_INFO, "Null parameter")); return_ACPI_STATUS(AE_AML_NO_OPERAND); } /* dest_desc can be either a namespace node or an ACPI object */ if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) { /* * Dest is a namespace node, * Storing an object into a Named node. */ status = acpi_ex_store_object_to_node(source_desc, (struct acpi_namespace_node *) dest_desc, walk_state, ACPI_IMPLICIT_CONVERSION); return_ACPI_STATUS(status); } /* Destination object must be a Reference or a Constant object */ switch (ACPI_GET_OBJECT_TYPE(dest_desc)) { case ACPI_TYPE_LOCAL_REFERENCE: break; case ACPI_TYPE_INTEGER: /* Allow stores to Constants -- a Noop as per ACPI spec */ if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) { return_ACPI_STATUS(AE_OK); } /*lint -fallthrough */ default: /* Destination is not a Reference object */ ACPI_ERROR((AE_INFO, "Target is not a Reference or Constant object - %s [%p]", acpi_ut_get_object_type_name(dest_desc), dest_desc)); ACPI_DUMP_STACK_ENTRY(source_desc); ACPI_DUMP_STACK_ENTRY(dest_desc); ACPI_DUMP_OPERANDS(&dest_desc, ACPI_IMODE_EXECUTE, "ExStore", 2, "Target is not a Reference or Constant object"); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* * Examine the Reference opcode. These cases are handled: * * 1) Store to Name (Change the object associated with a name) * 2) Store to an indexed area of a Buffer or Package * 3) Store to a Method Local or Arg * 4) Store to the debug object */ switch (ref_desc->reference.opcode) { case AML_NAME_OP: case AML_REF_OF_OP: /* Storing an object into a Name "container" */ status = acpi_ex_store_object_to_node(source_desc, ref_desc->reference. object, walk_state, ACPI_IMPLICIT_CONVERSION); break; case AML_INDEX_OP: /* Storing to an Index (pointer into a packager or buffer) */ status = acpi_ex_store_object_to_index(source_desc, ref_desc, walk_state); break; case AML_LOCAL_OP: case AML_ARG_OP: /* Store to a method local/arg */ status = acpi_ds_store_object_to_local(ref_desc->reference.opcode, ref_desc->reference.offset, source_desc, walk_state); break; case AML_DEBUG_OP: /* * Storing to the Debug object causes the value stored to be * displayed and otherwise has no effect -- see ACPI Specification */ ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "**** Write to Debug Object: Object %p %s ****:\n\n", source_desc, acpi_ut_get_object_type_name(source_desc))); acpi_ex_do_debug_object(source_desc, 0, 0); break; default: ACPI_ERROR((AE_INFO, "Unknown Reference opcode %X", ref_desc->reference.opcode)); ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_ERROR); status = AE_AML_INTERNAL; break; } return_ACPI_STATUS(status); }
static acpi_status acpi_ut_get_simple_object_size(union acpi_operand_object *internal_object, acpi_size * obj_length) { acpi_size length; acpi_size size; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR(ut_get_simple_object_size, internal_object); /* * Handle a null object (Could be a uninitialized package * element -- which is legal) */ if (!internal_object) { *obj_length = sizeof(union acpi_object); return_ACPI_STATUS(AE_OK); } /* Start with the length of the Acpi object */ length = sizeof(union acpi_object); if (ACPI_GET_DESCRIPTOR_TYPE(internal_object) == ACPI_DESC_TYPE_NAMED) { /* Object is a named object (reference), just return the length */ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(status); } /* * The final length depends on the object type * Strings and Buffers are packed right up against the parent object and * must be accessed bytewise or there may be alignment problems on * certain processors */ switch (internal_object->common.type) { case ACPI_TYPE_STRING: length += (acpi_size) internal_object->string.length + 1; break; case ACPI_TYPE_BUFFER: length += (acpi_size) internal_object->buffer.length; break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: /* No extra data for these types */ break; case ACPI_TYPE_LOCAL_REFERENCE: switch (internal_object->reference.class) { case ACPI_REFCLASS_NAME: /* * Get the actual length of the full pathname to this object. * The reference will be converted to the pathname to the object */ size = acpi_ns_get_pathname_length(internal_object-> reference.node); if (!size) { return_ACPI_STATUS(AE_BAD_PARAMETER); } length += ACPI_ROUND_UP_TO_NATIVE_WORD(size); break; default: /* * No other reference opcodes are supported. * Notably, Locals and Args are not supported, but this may be * required eventually. */ ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported Reference Class [%s] %X in object %p", acpi_ut_get_reference_name(internal_object), internal_object->reference.class, internal_object)); status = AE_TYPE; break; } break; default: ACPI_ERROR((AE_INFO, "Cannot convert to external object - " "unsupported type [%s] %X in object %p", acpi_ut_get_object_type_name(internal_object), internal_object->common.type, internal_object)); status = AE_TYPE; break; } /* * Account for the space required by the object rounded up to the next * multiple of the machine word size. This keeps each object aligned * on a machine word boundary. (preventing alignment faults on some * machines.) */ *obj_length = ACPI_ROUND_UP_TO_NATIVE_WORD(length); return_ACPI_STATUS(status); }
acpi_status acpi_ex_field_datum_io ( union acpi_operand_object *obj_desc, u32 field_datum_byte_offset, acpi_integer *value, u32 read_write) { acpi_status status; acpi_integer local_value; ACPI_FUNCTION_TRACE_U32 ("ex_field_datum_io", field_datum_byte_offset); if (read_write == ACPI_READ) { if (!value) { local_value = 0; value = &local_value; /* To support reads without saving return value */ } /* Clear the entire return buffer first, [Very Important!] */ *value = 0; } /* * The four types of fields are: * * buffer_field - Read/write from/to a Buffer * region_field - Read/write from/to a Operation Region. * bank_field - Write to a Bank Register, then read/write from/to an op_region * index_field - Write to an Index Register, then read/write from/to a Data Register */ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_BUFFER_FIELD: /* * If the buffer_field arguments have not been previously evaluated, * evaluate them now and save the results. */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_buffer_field_arguments (obj_desc); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } if (read_write == ACPI_READ) { /* * Copy the data from the source buffer. * Length is the field width in bytes. */ ACPI_MEMCPY (value, (obj_desc->buffer_field.buffer_obj)->buffer.pointer + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, obj_desc->common_field.access_byte_width); } else { /* * Copy the data to the target buffer. * Length is the field width in bytes. */ ACPI_MEMCPY ((obj_desc->buffer_field.buffer_obj)->buffer.pointer + obj_desc->buffer_field.base_byte_offset + field_datum_byte_offset, value, obj_desc->common_field.access_byte_width); } status = AE_OK; break; case ACPI_TYPE_LOCAL_BANK_FIELD: /* Ensure that the bank_value is not beyond the capacity of the register */ if (acpi_ex_register_overflow (obj_desc->bank_field.bank_obj, (acpi_integer) obj_desc->bank_field.value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } /* * For bank_fields, we must write the bank_value to the bank_register * (itself a region_field) before we can access the data. */ status = acpi_ex_insert_into_field (obj_desc->bank_field.bank_obj, &obj_desc->bank_field.value, sizeof (obj_desc->bank_field.value)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * Now that the Bank has been selected, fall through to the * region_field case and write the datum to the Operation Region */ /*lint -fallthrough */ case ACPI_TYPE_LOCAL_REGION_FIELD: /* * For simple region_fields, we just directly access the owning * Operation Region. */ status = acpi_ex_access_region (obj_desc, field_datum_byte_offset, value, read_write); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: /* Ensure that the index_value is not beyond the capacity of the register */ if (acpi_ex_register_overflow (obj_desc->index_field.index_obj, (acpi_integer) obj_desc->index_field.value)) { return_ACPI_STATUS (AE_AML_REGISTER_LIMIT); } /* Write the index value to the index_register (itself a region_field) */ field_datum_byte_offset += obj_desc->index_field.value; ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Write to Index Register: Value %8.8X\n", field_datum_byte_offset)); status = acpi_ex_insert_into_field (obj_desc->index_field.index_obj, &field_datum_byte_offset, sizeof (field_datum_byte_offset)); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "I/O to Data Register: value_ptr %p\n", value)); if (read_write == ACPI_READ) { /* Read the datum from the data_register */ status = acpi_ex_extract_from_field (obj_desc->index_field.data_obj, value, sizeof (acpi_integer)); } else { /* Write the datum to the data_register */ status = acpi_ex_insert_into_field (obj_desc->index_field.data_obj, value, sizeof (acpi_integer)); } break; default: ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p, Wrong object type - %s\n", obj_desc, acpi_ut_get_object_type_name (obj_desc))); status = AE_AML_INTERNAL; break; } if (ACPI_SUCCESS (status)) { if (read_write == ACPI_READ) { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Read %8.8X%8.8X, Width %d\n", ACPI_HIDWORD (*value), ACPI_LODWORD (*value), obj_desc->common_field.access_byte_width)); } else { ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, "Value Written %8.8X%8.8X, Width %d\n", ACPI_HIDWORD (*value), ACPI_LODWORD (*value), obj_desc->common_field.access_byte_width)); } } return_ACPI_STATUS (status); }
acpi_status acpi_ex_get_object_reference ( union acpi_operand_object *obj_desc, union acpi_operand_object **return_desc, struct acpi_walk_state *walk_state) { union acpi_operand_object *reference_obj; union acpi_operand_object *referenced_obj; ACPI_FUNCTION_TRACE_PTR ("ex_get_object_reference", obj_desc); *return_desc = NULL; switch (ACPI_GET_DESCRIPTOR_TYPE (obj_desc)) { case ACPI_DESC_TYPE_OPERAND: if (ACPI_GET_OBJECT_TYPE (obj_desc) != ACPI_TYPE_LOCAL_REFERENCE) { return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * Must be a reference to a Local or Arg */ switch (obj_desc->reference.opcode) { case AML_LOCAL_OP: case AML_ARG_OP: /* The referenced object is the pseudo-node for the local/arg */ referenced_obj = obj_desc->reference.object; break; default: ACPI_REPORT_ERROR (("Unknown Reference subtype in get ref %X\n", obj_desc->reference.opcode)); return_ACPI_STATUS (AE_AML_INTERNAL); } break; case ACPI_DESC_TYPE_NAMED: /* * A named reference that has already been resolved to a Node */ referenced_obj = obj_desc; break; default: ACPI_REPORT_ERROR (("Invalid descriptor type in get ref: %X\n", ACPI_GET_DESCRIPTOR_TYPE (obj_desc))); return_ACPI_STATUS (AE_TYPE); } /* Create a new reference object */ reference_obj = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE); if (!reference_obj) { return_ACPI_STATUS (AE_NO_MEMORY); } reference_obj->reference.opcode = AML_REF_OF_OP; reference_obj->reference.object = referenced_obj; *return_desc = reference_obj; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p Type [%s], returning Reference %p\n", obj_desc, acpi_ut_get_object_type_name (obj_desc), *return_desc)); return_ACPI_STATUS (AE_OK); }
static void acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index) { u32 i; ACPI_FUNCTION_TRACE_PTR(ex_do_debug_object, source_desc); /* Print line header as long as we are not in the middle of an object display */ if (!((level > 0) && index == 0)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[ACPI Debug] %*s", level, " ")); } /* Display index for package output only */ if (index > 0) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "(%.2u) ", index - 1)); } if (!source_desc) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Null Object]\n")); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s ", acpi_ut_get_object_type_name (source_desc))); if (!acpi_ut_valid_internal_object(source_desc)) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p, Invalid Internal Object!\n", source_desc)); return_VOID; } } else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%s: %p\n", acpi_ut_get_type_name(((struct acpi_namespace_node *)source_desc)-> type), source_desc)); return_VOID; } else { return_VOID; } /* source_desc is of type ACPI_DESC_TYPE_OPERAND */ switch (ACPI_GET_OBJECT_TYPE(source_desc)) { case ACPI_TYPE_INTEGER: /* Output correct integer width */ if (acpi_gbl_integer_byte_width == 4) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X\n", (u32) source_desc->integer. value)); } else { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "0x%8.8X%8.8X\n", ACPI_FORMAT_UINT64(source_desc-> integer. value))); } break; case ACPI_TYPE_BUFFER: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X]\n", (u32) source_desc->buffer.length)); ACPI_DUMP_BUFFER(source_desc->buffer.pointer, (source_desc->buffer.length < 256) ? source_desc->buffer.length : 256); break; case ACPI_TYPE_STRING: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[0x%.2X] \"%s\"\n", source_desc->string.length, source_desc->string.pointer)); break; case ACPI_TYPE_PACKAGE: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[Contains 0x%.2X Elements]\n", source_desc->package.count)); /* Output the entire contents of the package */ for (i = 0; i < source_desc->package.count; i++) { acpi_ex_do_debug_object(source_desc->package. elements[i], level + 4, i + 1); } break; case ACPI_TYPE_LOCAL_REFERENCE: if (source_desc->reference.opcode == AML_INDEX_OP) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s, 0x%X]\n", acpi_ps_get_opcode_name (source_desc->reference.opcode), source_desc->reference.offset)); } else { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "[%s]", acpi_ps_get_opcode_name (source_desc->reference.opcode))); } if (source_desc->reference.opcode == AML_LOAD_OP) { /* Load and load_table */ ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " Table OwnerId %p\n", source_desc->reference.object)); break; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " ")); /* Check for valid node first, then valid object */ if (source_desc->reference.node) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.node) != ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, " %p - Not a valid namespace node\n", source_desc->reference. node)); } else { ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "Node %p [%4.4s] ", source_desc->reference. node, (source_desc->reference. node)->name.ascii)); switch ((source_desc->reference.node)->type) { /* These types have no attached object */ case ACPI_TYPE_DEVICE: acpi_os_printf("Device\n"); break; case ACPI_TYPE_THERMAL: acpi_os_printf("Thermal Zone\n"); break; default: acpi_ex_do_debug_object((source_desc-> reference. node)->object, level + 4, 0); break; } } } else if (source_desc->reference.object) { if (ACPI_GET_DESCRIPTOR_TYPE (source_desc->reference.object) == ACPI_DESC_TYPE_NAMED) { acpi_ex_do_debug_object(((struct acpi_namespace_node *) source_desc->reference. object)->object, level + 4, 0); } else { acpi_ex_do_debug_object(source_desc->reference. object, level + 4, 0); } } break; default: ACPI_DEBUG_PRINT_RAW((ACPI_DB_DEBUG_OBJECT, "%p\n", source_desc)); break; } ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "\n")); return_VOID; }