static acpi_status osl_list_bios_tables(void) { struct acpi_table_header *mapped_table = NULL; u8 *table_data; u8 number_of_tables; u8 item_size; acpi_physical_address table_address = 0; acpi_status status = AE_OK; u32 i; if (osl_can_use_xsdt()) { item_size = sizeof(u64); table_data = ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header); number_of_tables = (u8)((gbl_xsdt->header.length - sizeof(struct acpi_table_header)) / item_size); } else { /* Use RSDT if XSDT is not available */ item_size = sizeof(u32); table_data = ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header); number_of_tables = (u8)((gbl_rsdt->header.length - sizeof(struct acpi_table_header)) / item_size); } /* Search RSDT/XSDT for the requested table */ for (i = 0; i < number_of_tables; ++i, table_data += item_size) { if (osl_can_use_xsdt()) { table_address = (acpi_physical_address) (*ACPI_CAST64(table_data)); } else { table_address = (acpi_physical_address) (*ACPI_CAST32(table_data)); } /* Skip NULL entries in RSDT/XSDT */ if (!table_address) { continue; } status = osl_map_table(table_address, NULL, &mapped_table); if (ACPI_FAILURE(status)) { return (status); } osl_add_table_to_list(mapped_table->signature, 0); osl_unmap_table(mapped_table); } return (AE_OK); }
acpi_status acpi_os_get_table_by_address(acpi_physical_address address, struct acpi_table_header ** table) { u32 table_length; struct acpi_table_header *mapped_table; struct acpi_table_header *local_table = NULL; acpi_status status = AE_OK; /* Get main ACPI tables from memory on first invocation of this function */ status = osl_table_initialize(); if (ACPI_FAILURE(status)) { return (status); } /* Map the table and validate it */ status = osl_map_table(address, NULL, &mapped_table); if (ACPI_FAILURE(status)) { return (status); } /* Copy table to local buffer and return it */ table_length = ap_get_table_length(mapped_table); if (table_length == 0) { status = AE_BAD_HEADER; goto exit; } local_table = calloc(1, table_length); if (!local_table) { status = AE_NO_MEMORY; goto exit; } memcpy(local_table, mapped_table, table_length); exit: osl_unmap_table(mapped_table); *table = local_table; return (status); }
static acpi_status osl_get_bios_table(char *signature, u32 instance, struct acpi_table_header **table, acpi_physical_address * address) { struct acpi_table_header *local_table = NULL; struct acpi_table_header *mapped_table = NULL; u8 *table_data; u8 number_of_tables; u8 item_size; u32 current_instance = 0; acpi_physical_address table_address = 0; u32 table_length = 0; acpi_status status = AE_OK; u32 i; /* Handle special tables whose addresses are not in RSDT/XSDT */ if (ACPI_COMPARE_NAME(signature, ACPI_RSDP_NAME) || ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT) || ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { if (instance > 0) { return (AE_LIMIT); } /* * Get the appropriate address, either 32-bit or 64-bit. Be very * careful about the FADT length and validate table addresses. * Note: The 64-bit addresses have priority. */ if (ACPI_COMPARE_NAME(signature, ACPI_SIG_DSDT)) { if ((gbl_fadt->header.length >= MIN_FADT_FOR_XDSDT) && gbl_fadt->Xdsdt) { table_address = (acpi_physical_address) gbl_fadt->Xdsdt; } else if ((gbl_fadt->header.length >= MIN_FADT_FOR_DSDT) && gbl_fadt->dsdt) { table_address = (acpi_physical_address) gbl_fadt->dsdt; } } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_FACS)) { if ((gbl_fadt->header.length >= MIN_FADT_FOR_XFACS) && gbl_fadt->Xfacs) { table_address = (acpi_physical_address) gbl_fadt->Xfacs; } else if ((gbl_fadt->header.length >= MIN_FADT_FOR_FACS) && gbl_fadt->facs) { table_address = (acpi_physical_address) gbl_fadt->facs; } } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_XSDT)) { if (!gbl_revision) { return (AE_BAD_SIGNATURE); } table_address = (acpi_physical_address) gbl_rsdp. xsdt_physical_address; } else if (ACPI_COMPARE_NAME(signature, ACPI_SIG_RSDT)) { table_address = (acpi_physical_address) gbl_rsdp. rsdt_physical_address; } else { table_address = (acpi_physical_address) gbl_rsdp_address; signature = ACPI_SIG_RSDP; } /* Now we can get the requested special table */ status = osl_map_table(table_address, signature, &mapped_table); if (ACPI_FAILURE(status)) { return (status); } table_length = ap_get_table_length(mapped_table); } else { /* Case for a normal ACPI table */ if (osl_can_use_xsdt()) { item_size = sizeof(u64); table_data = ACPI_CAST8(gbl_xsdt) + sizeof(struct acpi_table_header); number_of_tables = (u8)((gbl_xsdt->header.length - sizeof(struct acpi_table_header)) / item_size); } else { /* Use RSDT if XSDT is not available */ item_size = sizeof(u32); table_data = ACPI_CAST8(gbl_rsdt) + sizeof(struct acpi_table_header); number_of_tables = (u8)((gbl_rsdt->header.length - sizeof(struct acpi_table_header)) / item_size); } /* Search RSDT/XSDT for the requested table */ for (i = 0; i < number_of_tables; ++i, table_data += item_size) { if (osl_can_use_xsdt()) { table_address = (acpi_physical_address) (*ACPI_CAST64 (table_data)); } else { table_address = (acpi_physical_address) (*ACPI_CAST32 (table_data)); } /* Skip NULL entries in RSDT/XSDT */ if (!table_address) { continue; } status = osl_map_table(table_address, NULL, &mapped_table); if (ACPI_FAILURE(status)) { return (status); } table_length = mapped_table->length; /* Does this table match the requested signature? */ if (!ACPI_COMPARE_NAME (mapped_table->signature, signature)) { osl_unmap_table(mapped_table); mapped_table = NULL; continue; } /* Match table instance (for SSDT/UEFI tables) */ if (current_instance != instance) { osl_unmap_table(mapped_table); mapped_table = NULL; current_instance++; continue; } break; } } if (!mapped_table) { return (AE_LIMIT); } if (table_length == 0) { status = AE_BAD_HEADER; goto exit; } /* Copy table to local buffer and return it */ local_table = calloc(1, table_length); if (!local_table) { status = AE_NO_MEMORY; goto exit; } ACPI_MEMCPY(local_table, mapped_table, table_length); *address = table_address; *table = local_table; exit: osl_unmap_table(mapped_table); return (status); }