2005-04-17 06:20:36 +08:00
/******************************************************************************
*
* Module Name : tbget - ACPI Table get * routines
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2006-01-14 05:22:00 +08:00
* Copyright ( C ) 2000 - 2006 , R . Byron Moore
2005-04-17 06:20:36 +08:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions , and the following disclaimer ,
* without modification .
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the " NO WARRANTY " disclaimer below
* ( " Disclaimer " ) and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution .
* 3. Neither the names of the above - listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) version 2 as published by the Free
* Software Foundation .
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT ,
* STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES .
*/
# include <acpi/acpi.h>
# include <acpi/actables.h>
# define _COMPONENT ACPI_TABLES
2005-08-05 12:44:28 +08:00
ACPI_MODULE_NAME ( " tbget " )
2005-04-17 06:20:36 +08:00
2005-04-19 10:49:35 +08:00
/* Local prototypes */
static acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_this_table ( struct acpi_pointer * address ,
struct acpi_table_header * header ,
struct acpi_table_desc * table_info ) ;
2005-04-19 10:49:35 +08:00
static acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_table_override ( struct acpi_table_header * header ,
struct acpi_table_desc * table_info ) ;
2005-04-17 06:20:36 +08:00
/*******************************************************************************
*
* FUNCTION : acpi_tb_get_table
*
* PARAMETERS : Address - Address of table to retrieve . Can be
* Logical or Physical
* table_info - Where table info is returned
*
* RETURN : None
*
* DESCRIPTION : Get entire table of unknown size .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_table ( struct acpi_pointer * address ,
struct acpi_table_desc * table_info )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
acpi_status status ;
struct acpi_table_header header ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_get_table " ) ;
2005-04-17 06:20:36 +08:00
2005-04-19 10:49:35 +08:00
/* Get the header in order to get signature and table size */
2005-08-05 12:44:28 +08:00
status = acpi_tb_get_table_header ( address , & header ) ;
if ( ACPI_FAILURE ( status ) ) {
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/* Get the entire table */
2005-08-05 12:44:28 +08:00
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 ) ;
2005-04-17 06:20:36 +08:00
}
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-17 06:20:36 +08:00
}
/*******************************************************************************
*
* FUNCTION : acpi_tb_get_table_header
*
* PARAMETERS : Address - Address of table to retrieve . Can be
* Logical or Physical
* return_header - Where the table header is returned
*
* RETURN : Status
*
* DESCRIPTION : Get an ACPI table header . Works in both physical or virtual
* addressing mode . Works with both physical or logical pointers .
* Table is either copied or mapped , depending on the pointer
* type and mode of the processor .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_table_header ( struct acpi_pointer * address ,
struct acpi_table_header * return_header )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
acpi_status status = AE_OK ;
struct acpi_table_header * header = NULL ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_get_table_header " ) ;
2005-04-17 06:20:36 +08:00
/*
2005-04-19 10:49:35 +08:00
* Flags contains the current processor mode ( Virtual or Physical
* addressing ) The pointer_type is either Logical or Physical
2005-04-17 06:20:36 +08:00
*/
switch ( address - > pointer_type ) {
case ACPI_PHYSMODE_PHYSPTR :
case ACPI_LOGMODE_LOGPTR :
/* Pointer matches processor mode, copy the header */
2005-08-05 12:44:28 +08:00
ACPI_MEMCPY ( return_header , address - > pointer . logical ,
sizeof ( struct acpi_table_header ) ) ;
2005-04-17 06:20:36 +08:00
break ;
case ACPI_LOGMODE_PHYSPTR :
2005-08-05 12:44:28 +08:00
/* Create a logical address for the physical pointer */
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
status = acpi_os_map_memory ( address - > pointer . physical ,
sizeof ( struct acpi_table_header ) ,
( void * ) & header ) ;
if ( ACPI_FAILURE ( status ) ) {
ACPI_REPORT_ERROR ( ( " Could not map memory at %8.8X%8.8X for length %X \n " , ACPI_FORMAT_UINT64 ( address - > pointer . physical ) , sizeof ( struct acpi_table_header ) ) ) ;
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/* Copy header and delete mapping */
2005-08-05 12:44:28 +08:00
ACPI_MEMCPY ( return_header , header ,
sizeof ( struct acpi_table_header ) ) ;
acpi_os_unmap_memory ( header , sizeof ( struct acpi_table_header ) ) ;
2005-04-17 06:20:36 +08:00
break ;
default :
2005-08-05 12:44:28 +08:00
ACPI_REPORT_ERROR ( ( " Invalid address flags %X \n " ,
address - > pointer_type ) ) ;
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
2005-04-17 06:20:36 +08:00
}
2005-08-05 12:44:28 +08:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_TABLES , " Table Signature: [%4.4s] \n " ,
return_header - > signature ) ) ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-17 06:20:36 +08:00
}
/*******************************************************************************
*
* FUNCTION : acpi_tb_get_table_body
*
* PARAMETERS : Address - Address of table to retrieve . Can be
* Logical or Physical
* Header - Header of the table to retrieve
* table_info - Where the table info is returned
*
* RETURN : Status
*
* DESCRIPTION : Get an entire ACPI table with support to allow the host OS to
* replace the table with a newer version ( table override . )
* Works in both physical or virtual
* addressing mode . Works with both physical or logical pointers .
* Table is either copied or mapped , depending on the pointer
* type and mode of the processor .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_table_body ( struct acpi_pointer * address ,
struct acpi_table_header * header ,
struct acpi_table_desc * table_info )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
acpi_status status ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_get_table_body " ) ;
2005-04-17 06:20:36 +08:00
if ( ! table_info | | ! address ) {
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
2005-04-17 06:20:36 +08:00
}
2005-04-19 10:49:35 +08:00
/* Attempt table override. */
2005-08-05 12:44:28 +08:00
status = acpi_tb_table_override ( header , table_info ) ;
if ( ACPI_SUCCESS ( status ) ) {
2005-04-17 06:20:36 +08:00
/* Table was overridden by the host OS */
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/* No override, get the original table */
2005-08-05 12:44:28 +08:00
status = acpi_tb_get_this_table ( address , header , table_info ) ;
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/*******************************************************************************
*
* FUNCTION : acpi_tb_table_override
*
* PARAMETERS : Header - Pointer to table header
* table_info - Return info if table is overridden
*
* RETURN : None
*
* DESCRIPTION : Attempts override of current table with a new one if provided
* by the host OS .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-04-19 10:49:35 +08:00
static acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_table_override ( struct acpi_table_header * header ,
struct acpi_table_desc * table_info )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
struct acpi_table_header * new_table ;
acpi_status status ;
struct acpi_pointer address ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_table_override " ) ;
2005-04-17 06:20:36 +08:00
/*
* The OSL will examine the header and decide whether to override this
* table . If it decides to override , a table will be returned in new_table ,
* which we will then copy .
*/
2005-08-05 12:44:28 +08:00
status = acpi_os_table_override ( header , & new_table ) ;
if ( ACPI_FAILURE ( status ) ) {
2005-04-17 06:20:36 +08:00
/* Some severe error from the OSL, but we basically ignore it */
2005-08-05 12:44:28 +08:00
ACPI_REPORT_ERROR ( ( " Could not override ACPI table, %s \n " ,
acpi_format_exception ( status ) ) ) ;
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
if ( ! new_table ) {
/* No table override */
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_NO_ACPI_TABLES ) ;
2005-04-17 06:20:36 +08:00
}
/*
* We have a new table to override the old one . Get a copy of
* the new one . We know that the new table has a logical pointer .
*/
2005-08-05 12:44:28 +08:00
address . pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING ;
2005-04-17 06:20:36 +08:00
address . pointer . logical = new_table ;
2005-08-05 12:44:28 +08:00
status = acpi_tb_get_this_table ( & address , new_table , table_info ) ;
if ( ACPI_FAILURE ( status ) ) {
ACPI_REPORT_ERROR ( ( " Could not copy override ACPI table, %s \n " ,
acpi_format_exception ( status ) ) ) ;
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/* Copy the table info */
2005-08-05 12:44:28 +08:00
ACPI_REPORT_INFO ( ( " Table [%4.4s] replaced by host OS \n " ,
table_info - > pointer - > signature ) ) ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-17 06:20:36 +08:00
}
/*******************************************************************************
*
* FUNCTION : acpi_tb_get_this_table
*
* PARAMETERS : Address - Address of table to retrieve . Can be
* Logical or Physical
* Header - Header of the table to retrieve
* table_info - Where the table info is returned
*
* RETURN : Status
*
* DESCRIPTION : Get an entire ACPI table . Works in both physical or virtual
* addressing mode . Works with both physical or logical pointers .
* Table is either copied or mapped , depending on the pointer
* type and mode of the processor .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-04-19 10:49:35 +08:00
static acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_this_table ( struct acpi_pointer * address ,
struct acpi_table_header * header ,
struct acpi_table_desc * table_info )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
struct acpi_table_header * full_table = NULL ;
u8 allocation ;
acpi_status status = AE_OK ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_get_this_table " ) ;
2005-04-17 06:20:36 +08:00
/*
2005-04-19 10:49:35 +08:00
* Flags contains the current processor mode ( Virtual or Physical
* addressing ) The pointer_type is either Logical or Physical
2005-04-17 06:20:36 +08:00
*/
switch ( address - > pointer_type ) {
case ACPI_PHYSMODE_PHYSPTR :
case ACPI_LOGMODE_LOGPTR :
/* Pointer matches processor mode, copy the table to a new buffer */
2005-08-05 12:44:28 +08:00
full_table = ACPI_MEM_ALLOCATE ( header - > length ) ;
2005-04-17 06:20:36 +08:00
if ( ! full_table ) {
2005-08-05 12:44:28 +08:00
ACPI_REPORT_ERROR ( ( " Could not allocate table memory for [%4.4s] length %X \n " , header - > signature , header - > length ) ) ;
return_ACPI_STATUS ( AE_NO_MEMORY ) ;
2005-04-17 06:20:36 +08:00
}
/* Copy the entire table (including header) to the local buffer */
2005-08-05 12:44:28 +08:00
ACPI_MEMCPY ( full_table , address - > pointer . logical ,
header - > length ) ;
2005-04-17 06:20:36 +08:00
/* Save allocation type */
allocation = ACPI_MEM_ALLOCATED ;
break ;
case ACPI_LOGMODE_PHYSPTR :
/*
* Just map the table ' s physical memory
* into our address space .
*/
2005-08-05 12:44:28 +08:00
status = acpi_os_map_memory ( address - > pointer . physical ,
( acpi_size ) header - > length ,
( void * ) & full_table ) ;
if ( ACPI_FAILURE ( status ) ) {
ACPI_REPORT_ERROR ( ( " Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X \n " , header - > signature , ACPI_FORMAT_UINT64 ( address - > pointer . physical ) , header - > length ) ) ;
2005-04-17 06:20:36 +08:00
return ( status ) ;
}
/* Save allocation type */
allocation = ACPI_MEM_MAPPED ;
break ;
default :
2006-01-14 05:22:00 +08:00
ACPI_REPORT_ERROR ( ( " Invalid address flags %X \n " ,
address - > pointer_type ) ) ;
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
2005-04-17 06:20:36 +08:00
}
/*
* Validate checksum for _most_ tables ,
* even the ones whose signature we don ' t recognize
*/
if ( table_info - > type ! = ACPI_TABLE_FACS ) {
2005-08-05 12:44:28 +08:00
status = acpi_tb_verify_table_checksum ( full_table ) ;
2005-04-17 06:20:36 +08:00
# if (!ACPI_CHECKSUM_ABORT)
2005-08-05 12:44:28 +08:00
if ( ACPI_FAILURE ( status ) ) {
2005-04-17 06:20:36 +08:00
/* Ignore the error if configuration says so */
status = AE_OK ;
}
# endif
}
/* Return values */
2005-08-05 12:44:28 +08:00
table_info - > pointer = full_table ;
table_info - > length = ( acpi_size ) header - > length ;
table_info - > allocation = allocation ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_INFO ,
" Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p \n " ,
full_table - > signature ,
ACPI_FORMAT_UINT64 ( address - > pointer . physical ) ,
full_table ) ) ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( status ) ;
2005-04-17 06:20:36 +08:00
}
/*******************************************************************************
*
* FUNCTION : acpi_tb_get_table_ptr
*
* PARAMETERS : table_type - one of the defined table types
* Instance - Which table of this type
* table_ptr_loc - pointer to location to place the pointer for
* return
*
* RETURN : Status
*
* DESCRIPTION : This function is called to get the pointer to an ACPI table .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2005-08-05 12:44:28 +08:00
acpi_tb_get_table_ptr ( acpi_table_type table_type ,
u32 instance , struct acpi_table_header * * table_ptr_loc )
2005-04-17 06:20:36 +08:00
{
2005-08-05 12:44:28 +08:00
struct acpi_table_desc * table_desc ;
u32 i ;
2005-04-17 06:20:36 +08:00
2005-08-05 12:44:28 +08:00
ACPI_FUNCTION_TRACE ( " tb_get_table_ptr " ) ;
2005-04-17 06:20:36 +08:00
if ( ! acpi_gbl_DSDT ) {
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_NO_ACPI_TABLES ) ;
2005-04-17 06:20:36 +08:00
}
if ( table_type > ACPI_TABLE_MAX ) {
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
2005-04-17 06:20:36 +08:00
}
/*
* For all table types ( Single / Multiple ) , the first
* instance is always in the list head .
*/
if ( instance = = 1 ) {
/* Get the first */
* table_ptr_loc = NULL ;
if ( acpi_gbl_table_lists [ table_type ] . next ) {
2005-08-05 12:44:28 +08:00
* table_ptr_loc =
acpi_gbl_table_lists [ table_type ] . next - > pointer ;
2005-04-17 06:20:36 +08:00
}
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-17 06:20:36 +08:00
}
2005-04-19 10:49:35 +08:00
/* Check for instance out of range */
2005-04-17 06:20:36 +08:00
if ( instance > acpi_gbl_table_lists [ table_type ] . count ) {
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_NOT_EXIST ) ;
2005-04-17 06:20:36 +08:00
}
/* Walk the list to get the desired table
* Since the if ( Instance = = 1 ) check above checked for the
* first table , setting table_desc equal to the . Next member
* is actually pointing to the second table . Therefore , we
* need to walk from the 2 nd table until we reach the Instance
* that the user is looking for and return its table pointer .
*/
table_desc = acpi_gbl_table_lists [ table_type ] . next ;
for ( i = 2 ; i < instance ; i + + ) {
table_desc = table_desc - > next ;
}
/* We are now pointing to the requested table's descriptor */
* table_ptr_loc = table_desc - > pointer ;
2005-08-05 12:44:28 +08:00
return_ACPI_STATUS ( AE_OK ) ;
2005-04-17 06:20:36 +08:00
}