* Instance - the non zero instance of the table, allows
* support for multiple tables of the same type
* Flags - Physical/Virtual support
- * ret_buffer - pointer to a structure containing a buffer to
- * receive the table
+ * table_pointer - Where a buffer containing the table is
+ * returned
*
* RETURN: Status
*
- * DESCRIPTION: This function is called to get an ACPI table. The caller
- * supplies an out_buffer large enough to contain the entire ACPI
- * table. Upon completion
- * the out_buffer->Length field will indicate the number of bytes
- * copied into the out_buffer->buf_ptr buffer. This table will be
- * a complete table including the header.
+ * DESCRIPTION: This function is called to get an ACPI table. A buffer is
+ * allocated for the table and returned in table_pointer.
+ * This table will be a complete table including the header.
*
******************************************************************************/
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;
+ 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;
/*
* 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
+ * 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) ||
+ if ((instance == 0) ||
+ (!signature) ||
(!table_pointer)) {
return_ACPI_STATUS (AE_BAD_PARAMETER);
}
- rsdt_info.pointer = NULL;
+ /* Ensure that we have a RSDP */
if (!acpi_gbl_RSDP) {
/* Get the RSDP */
- status = acpi_os_get_root_pointer (flags, &rsdp_address);
+ status = acpi_os_get_root_pointer (flags, &address);
if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n"));
+ 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),
+ 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 = rsdp_address.pointer.logical;
+ acpi_gbl_RSDP = address.pointer.logical;
}
- /*
- * The signature and checksum must both be correct
- */
+ /* 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 */
}
}
- /* Get the RSDT and validate it */
+ /* 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,
address.pointer_type |= flags;
- status = acpi_tb_get_table (&address, &rsdt_info);
+ /* 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)) {
- return_ACPI_STATUS (status);
+ goto cleanup;
}
- status = acpi_tb_validate_rsdt (rsdt_info.pointer);
+ status = acpi_tb_validate_rsdt (rsdt_info->pointer);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
- /* Get the number of table pointers within the RSDT */
+ /* 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;
+ }
- table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer);
+ /* 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;
/*
/* Get the next table pointer, handle RSDT vs. XSDT */
if (acpi_gbl_RSDP->revision < 2) {
- address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info.pointer))->table_offset_entry[i];
+ 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];
+ 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);
+ 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)) {
+ 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);
+ status = acpi_tb_get_table_body (&address, header, table_info);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
- *table_pointer = table_info.pointer;
+ *table_pointer = table_info->pointer;
goto cleanup;
}
}
cleanup:
- acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length);
+ 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);
}
* Flags - Current memory mode (logical vs.
* physical addressing)
*
- * RETURN: Status
+ * RETURN: Status, RSDP physical address
*
* DESCRIPTION: search lower 1_mbyte of memory for the root system descriptor
* pointer structure. If it is found, set *RSDP to point to it.
*
- * NOTE: The RSDp must be either in the first 1_k of the Extended
- * BIOS Data Area or between E0000 and FFFFF (ACPI 1.0 section
- * 5.2.2; assertion #421).
+ * NOTE1: The RSDp must be either in the first 1_k of the Extended
+ * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.)
+ * Only a 32-bit physical address is necessary.
+ *
+ * NOTE2: This function is always available, regardless of the
+ * initialization state of the rest of ACPI.
*
******************************************************************************/
{
u8 *table_ptr;
u8 *mem_rover;
- u64 phys_addr;
- acpi_status status = AE_OK;
+ u32 physical_address;
+ acpi_status status;
ACPI_FUNCTION_TRACE ("tb_find_rsdp");
*/
if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) {
/*
- * 1) Search EBDA (low memory) paragraphs
+ * 1a) Get the location of the EBDA
*/
- status = acpi_os_map_memory ((u64) ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE,
+ status = acpi_os_map_memory ((acpi_physical_address) ACPI_EBDA_PTR_LOCATION,
+ ACPI_EBDA_PTR_LENGTH,
(void *) &table_ptr);
if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
- ACPI_LO_RSDP_WINDOW_BASE, ACPI_LO_RSDP_WINDOW_SIZE));
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+ ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH));
return_ACPI_STATUS (status);
}
- mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
- acpi_os_unmap_memory (table_ptr, ACPI_LO_RSDP_WINDOW_SIZE);
+ ACPI_MOVE_16_TO_32 (&physical_address, table_ptr);
+ physical_address <<= 4; /* Convert segment to physical address */
+ acpi_os_unmap_memory (table_ptr, ACPI_EBDA_PTR_LENGTH);
- if (mem_rover) {
- /* Found it, return the physical address */
+ /* EBDA present? */
- phys_addr = ACPI_LO_RSDP_WINDOW_BASE;
- phys_addr += ACPI_PTR_DIFF (mem_rover,table_ptr);
+ if (physical_address > 0x400) {
+ /*
+ * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+ */
+ status = acpi_os_map_memory ((acpi_physical_address) physical_address,
+ ACPI_EBDA_WINDOW_SIZE,
+ (void *) &table_ptr);
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
+ physical_address, ACPI_EBDA_WINDOW_SIZE));
+ return_ACPI_STATUS (status);
+ }
- table_info->physical_address = phys_addr;
- return_ACPI_STATUS (AE_OK);
+ mem_rover = acpi_tb_scan_memory_for_rsdp (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+ acpi_os_unmap_memory (table_ptr, ACPI_EBDA_WINDOW_SIZE);
+
+ if (mem_rover) {
+ /* Found it, return the physical address */
+
+ physical_address += ACPI_PTR_DIFF (mem_rover, table_ptr);
+
+ table_info->physical_address = (acpi_physical_address) physical_address;
+ return_ACPI_STATUS (AE_OK);
+ }
}
/*
- * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+ * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
*/
- status = acpi_os_map_memory ((u64) ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE,
+ status = acpi_os_map_memory ((acpi_physical_address) ACPI_HI_RSDP_WINDOW_BASE,
+ ACPI_HI_RSDP_WINDOW_SIZE,
(void *) &table_ptr);
if (ACPI_FAILURE (status)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %X for length %X\n",
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not map memory at %8.8X for length %X\n",
ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE));
return_ACPI_STATUS (status);
}
if (mem_rover) {
/* Found it, return the physical address */
- phys_addr = ACPI_HI_RSDP_WINDOW_BASE;
- phys_addr += ACPI_PTR_DIFF (mem_rover, table_ptr);
+ physical_address = ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (mem_rover, table_ptr);
- table_info->physical_address = phys_addr;
+ table_info->physical_address = (acpi_physical_address) physical_address;
return_ACPI_STATUS (AE_OK);
}
}
*/
else {
/*
- * 1) Search EBDA (low memory) paragraphs
+ * 1a) Get the location of the EBDA
*/
- mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_LO_RSDP_WINDOW_BASE),
- ACPI_LO_RSDP_WINDOW_SIZE);
- if (mem_rover) {
- /* Found it, return the physical address */
-
- table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
- return_ACPI_STATUS (AE_OK);
+ ACPI_MOVE_16_TO_32 (&physical_address, ACPI_EBDA_PTR_LOCATION);
+ physical_address <<= 4; /* Convert segment to physical address */
+
+ /* EBDA present? */
+
+ if (physical_address > 0x400) {
+ /*
+ * 1b) Search EBDA paragraphs (EBDa is required to be a minimum of 1_k length)
+ */
+ mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (physical_address),
+ ACPI_EBDA_WINDOW_SIZE);
+ if (mem_rover) {
+ /* Found it, return the physical address */
+
+ table_info->physical_address = ACPI_TO_INTEGER (mem_rover);
+ return_ACPI_STATUS (AE_OK);
+ }
}
/*
- * 2) Search upper memory: 16-byte boundaries in E0000h-F0000h
+ * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh
*/
mem_rover = acpi_tb_scan_memory_for_rsdp (ACPI_PHYSADDR_TO_PTR (ACPI_HI_RSDP_WINDOW_BASE),
ACPI_HI_RSDP_WINDOW_SIZE);