在acpi_tb_parse_root_table 函数中会调用 acpi_tb_parse_fadt parse FADT table
当然前提是acpi_gbl_root_table_list 中有fdat table,判断的额方法如下:
if (ACPI_SUCCESS(status) &&
ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
tables[table_index].signature,
ACPI_SIG_FADT)) {
acpi_gbl_fadt_index = table_index;
acpi_tb_parse_fadt();
于此同时acpi_gbl_fadt_index 表示fadt在这个acpi_tb_parse_root_table 数组中的index.
可见会比较signature 是否相等来作为是否parse fadt的条件
void acpi_tb_parse_fadt(void)
{
u32 length;
struct acpi_table_header *table;
/*
* The FADT has multiple versions with different lengths,
* and it contains pointers to both the DSDT and FACS tables.
*
* Get a local copy of the FADT and convert it to a common format
* Map entire FADT, assumed to be smaller than one page.
*/
length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
table =
acpi_os_map_memory(acpi_gbl_root_table_list.
tables[acpi_gbl_fadt_index].address, length);
if (!table) {
return;
}
/*
* Validate the FADT checksum before we copy the table. Ignore
* checksum error as we want to try to get the DSDT and FACS.
*/
(void)acpi_tb_verify_checksum(table, length);
/* Create a local copy of the FADT in common ACPI 2.0+ format */
acpi_tb_create_local_fadt(table, length);
/* All done with the real FADT, unmap it */
acpi_os_unmap_memory(table, length);
/* Obtain the DSDT and FACS tables via their addresses within the FADT */
acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT.
Xdsdt,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE, &acpi_gbl_dsdt_index);
/* If Hardware Reduced flag is set, there is no FACS */
if (!acpi_gbl_reduced_hardware) {
if (acpi_gbl_FADT.facs) {
acpi_tb_install_standard_table((acpi_physical_address)
acpi_gbl_FADT.facs,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&acpi_gbl_facs_index);
}
if (acpi_gbl_FADT.Xfacs) {
acpi_tb_install_standard_table((acpi_physical_address)
acpi_gbl_FADT.Xfacs,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&acpi_gbl_xfacs_index);
}
}
}
acpi_tb_parse_fadt 中首先的到fadt的长度
length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
得到memory
table =
acpi_os_map_memory(acpi_gbl_root_table_list.
tables[acpi_gbl_fadt_index].address, length);
调用
(void)acpi_tb_verify_checksum(table, length);
来计算fadt的checksum
acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
{
u8 checksum;
/*
* FACS/S3PT:
* They are the odd tables, have no standard ACPI header and no checksum
*/
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
return (AE_OK);
}
/* Compute the checksum on the table */
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
/* Checksum ok? (should be zero) */
if (checksum) {
ACPI_BIOS_WARNING((AE_INFO,
"Incorrect checksum in table [%4.4s] - 0x%2.2X, "
"should be 0x%2.2X",
table->signature, table->checksum,
(u8)(table->checksum - checksum)));
#if (ACPI_CHECKSUM_ABORT)
return (AE_BAD_CHECKSUM);
#endif
}
return (AE_OK);
}
acpi_tb_verify_checksum 的就是计算checksum 然后看table->checksum - checksum的结果是否为0
也就是说无论checksum是否ok 都会打印“Incorrect checksum in table”
最后会调用acpi_tb_install_standard_table -> acpi_tb_install_table_with_override
来将fadt table安装到acpi_gbl_root_table_list中
void
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
u8 override, u32 *table_index)
{
u32 i;
acpi_status status;
status = acpi_tb_get_next_table_descriptor(&i, NULL);
if (ACPI_FAILURE(status)) {
return;
}
/*
* ACPI Table Override:
*
* Before we install the table, let the host OS override it with a new
* one if desired. Any table within the RSDT/XSDT can be replaced,
* including the DSDT which is pointed to by the FADT.
*/
if (override) {
acpi_tb_override_table(new_table_desc);
}
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_tb_print_table_header(new_table_desc->address,
new_table_desc->pointer);
/* This synchronizes acpi_gbl_dsdt_index */
*table_index = i;
/* Set the global integer width (based upon revision of the DSDT) */
if (i == acpi_gbl_dsdt_index) {
acpi_ut_set_integer_width(new_table_desc->pointer->revision);
}
}
acpi_tb_install_table_with_override 中首先调用acpi_tb_get_next_table_descriptor 获得acpi_gbl_root_table_list 中的位置
最后调用acpi_tb_init_table_descriptor 更新fadt到acpi_gbl_root_table_list
当然前提是acpi_gbl_root_table_list 中有fdat table,判断的额方法如下:
if (ACPI_SUCCESS(status) &&
ACPI_COMPARE_NAME(&acpi_gbl_root_table_list.
tables[table_index].signature,
ACPI_SIG_FADT)) {
acpi_gbl_fadt_index = table_index;
acpi_tb_parse_fadt();
于此同时acpi_gbl_fadt_index 表示fadt在这个acpi_tb_parse_root_table 数组中的index.
可见会比较signature 是否相等来作为是否parse fadt的条件
void acpi_tb_parse_fadt(void)
{
u32 length;
struct acpi_table_header *table;
/*
* The FADT has multiple versions with different lengths,
* and it contains pointers to both the DSDT and FACS tables.
*
* Get a local copy of the FADT and convert it to a common format
* Map entire FADT, assumed to be smaller than one page.
*/
length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
table =
acpi_os_map_memory(acpi_gbl_root_table_list.
tables[acpi_gbl_fadt_index].address, length);
if (!table) {
return;
}
/*
* Validate the FADT checksum before we copy the table. Ignore
* checksum error as we want to try to get the DSDT and FACS.
*/
(void)acpi_tb_verify_checksum(table, length);
/* Create a local copy of the FADT in common ACPI 2.0+ format */
acpi_tb_create_local_fadt(table, length);
/* All done with the real FADT, unmap it */
acpi_os_unmap_memory(table, length);
/* Obtain the DSDT and FACS tables via their addresses within the FADT */
acpi_tb_install_standard_table((acpi_physical_address)acpi_gbl_FADT.
Xdsdt,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE, &acpi_gbl_dsdt_index);
/* If Hardware Reduced flag is set, there is no FACS */
if (!acpi_gbl_reduced_hardware) {
if (acpi_gbl_FADT.facs) {
acpi_tb_install_standard_table((acpi_physical_address)
acpi_gbl_FADT.facs,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&acpi_gbl_facs_index);
}
if (acpi_gbl_FADT.Xfacs) {
acpi_tb_install_standard_table((acpi_physical_address)
acpi_gbl_FADT.Xfacs,
ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
FALSE, TRUE,
&acpi_gbl_xfacs_index);
}
}
}
acpi_tb_parse_fadt 中首先的到fadt的长度
length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length;
得到memory
table =
acpi_os_map_memory(acpi_gbl_root_table_list.
tables[acpi_gbl_fadt_index].address, length);
调用
(void)acpi_tb_verify_checksum(table, length);
来计算fadt的checksum
acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
{
u8 checksum;
/*
* FACS/S3PT:
* They are the odd tables, have no standard ACPI header and no checksum
*/
if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
return (AE_OK);
}
/* Compute the checksum on the table */
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
/* Checksum ok? (should be zero) */
if (checksum) {
ACPI_BIOS_WARNING((AE_INFO,
"Incorrect checksum in table [%4.4s] - 0x%2.2X, "
"should be 0x%2.2X",
table->signature, table->checksum,
(u8)(table->checksum - checksum)));
#if (ACPI_CHECKSUM_ABORT)
return (AE_BAD_CHECKSUM);
#endif
}
return (AE_OK);
}
acpi_tb_verify_checksum 的就是计算checksum 然后看table->checksum - checksum的结果是否为0
也就是说无论checksum是否ok 都会打印“Incorrect checksum in table”
最后会调用acpi_tb_install_standard_table -> acpi_tb_install_table_with_override
来将fadt table安装到acpi_gbl_root_table_list中
void
acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
u8 override, u32 *table_index)
{
u32 i;
acpi_status status;
status = acpi_tb_get_next_table_descriptor(&i, NULL);
if (ACPI_FAILURE(status)) {
return;
}
/*
* ACPI Table Override:
*
* Before we install the table, let the host OS override it with a new
* one if desired. Any table within the RSDT/XSDT can be replaced,
* including the DSDT which is pointed to by the FADT.
*/
if (override) {
acpi_tb_override_table(new_table_desc);
}
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_tb_print_table_header(new_table_desc->address,
new_table_desc->pointer);
/* This synchronizes acpi_gbl_dsdt_index */
*table_index = i;
/* Set the global integer width (based upon revision of the DSDT) */
if (i == acpi_gbl_dsdt_index) {
acpi_ut_set_integer_width(new_table_desc->pointer->revision);
}
}
acpi_tb_install_table_with_override 中首先调用acpi_tb_get_next_table_descriptor 获得acpi_gbl_root_table_list 中的位置
最后调用acpi_tb_init_table_descriptor 更新fadt到acpi_gbl_root_table_list