acpi_status acpi_tb_allocate_owner_id(u32 table_index) { acpi_status status = AE_BAD_PARAMETER; ACPI_FUNCTION_TRACE(tb_allocate_owner_id); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); if (table_index < acpi_gbl_root_table_list.current_table_count) { status = acpi_ut_allocate_owner_id (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); } (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); }
acpi_status acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); if (!method_node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Prevent wraparound of thread count */ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { ACPI_ERROR((AE_INFO, "Method reached maximum reentrancy limit (255)")); return_ACPI_STATUS(AE_AML_METHOD_LIMIT); } /* * If this method is serialized, we need to acquire the method mutex. */ if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { /* * Create a mutex for the method if it is defined to be Serialized * and a mutex has not already been created. We defer the mutex creation * until a method is actually executed, to minimize the object count */ if (!obj_desc->method.mutex) { status = acpi_ds_create_method_mutex(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* * The current_sync_level (per-thread) must be less than or equal to * the sync level of the method. This mechanism provides some * deadlock prevention * * Top-level method invocation has no walk state at this point */ if (walk_state && (walk_state->thread->current_sync_level > obj_desc->method.mutex->mutex.sync_level)) { ACPI_ERROR((AE_INFO, "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)", acpi_ut_get_node_name(method_node), walk_state->thread->current_sync_level)); return_ACPI_STATUS(AE_AML_MUTEX_ORDER); } /* * Obtain the method mutex if necessary. Do not acquire mutex for a * recursive call. */ if (acpi_os_get_thread_id() != obj_desc->method.mutex->mutex.owner_thread_id) { /* * Acquire the method mutex. This releases the interpreter if we * block (and reacquires it before it returns) */ status = acpi_ex_system_wait_mutex(obj_desc->method.mutex-> mutex.os_mutex, ACPI_WAIT_FOREVER); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Update the mutex and walk info and save the original sync_level */ obj_desc->method.mutex->mutex.owner_thread_id = acpi_os_get_thread_id(); if (walk_state) { obj_desc->method.mutex->mutex. original_sync_level = walk_state->thread->current_sync_level; walk_state->thread->current_sync_level = obj_desc->method.sync_level; } else { obj_desc->method.mutex->mutex. original_sync_level = obj_desc->method.mutex->mutex.sync_level; } } /* Always increase acquisition depth */ obj_desc->method.mutex->mutex.acquisition_depth++; } /* * Allocate an Owner ID for this method, only if this is the first thread * to begin concurrent execution. We only need one owner_id, even if the * method is invoked recursively. */ if (!obj_desc->method.owner_id) { status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { goto cleanup; } } /* * Increment the method parse tree thread count since it has been * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; return_ACPI_STATUS(status); cleanup: /* On error, must release the method mutex (if present) */ if (obj_desc->method.mutex) { acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex); } return_ACPI_STATUS(status); }
acpi_status acpi_tb_init_table_descriptor ( acpi_table_type table_type, acpi_table_desc *table_info) { acpi_table_desc *list_head; acpi_table_desc *table_desc; FUNCTION_TRACE_U32 ("Tb_init_table_descriptor", table_type); /* * Install the table into the global data structure */ list_head = &acpi_gbl_acpi_tables[table_type]; table_desc = list_head; /* * Two major types of tables: 1) Only one instance is allowed. This * includes most ACPI tables such as the DSDT. 2) Multiple instances of * the table are allowed. This includes SSDT and PSDTs. */ if (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed * at this location, so return an error. */ if (list_head->pointer) { return_ACPI_STATUS (AE_EXIST); } table_desc->count = 1; } else { /* * Multiple tables allowed for this table type, we must link * the new table in to the list of tables of this type. */ if (list_head->pointer) { table_desc = ACPI_MEM_CALLOCATE (sizeof (acpi_table_desc)); if (!table_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } list_head->count++; /* Update the original previous */ list_head->prev->next = table_desc; /* Update new entry */ table_desc->prev = list_head->prev; table_desc->next = list_head; /* Update list head */ list_head->prev = table_desc; } else { table_desc->count = 1; } } /* Common initialization of the table descriptor */ table_desc->pointer = table_info->pointer; table_desc->base_pointer = table_info->base_pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; table_desc->aml_start = (u8 *) (table_desc->pointer + 1), table_desc->aml_length = (u32) (table_desc->length - (u32) sizeof (acpi_table_header)); table_desc->table_id = acpi_ut_allocate_owner_id (OWNER_TYPE_TABLE); table_desc->loaded_into_namespace = FALSE; /* * Set the appropriate global pointer (if there is one) to point to the * newly installed table */ if (acpi_gbl_acpi_table_data[table_type].global_ptr) { *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer; } /* Return Data */ table_info->table_id = table_desc->table_id; table_info->installed_desc = table_desc; return_ACPI_STATUS (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_ds_parse_method * * PARAMETERS: Node - Method node * * RETURN: Status * * DESCRIPTION: Parse the AML that is associated with the method. * * MUTEX: Assumes parser is locked * ******************************************************************************/ acpi_status acpi_ds_parse_method(struct acpi_namespace_node *node) { acpi_status status; union acpi_operand_object *obj_desc; union acpi_parse_object *op; struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE_PTR("ds_parse_method", node); /* Parameter Validation */ if (!node) { return_ACPI_STATUS(AE_NULL_ENTRY); } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n", acpi_ut_get_node_name(node), node)); /* Extract the method object from the method Node */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return_ACPI_STATUS(AE_NULL_OBJECT); } /* Create a mutex for the method if there is a concurrency limit */ if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) && (!obj_desc->method.semaphore)) { status = acpi_os_create_semaphore(obj_desc->method.concurrency, obj_desc->method.concurrency, &obj_desc->method.semaphore); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* * Allocate a new parser op to be the root of the parsed * method tree */ op = acpi_ps_alloc_op(AML_METHOD_OP); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Init new op with the method name and pointer back to the Node */ acpi_ps_set_name(op, node->name.integer); op->common.node = node; /* * Get a new owner_id for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { goto cleanup; } /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk(walk_state, op, node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE(status)) { acpi_ds_delete_walk_state(walk_state); goto cleanup2; } /* * Parse the method, first pass * * The first pass load is where newly declared named objects are added into * the namespace. Actual evaluation of the named objects (what would be * called a "second pass") happens during the actual execution of the * method so that operands to the named objects can take on dynamic * run-time values. */ status = acpi_ps_parse_aml(walk_state); if (ACPI_FAILURE(status)) { goto cleanup2; } ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n", acpi_ut_get_node_name(node), node, op)); /* * Delete the parse tree. We simply re-parse the method for every * execution since there isn't much overhead (compared to keeping lots * of parse trees around) */ acpi_ns_delete_namespace_subtree(node); acpi_ns_delete_namespace_by_owner(obj_desc->method.owner_id); cleanup2: acpi_ut_release_owner_id(&obj_desc->method.owner_id); cleanup: acpi_ps_delete_parse_tree(op); return_ACPI_STATUS(status); }
acpi_status acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, union acpi_operand_object *obj_desc, struct acpi_namespace_node *calling_method_node) { acpi_status status = AE_OK; ACPI_FUNCTION_TRACE_PTR("ds_begin_method_execution", method_node); if (!method_node) { return_ACPI_STATUS(AE_NULL_ENTRY); } /* Prevent wraparound of thread count */ if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { ACPI_REPORT_ERROR(("Method reached maximum reentrancy limit (255)\n")); return_ACPI_STATUS(AE_AML_METHOD_LIMIT); } /* * If there is a concurrency limit on this method, we need to * obtain a unit from the method semaphore. */ if (obj_desc->method.semaphore) { /* * Allow recursive method calls, up to the reentrancy/concurrency * limit imposed by the SERIALIZED rule and the sync_level method * parameter. * * The point of this code is to avoid permanently blocking a * thread that is making recursive method calls. */ if (method_node == calling_method_node) { if (obj_desc->method.thread_count >= obj_desc->method.concurrency) { return_ACPI_STATUS(AE_AML_METHOD_LIMIT); } } /* * Get a unit from the method semaphore. This releases the * interpreter if we block */ status = acpi_ex_system_wait_semaphore(obj_desc->method.semaphore, ACPI_WAIT_FOREVER); } /* * Allocate an Owner ID for this method, only if this is the first thread * to begin concurrent execution. We only need one owner_id, even if the * method is invoked recursively. */ if (!obj_desc->method.owner_id) { status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* * Increment the method parse tree thread count since it has been * reentered one more time (even if it is the same thread) */ obj_desc->method.thread_count++; return_ACPI_STATUS(status); }
acpi_status acpi_ds_call_control_method ( struct acpi_thread_state *thread, struct acpi_walk_state *this_walk_state, union acpi_parse_object *op) { acpi_status status; struct acpi_namespace_node *method_node; union acpi_operand_object *obj_desc; struct acpi_walk_state *next_walk_state; u32 i; ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n", this_walk_state->prev_op, this_walk_state)); /* * Get the namespace entry for the control method we are about to call */ method_node = this_walk_state->method_call_node; if (!method_node) { return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (method_node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (method_node, obj_desc, this_walk_state->method_node); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) { /* 1) Parse: Create a new walk state for the preempting walk */ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, op, obj_desc, NULL); if (!next_walk_state) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); if (!op) { status = AE_NO_MEMORY; goto cleanup; } status = acpi_ds_init_aml_walk (next_walk_state, op, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, NULL, 1); if (ACPI_FAILURE (status)) { acpi_ds_delete_walk_state (next_walk_state); goto cleanup; } /* Begin AML parse */ status = acpi_ps_parse_aml (next_walk_state); acpi_ps_delete_parse_tree (op); } /* 2) Execute: Create a new state for the preempting walk */ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, NULL, obj_desc, thread); if (!next_walk_state) { status = AE_NO_MEMORY; goto cleanup; } /* * The resolved arguments were put on the previous walk state's operand * stack. Operands on the previous walk state stack always * start at index 0. * Null terminate the list of arguments */ this_walk_state->operands [this_walk_state->num_operands] = NULL; status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node, obj_desc->method.aml_start, obj_desc->method.aml_length, &this_walk_state->operands[0], NULL, 3); if (ACPI_FAILURE (status)) { goto cleanup; } /* * Delete the operands on the previous walkstate operand stack * (they were copied to new objects) */ for (i = 0; i < obj_desc->method.param_count; i++) { acpi_ut_remove_reference (this_walk_state->operands [i]); this_walk_state->operands [i] = NULL; } /* Clear the operand stack */ this_walk_state->num_operands = 0; ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Starting nested execution, newstate=%p\n", next_walk_state)); if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { status = obj_desc->method.implementation (next_walk_state); return_ACPI_STATUS (status); } return_ACPI_STATUS (AE_OK); /* On error, we must delete the new walk state */ cleanup: if (next_walk_state->method_desc) { /* Decrement the thread count on the method parse tree */ next_walk_state->method_desc->method.thread_count--; } (void) acpi_ds_terminate_control_method (next_walk_state); acpi_ds_delete_walk_state (next_walk_state); return_ACPI_STATUS (status); }
/**ltl * 功能:将ACPI表的描述符信息插入到全局列表中 * 参数: * 返回值: * 说明:表类型table_type分别为:0(RSDP)、6 (XSDT)、2 (FADT)、5 (SSDT)、5 (SSDT)、3 (FACS)、1 (DSDT) */ acpi_status acpi_tb_init_table_descriptor(acpi_table_type table_type, struct acpi_table_desc *table_info) { struct acpi_table_list *list_head; struct acpi_table_desc *table_desc; acpi_status status; ACPI_FUNCTION_TRACE_U32(tb_init_table_descriptor, table_type); /* Allocate a descriptor for this table */ /* 分配ACPI表描述符信息 */ table_desc = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_table_desc)); if (!table_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Get a new owner ID for the table */ /* 为ACPI表描述符分配ID */ status = acpi_ut_allocate_owner_id(&table_desc->owner_id); if (ACPI_FAILURE(status)) { goto error_exit1; } /* Install the table into the global data structure */ /* 全局列表 */ list_head = &acpi_gbl_table_lists[table_type]; /* * Two major types of tables: 1) Only one instance is allowed. This * includes most ACPI tables such as the DSDT. 2) Multiple instances of * the table are allowed. This includes SSDT and PSDTs. */ /* 如果此ACPI表在系统中只能是唯一一个 */ if (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed * at this location, so return an error. */ if (list_head->next) { /* 表示此表已经存在,退出 */ status = AE_ALREADY_EXISTS; goto error_exit2; } /* 将ACPI表描述符对象插入到全局列表中 */ table_desc->next = list_head->next; list_head->next = table_desc; if (table_desc->next) { table_desc->next->prev = table_desc; } list_head->count++; } else { /* * Link the new table in to the list of tables of this type. * Insert at the end of the list, order IS IMPORTANT. * * table_desc->Prev & Next are already NULL from calloc() */ /* 在系统中引出现多张相同的ACPI表,把它们以链表的形式链接 */ list_head->count++; if (!list_head->next) { list_head->next = table_desc; } else { table_desc->next = list_head->next; while (table_desc->next->next) { table_desc->next = table_desc->next->next; } table_desc->next->next = table_desc; table_desc->prev = table_desc->next; table_desc->next = NULL; } } /* Finish initialization of the table descriptor */ table_desc->loaded_into_namespace = FALSE; table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; table_desc->aml_start = (u8 *) (table_desc->pointer + 1), table_desc->aml_length = (u32) (table_desc->length - (u32) sizeof(struct acpi_table_header)); /* * Set the appropriate global pointer (if there is one) to point to the * newly installed table */ /* 将ACPI表的起始地址保存到global_ptr中。在这语句是对全局变量:acpi_gbl_FADT、acpi_gbl_FACS、acpi_gbl_DSDT * 进行赋值 */ if (acpi_gbl_table_data[table_type].global_ptr) { *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer; } /* Return Data */ table_info->owner_id = table_desc->owner_id; table_info->installed_desc = table_desc; return_ACPI_STATUS(AE_OK); /* Error exit with cleanup */ error_exit2: acpi_ut_release_owner_id(&table_desc->owner_id); error_exit1: ACPI_FREE(table_desc); return_ACPI_STATUS(status); }
acpi_status acpi_psx_execute ( struct acpi_parameter_info *info) { acpi_status status; union acpi_operand_object *obj_desc; u32 i; union acpi_parse_object *op; struct acpi_walk_state *walk_state; ACPI_FUNCTION_TRACE ("psx_execute"); /* Validate the Node and get the attached object */ if (!info || !info->node) { return_ACPI_STATUS (AE_NULL_ENTRY); } obj_desc = acpi_ns_get_attached_object (info->node); if (!obj_desc) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Init for new method, wait on concurrency semaphore */ status = acpi_ds_begin_method_execution (info->node, obj_desc, NULL); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { /* * The caller "owns" the parameters, so give each one an extra * reference */ for (i = 0; info->parameters[i]; i++) { acpi_ut_add_reference (info->parameters[i]); } } /* * 1) Perform the first pass parse of the method to enter any * named objects that it creates into the namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Parse **** Entry=%p obj=%p\n", info->node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); if (!op) { status = AE_NO_MEMORY; goto cleanup1; } /* * Get a new owner_id for objects created by this method. Namespace * objects (such as Operation Regions) can be created during the * first pass parse. */ obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD); /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, info->node, obj_desc->method.aml_start, obj_desc->method.aml_length, NULL, 1); if (ACPI_FAILURE (status)) { goto cleanup3; } /* Parse the AML */ status = acpi_ps_parse_aml (walk_state); acpi_ps_delete_parse_tree (op); if (ACPI_FAILURE (status)) { goto cleanup1; /* Walk state is already deleted */ } /* * 2) Execute the method. Performs second pass parse simultaneously */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Begin Method Execution **** Entry=%p obj=%p\n", info->node, obj_desc)); /* Create and init a Root Node */ op = acpi_ps_create_scope_op (); if (!op) { status = AE_NO_MEMORY; goto cleanup1; } /* Init new op with the method name and pointer back to the NS node */ acpi_ps_set_name (op, info->node->name.integer); op->common.node = info->node; /* Create and initialize a new walk state */ walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL); if (!walk_state) { status = AE_NO_MEMORY; goto cleanup2; } status = acpi_ds_init_aml_walk (walk_state, op, info->node, obj_desc->method.aml_start, obj_desc->method.aml_length, info, 3); if (ACPI_FAILURE (status)) { goto cleanup3; } /* The walk of the parse tree is where we actually execute the method */ status = acpi_ps_parse_aml (walk_state); goto cleanup2; /* Walk state already deleted */ cleanup3: acpi_ds_delete_walk_state (walk_state); cleanup2: acpi_ps_delete_parse_tree (op); cleanup1: if ((info->parameter_type == ACPI_PARAM_ARGS) && (info->parameters)) { /* Take away the extra reference that we gave the parameters above */ for (i = 0; info->parameters[i]; i++) { /* Ignore errors, just do them all */ (void) acpi_ut_update_object_reference ( info->parameters[i], REF_DECREMENT); } } if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* * If the method has returned an object, signal this to the caller with * a control exception code */ if (info->return_object) { ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned obj_desc=%p\n", info->return_object)); ACPI_DUMP_STACK_ENTRY (info->return_object); status = AE_CTRL_RETURN_VALUE; } return_ACPI_STATUS (status); }
acpi_status acpi_tb_init_table_descriptor ( acpi_table_type table_type, struct acpi_table_desc *table_info) { struct acpi_table_list *list_head; struct acpi_table_desc *table_desc; ACPI_FUNCTION_TRACE_U32 ("tb_init_table_descriptor", table_type); /* Allocate a descriptor for this table */ table_desc = ACPI_MEM_CALLOCATE (sizeof (struct acpi_table_desc)); if (!table_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } /* * Install the table into the global data structure */ list_head = &acpi_gbl_table_lists[table_type]; /* * Two major types of tables: 1) Only one instance is allowed. This * includes most ACPI tables such as the DSDT. 2) Multiple instances of * the table are allowed. This includes SSDT and PSDTs. */ if (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags)) { /* * Only one table allowed, and a table has alread been installed * at this location, so return an error. */ if (list_head->next) { ACPI_MEM_FREE (table_desc); return_ACPI_STATUS (AE_ALREADY_EXISTS); } table_desc->next = list_head->next; list_head->next = table_desc; if (table_desc->next) { table_desc->next->prev = table_desc; } list_head->count++; } else { /* * Link the new table in to the list of tables of this type. * Insert at the end of the list, order IS IMPORTANT. * * table_desc->Prev & Next are already NULL from calloc() */ list_head->count++; if (!list_head->next) { list_head->next = table_desc; } else { table_desc->next = list_head->next; while (table_desc->next->next) { table_desc->next = table_desc->next->next; } table_desc->next->next = table_desc; table_desc->prev = table_desc->next; table_desc->next = NULL; } } /* Finish initialization of the table descriptor */ table_desc->type = (u8) table_type; table_desc->pointer = table_info->pointer; table_desc->length = table_info->length; table_desc->allocation = table_info->allocation; table_desc->aml_start = (u8 *) (table_desc->pointer + 1), table_desc->aml_length = (u32) (table_desc->length - (u32) sizeof (struct acpi_table_header)); table_desc->table_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_TABLE); table_desc->loaded_into_namespace = FALSE; /* * Set the appropriate global pointer (if there is one) to point to the * newly installed table */ if (acpi_gbl_table_data[table_type].global_ptr) { *(acpi_gbl_table_data[table_type].global_ptr) = table_info->pointer; } /* Return Data */ table_info->table_id = table_desc->table_id; table_info->installed_desc = table_desc; return_ACPI_STATUS (AE_OK); }