acpi_get_table_with_size 这个函数会从acpi_gbl_root_table_list 中找每一个子表,匹配的原则就是看signature是否
匹配
acpi_get_table_with_size(char *signature,
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size)
{
u32 i;
u32 j;
acpi_status status;
/* Walk the root table list */
for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
i++) {
if (!ACPI_COMPARE_NAME
(&(acpi_gbl_root_table_list.tables[i].signature),
signature)) {
continue;
}
}
那这个acpi_gbl_root_table_list 是哪里将子表添加进去的呢?
void __init setup_arch(char **cmdline_p) 中会调用acpi_boot_table_init
void __init acpi_boot_table_init(void)
{
if (acpi_table_init() || acpi_fadt_sanity_check()) {
pr_err("Failed to init ACPI tables\n");
if (!param_acpi_force)
disable_acpi();
}
}
acpi_boot_table_init 又调用acpi_table_init
int __init acpi_table_init(void)
{
acpi_status status;
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
}
acpi_table_init调用acpi_initialize_tables
acpi_status __init
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
u32 initial_table_count, u8 allow_resize)
{
acpi_physical_address rsdp_address;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_initialize_tables);
/*
* Setup the Root Table Array and allocate the table array
* if requested
*/
if (!initial_table_array) {
status = acpi_allocate_root_table(initial_table_count);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else {
/* Root Table Array has been statically allocated by the host */
memset(initial_table_array, 0,
(acpi_size) initial_table_count *
sizeof(struct acpi_table_desc));
acpi_gbl_root_table_list.tables = initial_table_array;
acpi_gbl_root_table_list.max_table_count = initial_table_count;
acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
if (allow_resize) {
acpi_gbl_root_table_list.flags |=
ACPI_ROOT_ALLOW_RESIZE;
}
}
/* Get the address of the RSDP */
rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) {
return_ACPI_STATUS(AE_NOT_FOUND);
}
/*
* Get the root table (RSDT or XSDT) and extract all entries to the local
* Root Table Array. This array contains the information of the RSDT/XSDT
* in a common, more useable format.
*/
status = acpi_tb_parse_root_table(rsdp_address);
return_ACPI_STATUS(status);
}
在acpi_initialize_tables中首先判断initial_tables 是否已经申请了memory,在arm64 这边是已经申请了的,所有我们走
else的case。
initial_tables 清零,并对acpi_gbl_root_table_list 赋初值,acpi_gbl_root_table_list是一个全局变量
acpi_gbl_root_table_list.tables = initial_table_array;
acpi_gbl_root_table_list.max_table_count = initial_table_count;
acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
acpi_initialize_tables 中的acpi_os_get_root_pointer 会找到rsdp的地址。
然后acpi_tb_parse_root_table会将rsdp中的所有表格加到acpi_gbl_root_table_list中
acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
{
/* Initialize the root table array from the RSDT/XSDT */
for (i = 0; i < table_count; i++) {
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
address =
acpi_tb_get_root_table_entry(table_entry, table_entry_size);
/* Skip NULL entries in RSDT/XSDT */
if (!address) {
goto next_table;
}
status = acpi_tb_install_standard_table(address,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&table_index);
}
这个函数中的for 循环会变量rsdp表,调用acpi_tb_install_standard_table 来将子表添加到acpi_gbl_root_table_list中
acpi_tb_install_standard_table -> acpi_tb_install_table_with_override->acpi_tb_init_table_descriptor
在acpi_tb_init_table_descriptor 函数中将会对acpi_gbl_root_table_list 添加address/length/flags等
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
new_table_desc->address,
new_table_desc->flags,
new_table_desc->pointer);
匹配
acpi_get_table_with_size(char *signature,
u32 instance, struct acpi_table_header **out_table,
acpi_size *tbl_size)
{
u32 i;
u32 j;
acpi_status status;
/* Walk the root table list */
for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
i++) {
if (!ACPI_COMPARE_NAME
(&(acpi_gbl_root_table_list.tables[i].signature),
signature)) {
continue;
}
}
那这个acpi_gbl_root_table_list 是哪里将子表添加进去的呢?
void __init setup_arch(char **cmdline_p) 中会调用acpi_boot_table_init
void __init acpi_boot_table_init(void)
{
if (acpi_table_init() || acpi_fadt_sanity_check()) {
pr_err("Failed to init ACPI tables\n");
if (!param_acpi_force)
disable_acpi();
}
}
acpi_boot_table_init 又调用acpi_table_init
int __init acpi_table_init(void)
{
acpi_status status;
status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
}
acpi_table_init调用acpi_initialize_tables
acpi_status __init
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
u32 initial_table_count, u8 allow_resize)
{
acpi_physical_address rsdp_address;
acpi_status status;
ACPI_FUNCTION_TRACE(acpi_initialize_tables);
/*
* Setup the Root Table Array and allocate the table array
* if requested
*/
if (!initial_table_array) {
status = acpi_allocate_root_table(initial_table_count);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
} else {
/* Root Table Array has been statically allocated by the host */
memset(initial_table_array, 0,
(acpi_size) initial_table_count *
sizeof(struct acpi_table_desc));
acpi_gbl_root_table_list.tables = initial_table_array;
acpi_gbl_root_table_list.max_table_count = initial_table_count;
acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
if (allow_resize) {
acpi_gbl_root_table_list.flags |=
ACPI_ROOT_ALLOW_RESIZE;
}
}
/* Get the address of the RSDP */
rsdp_address = acpi_os_get_root_pointer();
if (!rsdp_address) {
return_ACPI_STATUS(AE_NOT_FOUND);
}
/*
* Get the root table (RSDT or XSDT) and extract all entries to the local
* Root Table Array. This array contains the information of the RSDT/XSDT
* in a common, more useable format.
*/
status = acpi_tb_parse_root_table(rsdp_address);
return_ACPI_STATUS(status);
}
在acpi_initialize_tables中首先判断initial_tables 是否已经申请了memory,在arm64 这边是已经申请了的,所有我们走
else的case。
initial_tables 清零,并对acpi_gbl_root_table_list 赋初值,acpi_gbl_root_table_list是一个全局变量
acpi_gbl_root_table_list.tables = initial_table_array;
acpi_gbl_root_table_list.max_table_count = initial_table_count;
acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
acpi_initialize_tables 中的acpi_os_get_root_pointer 会找到rsdp的地址。
然后acpi_tb_parse_root_table会将rsdp中的所有表格加到acpi_gbl_root_table_list中
acpi_status __init acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
{
/* Initialize the root table array from the RSDT/XSDT */
for (i = 0; i < table_count; i++) {
/* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
address =
acpi_tb_get_root_table_entry(table_entry, table_entry_size);
/* Skip NULL entries in RSDT/XSDT */
if (!address) {
goto next_table;
}
status = acpi_tb_install_standard_table(address,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&table_index);
}
这个函数中的for 循环会变量rsdp表,调用acpi_tb_install_standard_table 来将子表添加到acpi_gbl_root_table_list中
acpi_tb_install_standard_table -> acpi_tb_install_table_with_override->acpi_tb_init_table_descriptor
在acpi_tb_init_table_descriptor 函数中将会对acpi_gbl_root_table_list 添加address/length/flags等
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
new_table_desc->address,
new_table_desc->flags,
new_table_desc->pointer);