mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-07 14:24:18 +08:00
d56ba92b0c
ACPICA commit 807665510f1ea71bbdc063c27782a1da56e8e10a Before this change we see the following UBSAN stack trace in Fuchsia: #0 0x00002234800696e6 in acpi_tb_get_root_table_entry(u8*, u32) ../../third_party/acpica/source/components/tables/tbutils.c:231 <platform-bus-x86.so>+0x9106e6 #1.2 0x0000233d72c8777f in ubsan_get_stack_trace() compiler-rt/lib/ubsan/ubsan_diag.cpp:41 <libclang_rt.asan.so>+0x3d77f #1.1 0x0000233d72c8777f in maybe_print_stack_trace() compiler-rt/lib/ubsan/ubsan_diag.cpp:51 <libclang_rt.asan.so>+0x3d77f #1 0x0000233d72c8777f in ~scoped_report() compiler-rt/lib/ubsan/ubsan_diag.cpp:387 <libclang_rt.asan.so>+0x3d77f #2 0x0000233d72c88385 in handletype_mismatch_impl() compiler-rt/lib/ubsan/ubsan_handlers.cpp:137 <libclang_rt.asan.so>+0x3e385 #3 0x0000233d72c87ead in compiler-rt/lib/ubsan/ubsan_handlers.cpp:142 <libclang_rt.asan.so>+0x3dead #4 0x00002234800696e6 in acpi_tb_get_root_table_entry(u8*, u32) ../../third_party/acpica/source/components/tables/tbutils.c:231 <platform-bus-x86.so>+0x9106e6 #5 0x00002234800691dd in acpi_tb_parse_root_table(acpi_physical_address) ../../third_party/acpica/source/components/tables/tbutils.c:385 <platform-bus-x86.so>+0x9101dd #6 0x0000223480070b06 in acpi_initialize_tables(struct acpi_table_desc*, u32, u8) ../../third_party/acpica/source/components/tables/tbxface.c:160 <platform-bus-x86.so>+0x917b06 #7 0x000022347fb803b4 in acpi::acpi_impl::initialize_acpi(acpi::acpi_impl*) ../../src/devices/board/lib/acpi/acpi-impl.cc:200 <platform-bus-x86.so>+0x4273b4 #8 0x000022347fa30d14 in x86::X86::early_acpi_init(x86::X86*) ../../src/devices/board/drivers/x86/init.cc:34 <platform-bus-x86.so>+0x2d7d14 #9 0x000022347fa310cf in x86::X86::early_init(x86::X86*) ../../src/devices/board/drivers/x86/init.cc:43 <platform-bus-x86.so>+0x2d80cf #10 0x000022347fa79410 in x86::X86::Bind(x86::X86*) ../../src/devices/board/drivers/x86/x86.cc:144 <platform-bus-x86.so>+0x320410 #11 0x000022347fa78ec0 in x86::X86::create_and_bind(void*, zx_device_t*) ../../src/devices/board/drivers/x86/x86.cc:123 <platform-bus-x86.so>+0x31fec0 #12 0x000020dc8908502f in λ(const zx_driver::bind_op::(anon class)*) ../../src/devices/bin/driver_host/zx_driver.cc:36 <<application>>+0x41502f #13 0x000020dc89084e03 in fit::internal::target<(lambda at../../src/devices/bin/driver_host/zx_driver.cc:34:61), false, false, void>::invoke(void*) ../../sdk/lib/fit/include/lib/fit/internal/function.h:181 <<application>>+0x414e03 #14 0x000020dc8935a930 in fit::internal::function_base<16UL, false, void()>::invoke(const fit::internal::function_base<16UL, false, void ()>*) ../../sdk/lib/fit/include/lib/fit/internal/function.h:505 <<application>>+0x6ea930 #15 0x000020dc893e2f8a in fit::function_impl<16UL, false, void()>::operator()(const fit::function_impl<16UL, false, void ()>*) ../../sdk/lib/fit/include/lib/fit/function.h:300 <<application>>+0x772f8a #16 0x000020dc8948dec5 in async::internal::retained_task::Handler(async_dispatcher_t*, async_task_t*, zx_status_t) ../../zircon/system/ulib/async/task.cc:25 <<application>>+0x81dec5 #17 0x000023ab5abcf91e in λ(const driver_runtime::Dispatcher::post_task::(anon class)*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, zx_status_t) ../../src/devices/bin/driver_runtime/dispatcher.cc:715 <libdriver_runtime.so>+0xed91e #18 0x000023ab5abcf621 in fit::internal::target<(lambda at../../src/devices/bin/driver_runtime/dispatcher.cc:714:7), true, false, void, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request>>, int>::invoke(void*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, int) ../../sdk/lib/fit/include/lib/fit/internal/function.h:128 <libdriver_runtime.so>+0xed621 #19 0x000023ab5abaa482 in fit::internal::function_base<24UL, true, void(std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request>>, int)>::invoke(const fit::internal::function_base<24UL, true, void (std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, int)>*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, int) ../../sdk/lib/fit/include/lib/fit/internal/function.h:505 <libdriver_runtime.so>+0xc8482 #20 0x000023ab5abaa0f8 in fit::callback_impl<24UL, true, void(std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request>>, int)>::operator()(fit::callback_impl<24UL, true, void (std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, int)>*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, int) ../../sdk/lib/fit/include/lib/fit/function.h:451 <libdriver_runtime.so>+0xc80f8 #21 0x000023ab5ab81c76 in driver_runtime::callback_request::Call(driver_runtime::callback_request*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >, zx_status_t) ../../src/devices/bin/driver_runtime/callback_request.h:67 <libdriver_runtime.so>+0x9fc76 #22 0x000023ab5ab8e7ef in driver_runtime::Dispatcher::dispatch_callback(driver_runtime::Dispatcher*, std::__2::unique_ptr<driver_runtime::callback_request, std::__2::default_delete<driver_runtime::callback_request> >) ../../src/devices/bin/driver_runtime/dispatcher.cc:1093 <libdriver_runtime.so>+0xac7ef #23 0x000023ab5ab91d67 in driver_runtime::Dispatcher::dispatch_callbacks(driver_runtime::Dispatcher*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../src/devices/bin/driver_runtime/dispatcher.cc:1169 <libdriver_runtime.so>+0xafd67 #24 0x000023ab5abbe9a2 in λ(const driver_runtime::Dispatcher::create_with_adder::(anon class)*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../src/devices/bin/driver_runtime/dispatcher.cc:338 <libdriver_runtime.so>+0xdc9a2 #25 0x000023ab5abbe6d2 in fit::internal::target<(lambda at../../src/devices/bin/driver_runtime/dispatcher.cc:337:7), true, false, void, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter>>, fbl::ref_ptr<driver_runtime::Dispatcher>>::invoke(void*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../sdk/lib/fit/include/lib/fit/internal/function.h:128 <libdriver_runtime.so>+0xdc6d2 #26 0x000023ab5abac1e5 in fit::internal::function_base<8UL, true, void(std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter>>, fbl::ref_ptr<driver_runtime::Dispatcher>)>::invoke(const fit::internal::function_base<8UL, true, void (std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>)>*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../sdk/lib/fit/include/lib/fit/internal/function.h:505 <libdriver_runtime.so>+0xca1e5 #27 0x000023ab5ababe32 in fit::function_impl<8UL, true, void(std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter>>, fbl::ref_ptr<driver_runtime::Dispatcher>)>::operator()(const fit::function_impl<8UL, true, void (std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>)>*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../sdk/lib/fit/include/lib/fit/function.h:300 <libdriver_runtime.so>+0xc9e32 #28 0x000023ab5ab95444 in driver_runtime::Dispatcher::event_waiter::invoke_callback(driver_runtime::Dispatcher::event_waiter*, std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, fbl::ref_ptr<driver_runtime::Dispatcher>) ../../src/devices/bin/driver_runtime/dispatcher.h:299 <libdriver_runtime.so>+0xb3444 #29 0x000023ab5ab94feb in driver_runtime::Dispatcher::event_waiter::handle_event(std::__2::unique_ptr<driver_runtime::Dispatcher::event_waiter, std::__2::default_delete<driver_runtime::Dispatcher::event_waiter> >, async_dispatcher_t*, async::wait_base*, zx_status_t, zx_packet_signal_t const*) ../../src/devices/bin/driver_runtime/dispatcher.cc:1259 <libdriver_runtime.so>+0xb2feb #30 0x000023ab5abbef74 in async_loop_owned_event_handler<driver_runtime::Dispatcher::event_waiter>::handle_event(async_loop_owned_event_handler<driver_runtime::Dispatcher::event_waiter>*, async_dispatcher_t*, async::wait_base*, zx_status_t, zx_packet_signal_t const*) ../../src/devices/bin/driver_runtime/async_loop_owned_event_handler.h:59 <libdriver_runtime.so>+0xdcf74 #31 0x000023ab5abbf1cb in async::wait_method<async_loop_owned_event_handler<driver_runtime::Dispatcher::event_waiter>, &async_loop_owned_event_handler<driver_runtime::Dispatcher::event_waiter>::handle_event>::call_handler(async_dispatcher_t*, async_wait_t*, zx_status_t, zx_packet_signal_t const*) ../../zircon/system/ulib/async/include/lib/async/cpp/wait.h:201 <libdriver_runtime.so>+0xdd1cb #32 0x000023ab5ac323a9 in async_loop_dispatch_wait(async_loop_t*, async_wait_t*, zx_status_t, zx_packet_signal_t const*) ../../zircon/system/ulib/async-loop/loop.c:381 <libdriver_runtime.so>+0x1503a9 #33 0x000023ab5ac2ba82 in async_loop_run_once(async_loop_t*, zx_time_t) ../../zircon/system/ulib/async-loop/loop.c:330 <libdriver_runtime.so>+0x149a82 #34 0x000023ab5ac2b102 in async_loop_run(async_loop_t*, zx_time_t, _Bool) ../../zircon/system/ulib/async-loop/loop.c:288 <libdriver_runtime.so>+0x149102 #35 0x000023ab5ac2ceb7 in async_loop_run_thread(void*) ../../zircon/system/ulib/async-loop/loop.c:840 <libdriver_runtime.so>+0x14aeb7 #36 0x000040b3be411f1c in start_c11(void*) ../../zircon/third_party/ulib/musl/pthread/pthread_create.c:55 <libc.so>+0xd7f1c #37 0x000040b3be53ce8d in thread_trampoline(uintptr_t, uintptr_t) ../../zircon/system/ulib/runtime/thread.cc:100 <libc.so>+0x202e8d Link: https://github.com/acpica/acpica/commit/80766551 Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
448 lines
13 KiB
C
448 lines
13 KiB
C
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
|
|
/******************************************************************************
|
|
*
|
|
* Module Name: tbutils - ACPI Table utilities
|
|
*
|
|
* Copyright (C) 2000 - 2023, Intel Corp.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#include <acpi/acpi.h>
|
|
#include "accommon.h"
|
|
#include "actables.h"
|
|
|
|
#define _COMPONENT ACPI_TABLES
|
|
ACPI_MODULE_NAME("tbutils")
|
|
|
|
/* Local prototypes */
|
|
static acpi_physical_address
|
|
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
|
|
|
|
#if (!ACPI_REDUCED_HARDWARE)
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_initialize_facs
|
|
*
|
|
* PARAMETERS: None
|
|
*
|
|
* RETURN: Status
|
|
*
|
|
* DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
|
|
* for accessing the Global Lock and Firmware Waking Vector
|
|
*
|
|
******************************************************************************/
|
|
|
|
acpi_status acpi_tb_initialize_facs(void)
|
|
{
|
|
struct acpi_table_facs *facs;
|
|
|
|
/* If Hardware Reduced flag is set, there is no FACS */
|
|
|
|
if (acpi_gbl_reduced_hardware) {
|
|
acpi_gbl_FACS = NULL;
|
|
return (AE_OK);
|
|
} else if (acpi_gbl_FADT.Xfacs &&
|
|
(!acpi_gbl_FADT.facs
|
|
|| !acpi_gbl_use32_bit_facs_addresses)) {
|
|
(void)acpi_get_table_by_index(acpi_gbl_xfacs_index,
|
|
ACPI_CAST_INDIRECT_PTR(struct
|
|
acpi_table_header,
|
|
&facs));
|
|
acpi_gbl_FACS = facs;
|
|
} else if (acpi_gbl_FADT.facs) {
|
|
(void)acpi_get_table_by_index(acpi_gbl_facs_index,
|
|
ACPI_CAST_INDIRECT_PTR(struct
|
|
acpi_table_header,
|
|
&facs));
|
|
acpi_gbl_FACS = facs;
|
|
}
|
|
|
|
/* If there is no FACS, just continue. There was already an error msg */
|
|
|
|
return (AE_OK);
|
|
}
|
|
#endif /* !ACPI_REDUCED_HARDWARE */
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_check_dsdt_header
|
|
*
|
|
* PARAMETERS: None
|
|
*
|
|
* RETURN: None
|
|
*
|
|
* DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
|
|
* if the DSDT has been replaced from outside the OS and/or if
|
|
* the DSDT header has been corrupted.
|
|
*
|
|
******************************************************************************/
|
|
|
|
void acpi_tb_check_dsdt_header(void)
|
|
{
|
|
|
|
/* Compare original length and checksum to current values */
|
|
|
|
if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length ||
|
|
acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) {
|
|
ACPI_BIOS_ERROR((AE_INFO,
|
|
"The DSDT has been corrupted or replaced - "
|
|
"old, new headers below"));
|
|
|
|
acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
|
|
acpi_tb_print_table_header(0, acpi_gbl_DSDT);
|
|
|
|
ACPI_ERROR((AE_INFO,
|
|
"Please send DMI info to linux-acpi@vger.kernel.org\n"
|
|
"If system does not work as expected, please boot with acpi=copy_dsdt"));
|
|
|
|
/* Disable further error messages */
|
|
|
|
acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
|
|
acpi_gbl_original_dsdt_header.checksum =
|
|
acpi_gbl_DSDT->checksum;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_copy_dsdt
|
|
*
|
|
* PARAMETERS: table_index - Index of installed table to copy
|
|
*
|
|
* RETURN: The copied DSDT
|
|
*
|
|
* DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
|
|
* Some very bad BIOSs are known to either corrupt the DSDT or
|
|
* install a new, bad DSDT. This copy works around the problem.
|
|
*
|
|
******************************************************************************/
|
|
|
|
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
|
|
{
|
|
struct acpi_table_header *new_table;
|
|
struct acpi_table_desc *table_desc;
|
|
|
|
table_desc = &acpi_gbl_root_table_list.tables[table_index];
|
|
|
|
new_table = ACPI_ALLOCATE(table_desc->length);
|
|
if (!new_table) {
|
|
ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
|
|
table_desc->length));
|
|
return (NULL);
|
|
}
|
|
|
|
memcpy(new_table, table_desc->pointer, table_desc->length);
|
|
acpi_tb_uninstall_table(table_desc);
|
|
|
|
acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
|
|
tables[acpi_gbl_dsdt_index],
|
|
ACPI_PTR_TO_PHYSADDR(new_table),
|
|
ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
|
|
new_table);
|
|
|
|
ACPI_INFO(("Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length));
|
|
|
|
return (new_table);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_get_root_table_entry
|
|
*
|
|
* PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry
|
|
* table_entry_size - sizeof 32 or 64 (RSDT or XSDT)
|
|
*
|
|
* RETURN: Physical address extracted from the root table
|
|
*
|
|
* DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
|
|
* both 32-bit and 64-bit platforms
|
|
*
|
|
* NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on
|
|
* 64-bit platforms.
|
|
*
|
|
******************************************************************************/
|
|
|
|
static acpi_physical_address
|
|
acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
|
|
{
|
|
u32 address32;
|
|
u64 address64;
|
|
|
|
/*
|
|
* Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
|
|
* Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
|
|
*/
|
|
if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) {
|
|
/*
|
|
* 32-bit platform, RSDT: Return 32-bit table entry
|
|
* 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
|
|
*/
|
|
ACPI_MOVE_32_TO_32(&address32, table_entry);
|
|
return address32;
|
|
} else {
|
|
/*
|
|
* 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
|
|
* 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
|
|
* return 64-bit
|
|
*/
|
|
ACPI_MOVE_64_TO_64(&address64, table_entry);
|
|
|
|
#if ACPI_MACHINE_WIDTH == 32
|
|
if (address64 > ACPI_UINT32_MAX) {
|
|
|
|
/* Will truncate 64-bit address to 32 bits, issue warning */
|
|
|
|
ACPI_BIOS_WARNING((AE_INFO,
|
|
"64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
|
|
" truncating",
|
|
ACPI_FORMAT_UINT64(address64)));
|
|
}
|
|
#endif
|
|
return ((acpi_physical_address)(address64));
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_parse_root_table
|
|
*
|
|
* PARAMETERS: rsdp_address - Pointer to the RSDP
|
|
*
|
|
* RETURN: Status
|
|
*
|
|
* DESCRIPTION: This function is called to parse the Root System Description
|
|
* Table (RSDT or XSDT)
|
|
*
|
|
* NOTE: Tables are mapped (not copied) for efficiency. The FACS must
|
|
* be mapped and cannot be copied because it contains the actual
|
|
* memory location of the ACPI Global Lock.
|
|
*
|
|
******************************************************************************/
|
|
|
|
acpi_status ACPI_INIT_FUNCTION
|
|
acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
|
|
{
|
|
struct acpi_table_rsdp *rsdp;
|
|
u32 table_entry_size;
|
|
u32 i;
|
|
u32 table_count;
|
|
struct acpi_table_header *table;
|
|
acpi_physical_address address;
|
|
u32 length;
|
|
u8 *table_entry;
|
|
acpi_status status;
|
|
u32 table_index;
|
|
|
|
ACPI_FUNCTION_TRACE(tb_parse_root_table);
|
|
|
|
/* Map the entire RSDP and extract the address of the RSDT or XSDT */
|
|
|
|
rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
|
|
if (!rsdp) {
|
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
|
}
|
|
|
|
acpi_tb_print_table_header(rsdp_address,
|
|
ACPI_CAST_PTR(struct acpi_table_header,
|
|
rsdp));
|
|
|
|
/* Use XSDT if present and not overridden. Otherwise, use RSDT */
|
|
|
|
if ((rsdp->revision > 1) &&
|
|
rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) {
|
|
/*
|
|
* RSDP contains an XSDT (64-bit physical addresses). We must use
|
|
* the XSDT if the revision is > 1 and the XSDT pointer is present,
|
|
* as per the ACPI specification.
|
|
*/
|
|
address = (acpi_physical_address)rsdp->xsdt_physical_address;
|
|
table_entry_size = ACPI_XSDT_ENTRY_SIZE;
|
|
} else {
|
|
/* Root table is an RSDT (32-bit physical addresses) */
|
|
|
|
address = (acpi_physical_address)rsdp->rsdt_physical_address;
|
|
table_entry_size = ACPI_RSDT_ENTRY_SIZE;
|
|
}
|
|
|
|
/*
|
|
* It is not possible to map more than one entry in some environments,
|
|
* so unmap the RSDP here before mapping other tables
|
|
*/
|
|
acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
|
|
|
|
/* Map the RSDT/XSDT table header to get the full table length */
|
|
|
|
table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
|
|
if (!table) {
|
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
|
}
|
|
|
|
acpi_tb_print_table_header(address, table);
|
|
|
|
/*
|
|
* Validate length of the table, and map entire table.
|
|
* Minimum length table must contain at least one entry.
|
|
*/
|
|
length = table->length;
|
|
acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
|
|
|
|
if (length < (sizeof(struct acpi_table_header) + table_entry_size)) {
|
|
ACPI_BIOS_ERROR((AE_INFO,
|
|
"Invalid table length 0x%X in RSDT/XSDT",
|
|
length));
|
|
return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
|
|
}
|
|
|
|
table = acpi_os_map_memory(address, length);
|
|
if (!table) {
|
|
return_ACPI_STATUS(AE_NO_MEMORY);
|
|
}
|
|
|
|
/* Validate the root table checksum */
|
|
|
|
status = acpi_ut_verify_checksum(table, length);
|
|
if (ACPI_FAILURE(status)) {
|
|
acpi_os_unmap_memory(table, length);
|
|
return_ACPI_STATUS(status);
|
|
}
|
|
|
|
/* Get the number of entries and pointer to first entry */
|
|
|
|
table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
|
|
table_entry_size);
|
|
table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
|
|
|
|
/* 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,
|
|
NULL, FALSE, TRUE,
|
|
&table_index);
|
|
|
|
if (ACPI_SUCCESS(status) &&
|
|
ACPI_COMPARE_NAMESEG(&acpi_gbl_root_table_list.
|
|
tables[table_index].signature,
|
|
ACPI_SIG_FADT)) {
|
|
acpi_gbl_fadt_index = table_index;
|
|
acpi_tb_parse_fadt();
|
|
}
|
|
|
|
next_table:
|
|
|
|
table_entry += table_entry_size;
|
|
}
|
|
|
|
acpi_os_unmap_memory(table, length);
|
|
return_ACPI_STATUS(AE_OK);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_get_table
|
|
*
|
|
* PARAMETERS: table_desc - Table descriptor
|
|
* out_table - Where the pointer to the table is returned
|
|
*
|
|
* RETURN: Status and pointer to the requested table
|
|
*
|
|
* DESCRIPTION: Increase a reference to a table descriptor and return the
|
|
* validated table pointer.
|
|
* If the table descriptor is an entry of the root table list,
|
|
* this API must be invoked with ACPI_MTX_TABLES acquired.
|
|
*
|
|
******************************************************************************/
|
|
|
|
acpi_status
|
|
acpi_tb_get_table(struct acpi_table_desc *table_desc,
|
|
struct acpi_table_header **out_table)
|
|
{
|
|
acpi_status status;
|
|
|
|
ACPI_FUNCTION_TRACE(acpi_tb_get_table);
|
|
|
|
if (table_desc->validation_count == 0) {
|
|
|
|
/* Table need to be "VALIDATED" */
|
|
|
|
status = acpi_tb_validate_table(table_desc);
|
|
if (ACPI_FAILURE(status)) {
|
|
return_ACPI_STATUS(status);
|
|
}
|
|
}
|
|
|
|
if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
|
|
table_desc->validation_count++;
|
|
|
|
/*
|
|
* Detect validation_count overflows to ensure that the warning
|
|
* message will only be printed once.
|
|
*/
|
|
if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
|
|
ACPI_WARNING((AE_INFO,
|
|
"Table %p, Validation count overflows\n",
|
|
table_desc));
|
|
}
|
|
}
|
|
|
|
*out_table = table_desc->pointer;
|
|
return_ACPI_STATUS(AE_OK);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* FUNCTION: acpi_tb_put_table
|
|
*
|
|
* PARAMETERS: table_desc - Table descriptor
|
|
*
|
|
* RETURN: None
|
|
*
|
|
* DESCRIPTION: Decrease a reference to a table descriptor and release the
|
|
* validated table pointer if no references.
|
|
* If the table descriptor is an entry of the root table list,
|
|
* this API must be invoked with ACPI_MTX_TABLES acquired.
|
|
*
|
|
******************************************************************************/
|
|
|
|
void acpi_tb_put_table(struct acpi_table_desc *table_desc)
|
|
{
|
|
|
|
ACPI_FUNCTION_TRACE(acpi_tb_put_table);
|
|
|
|
if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
|
|
table_desc->validation_count--;
|
|
|
|
/*
|
|
* Detect validation_count underflows to ensure that the warning
|
|
* message will only be printed once.
|
|
*/
|
|
if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
|
|
ACPI_WARNING((AE_INFO,
|
|
"Table %p, Validation count underflows\n",
|
|
table_desc));
|
|
return_VOID;
|
|
}
|
|
}
|
|
|
|
if (table_desc->validation_count == 0) {
|
|
|
|
/* Table need to be "INVALIDATED" */
|
|
|
|
acpi_tb_invalidate_table(table_desc);
|
|
}
|
|
|
|
return_VOID;
|
|
}
|