acpi_status acpi_tb_get_table(struct acpi_pointer *address, struct acpi_table_desc *table_info) { acpi_status status; struct acpi_table_header header; ACPI_FUNCTION_TRACE(tb_get_table); /* Get the header in order to get signature and table size */ status = acpi_tb_get_table_header(address, &header); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Get the entire table */ status = acpi_tb_get_table_body(address, &header, table_info); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not get ACPI table (size %X)", header.length)); return_ACPI_STATUS(status); } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_tb_get_table ( struct acpi_pointer *address, struct acpi_table_desc *table_info) { acpi_status status; struct acpi_table_header header; ACPI_FUNCTION_TRACE ("tb_get_table"); /* Get the header in order to get signature and table size */ status = acpi_tb_get_table_header (address, &header); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Get the entire table */ status = acpi_tb_get_table_body (address, &header, table_info); if (ACPI_FAILURE (status)) { ACPI_REPORT_ERROR (("Could not get ACPI table (size %X), %s\n", header.length, acpi_format_exception (status))); return_ACPI_STATUS (status); } return_ACPI_STATUS (AE_OK); }
acpi_status acpi_tb_get_primary_table ( struct acpi_pointer *address, struct acpi_table_desc *table_info) { acpi_status status; struct acpi_table_header header; ACPI_FUNCTION_TRACE ("tb_get_primary_table"); /* Ignore a NULL address in the RSDT */ if (!address->pointer.value) { return_ACPI_STATUS (AE_OK); } /* * Get the header in order to get signature and table size */ status = acpi_tb_get_table_header (address, &header); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Clear the table_info */ ACPI_MEMSET (table_info, 0, sizeof (struct acpi_table_desc)); /* * Check the table signature and make sure it is recognized. * Also checks the header checksum */ table_info->pointer = &header; status = acpi_tb_recognize_table (table_info, ACPI_TABLE_PRIMARY); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Get the entire table */ status = acpi_tb_get_table_body (address, &header, table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the table */ status = acpi_tb_install_table (table_info); return_ACPI_STATUS (status); }
static acpi_status acpi_tb_get_secondary_table ( struct acpi_pointer *address, acpi_string signature, struct acpi_table_desc *table_info) { acpi_status status; struct acpi_table_header header; ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature); /* Get the header in order to match the signature */ status = acpi_tb_get_table_header (address, &header); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Signature must match request */ if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { ACPI_REPORT_ERROR (( "Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature)); return_ACPI_STATUS (AE_BAD_SIGNATURE); } /* * Check the table signature and make sure it is recognized. * Also checks the header checksum */ table_info->pointer = &header; status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Get the entire table */ status = acpi_tb_get_table_body (address, &header, table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the table */ status = acpi_tb_install_table (table_info); return_ACPI_STATUS (status); }
acpi_status acpi_load_table ( struct acpi_table_header *table_ptr) { acpi_status status; struct acpi_table_desc table_info; struct acpi_pointer address; ACPI_FUNCTION_TRACE ("acpi_load_table"); if (!table_ptr) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Copy the table to a local buffer */ address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; address.pointer.logical = table_ptr; status = acpi_tb_get_table_body (&address, table_ptr, &table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the new table into the local data structures */ status = acpi_tb_install_table (&table_info); if (ACPI_FAILURE (status)) { /* Free table allocated by acpi_tb_get_table_body */ acpi_tb_delete_single_table (&table_info); return_ACPI_STATUS (status); } /* Convert the table to common format if necessary */ switch (table_info.type) { case ACPI_TABLE_FADT: status = acpi_tb_convert_table_fadt (); break; case ACPI_TABLE_FACS: status = acpi_tb_build_common_facs (&table_info); break; default: /* Load table into namespace if it contains executable AML */ status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node); break; } if (ACPI_FAILURE (status)) { /* Uninstall table and free the buffer */ (void) acpi_tb_uninstall_table (table_info.installed_desc); } return_ACPI_STATUS (status); }
acpi_status acpi_get_firmware_table ( acpi_string signature, u32 instance, u32 flags, struct acpi_table_header **table_pointer) { struct acpi_pointer rsdp_address; struct acpi_pointer address; acpi_status status; struct acpi_table_header header; struct acpi_table_desc table_info; struct acpi_table_desc rsdt_info; u32 table_count; u32 i; u32 j; ACPI_FUNCTION_TRACE ("acpi_get_firmware_table"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface */ /* * If we have a buffer, we must have a length too */ if ((instance == 0) || (!signature) || (!table_pointer)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } rsdt_info.pointer = NULL; if (!acpi_gbl_RSDP) { /* Get the RSDP */ status = acpi_os_get_root_pointer (flags, &rsdp_address); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor), (void *) &acpi_gbl_RSDP); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } else { acpi_gbl_RSDP = rsdp_address.pointer.logical; } /* * The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { /* Nope, BAD Signature */ return_ACPI_STATUS (AE_BAD_SIGNATURE); } if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { /* Nope, BAD Checksum */ return_ACPI_STATUS (AE_BAD_CHECKSUM); } } /* Get the RSDT and validate it */ acpi_tb_get_rsdt_address (&address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, ACPI_HIDWORD (address.pointer.value), ACPI_LODWORD (address.pointer.value))); /* Insert processor_mode flags */ address.pointer_type |= flags; status = acpi_tb_get_table (&address, &rsdt_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_tb_validate_rsdt (rsdt_info.pointer); if (ACPI_FAILURE (status)) { goto cleanup; } /* Get the number of table pointers within the RSDT */ table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < table_count; i++) { /* Get the next table pointer, handle RSDT vs. XSDT */ if (acpi_gbl_RSDP->revision < 2) { address.pointer.value = ((RSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; } else { address.pointer.value = ((XSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; } /* Get the table header */ status = acpi_tb_get_table_header (&address, &header); if (ACPI_FAILURE (status)) { goto cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ status = acpi_tb_get_table_body (&address, &header, &table_info); if (ACPI_FAILURE (status)) { goto cleanup; } *table_pointer = table_info.pointer; goto cleanup; } } } /* Did not find the table */ status = AE_NOT_EXIST; cleanup: acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length); return_ACPI_STATUS (status); }
acpi_status acpi_get_firmware_table(acpi_string signature, u32 instance, u32 flags, struct acpi_table_header **table_pointer) { acpi_status status; struct acpi_pointer address; struct acpi_table_header *header = NULL; struct acpi_table_desc *table_info = NULL; struct acpi_table_desc *rsdt_info; u32 table_count; u32 i; u32 j; ACPI_FUNCTION_TRACE("acpi_get_firmware_table"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface. * If we have a buffer, we must have a length too */ if ((instance == 0) || (!signature) || (!table_pointer)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { /* Get the RSDP */ status = acpi_os_get_root_pointer(flags, &address); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory(address.pointer.physical, sizeof(struct rsdp_descriptor), (void *)&acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else { acpi_gbl_RSDP = address.pointer.logical; } /* The RDSP signature and checksum must both be correct */ status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Get the RSDT address via the RSDP */ acpi_tb_get_rsdt_address(&address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, ACPI_FORMAT_UINT64(address.pointer.value))); /* Insert processor_mode flags */ address.pointer_type |= flags; /* Get and validate the RSDT */ rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_tb_get_table(&address, rsdt_info); if (ACPI_FAILURE(status)) { goto cleanup; } status = acpi_tb_validate_rsdt(rsdt_info->pointer); if (ACPI_FAILURE(status)) { goto cleanup; } /* Allocate a scratch table header and table descriptor */ header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header)); if (!header) { status = AE_NO_MEMORY; goto cleanup; } table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc)); if (!table_info) { status = AE_NO_MEMORY; goto cleanup; } /* Get the number of table pointers within the RSDT */ table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < table_count; i++) { /* * Get the next table pointer, handle RSDT vs. XSDT * RSDT pointers are 32 bits, XSDT pointers are 64 bits */ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } else { address.pointer.value = (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } /* Get the table header */ status = acpi_tb_get_table_header(&address, header); if (ACPI_FAILURE(status)) { goto cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ status = acpi_tb_get_table_body(&address, header, table_info); if (ACPI_FAILURE(status)) { goto cleanup; } *table_pointer = table_info->pointer; goto cleanup; } } } /* Did not find the table */ status = AE_NOT_EXIST; cleanup: if (rsdt_info->pointer) { acpi_os_unmap_memory(rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); } ACPI_MEM_FREE(rsdt_info); if (header) { ACPI_MEM_FREE(header); } if (table_info) { ACPI_MEM_FREE(table_info); } return_ACPI_STATUS(status); }