2005-11-02 00:00:00 -05:00
/*******************************************************************************
*
* Module Name : utresrc - Resource managment utilities
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2006-01-13 16:22:00 -05:00
* Copyright ( C ) 2000 - 2006 , R . Byron Moore
2005-11-02 00:00:00 -05: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/amlresrc.h>
# define _COMPONENT ACPI_UTILITIES
ACPI_MODULE_NAME ( " utmisc " )
2005-12-16 17:05:00 -05:00
# if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER)
/*
* Strings used to decode resource descriptors .
* Used by both the disasssembler and the debugger resource dump routines
*/
const char * acpi_gbl_BMdecode [ 2 ] = {
" not_bus_master " ,
" bus_master "
} ;
const char * acpi_gbl_config_decode [ 4 ] = {
" 0 - Good Configuration " ,
" 1 - Acceptable Configuration " ,
" 2 - Suboptimal Configuration " ,
" 3 - ***Invalid Configuration*** " ,
} ;
const char * acpi_gbl_consume_decode [ 2 ] = {
" resource_producer " ,
" resource_consumer "
} ;
const char * acpi_gbl_DECdecode [ 2 ] = {
" pos_decode " ,
" sub_decode "
} ;
const char * acpi_gbl_HEdecode [ 2 ] = {
" Level " ,
" Edge "
} ;
const char * acpi_gbl_io_decode [ 2 ] = {
" Decode10 " ,
" Decode16 "
} ;
const char * acpi_gbl_LLdecode [ 2 ] = {
" active_high " ,
" active_low "
} ;
const char * acpi_gbl_max_decode [ 2 ] = {
" max_not_fixed " ,
" max_fixed "
} ;
const char * acpi_gbl_MEMdecode [ 4 ] = {
" non_cacheable " ,
" Cacheable " ,
" write_combining " ,
" Prefetchable "
} ;
const char * acpi_gbl_min_decode [ 2 ] = {
" min_not_fixed " ,
" min_fixed "
} ;
const char * acpi_gbl_MTPdecode [ 4 ] = {
" address_range_memory " ,
" address_range_reserved " ,
" address_range_aCPI " ,
" address_range_nVS "
} ;
const char * acpi_gbl_RNGdecode [ 4 ] = {
" invalid_ranges " ,
" non_iSAonly_ranges " ,
" ISAonly_ranges " ,
" entire_range "
} ;
const char * acpi_gbl_RWdecode [ 2 ] = {
" read_only " ,
" read_write "
} ;
const char * acpi_gbl_SHRdecode [ 2 ] = {
" Exclusive " ,
" Shared "
} ;
const char * acpi_gbl_SIZdecode [ 4 ] = {
" Transfer8 " ,
" Transfer8_16 " ,
" Transfer16 " ,
" invalid_size "
} ;
const char * acpi_gbl_TRSdecode [ 2 ] = {
" dense_translation " ,
" sparse_translation "
} ;
const char * acpi_gbl_TTPdecode [ 2 ] = {
" type_static " ,
" type_translation "
} ;
const char * acpi_gbl_TYPdecode [ 4 ] = {
" Compatibility " ,
" type_a " ,
" type_b " ,
" type_f "
} ;
# endif
2005-11-02 00:00:00 -05:00
/*
* Base sizes of the raw AML resource descriptors , indexed by resource type .
* Zero indicates a reserved ( and therefore invalid ) resource type .
*/
const u8 acpi_gbl_resource_aml_sizes [ ] = {
/* Small descriptors */
0 ,
0 ,
0 ,
0 ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_irq ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_dma ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_start_dependent ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_end_dependent ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_io ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_fixed_io ) ,
0 ,
0 ,
0 ,
0 ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_vendor_small ) ,
ACPI_AML_SIZE_SMALL ( struct aml_resource_end_tag ) ,
/* Large descriptors */
0 ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_memory24 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_generic_register ) ,
0 ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_vendor_large ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_memory32 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_fixed_memory32 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_address32 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_address16 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_extended_irq ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_address64 ) ,
ACPI_AML_SIZE_LARGE ( struct aml_resource_extended_address64 )
} ;
/*
* Resource types , used to validate the resource length field .
* The length of fixed - length types must match exactly , variable
* lengths must meet the minimum required length , etc .
* Zero indicates a reserved ( and therefore invalid ) resource type .
*/
static const u8 acpi_gbl_resource_types [ ] = {
/* Small descriptors */
0 ,
0 ,
0 ,
0 ,
ACPI_SMALL_VARIABLE_LENGTH ,
ACPI_FIXED_LENGTH ,
ACPI_SMALL_VARIABLE_LENGTH ,
ACPI_FIXED_LENGTH ,
ACPI_FIXED_LENGTH ,
ACPI_FIXED_LENGTH ,
0 ,
0 ,
0 ,
0 ,
ACPI_VARIABLE_LENGTH ,
ACPI_FIXED_LENGTH ,
/* Large descriptors */
0 ,
ACPI_FIXED_LENGTH ,
ACPI_FIXED_LENGTH ,
0 ,
ACPI_VARIABLE_LENGTH ,
ACPI_FIXED_LENGTH ,
ACPI_FIXED_LENGTH ,
ACPI_VARIABLE_LENGTH ,
ACPI_VARIABLE_LENGTH ,
ACPI_VARIABLE_LENGTH ,
ACPI_VARIABLE_LENGTH ,
ACPI_FIXED_LENGTH
} ;
/*******************************************************************************
*
* FUNCTION : acpi_ut_validate_resource
*
* PARAMETERS : Aml - Pointer to the raw AML resource descriptor
* return_index - Where the resource index is returned . NULL
* if the index is not required .
*
* RETURN : Status , and optionally the Index into the global resource tables
*
* DESCRIPTION : Validate an AML resource descriptor by checking the Resource
* Type and Resource Length . Returns an index into the global
* resource information / dispatch tables for later use .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status acpi_ut_validate_resource ( void * aml , u8 * return_index )
{
u8 resource_type ;
u8 resource_index ;
acpi_rs_length resource_length ;
acpi_rs_length minimum_resource_length ;
ACPI_FUNCTION_ENTRY ( ) ;
/*
* 1 ) Validate the resource_type field ( Byte 0 )
*/
2005-11-17 13:07:00 -05:00
resource_type = ACPI_GET8 ( aml ) ;
2005-11-02 00:00:00 -05:00
/*
* Byte 0 contains the descriptor name ( Resource Type )
* Examine the large / small bit in the resource header
*/
if ( resource_type & ACPI_RESOURCE_NAME_LARGE ) {
/* Verify the large resource type (name) against the max */
if ( resource_type > ACPI_RESOURCE_NAME_LARGE_MAX ) {
return ( AE_AML_INVALID_RESOURCE_TYPE ) ;
}
/*
* Large Resource Type - - bits 6 : 0 contain the name
* Translate range 0x80 - 0x8B to index range 0x10 - 0x1B
*/
resource_index = ( u8 ) ( resource_type - 0x70 ) ;
} else {
/*
* Small Resource Type - - bits 6 : 3 contain the name
* Shift range to index range 0x00 - 0x0F
*/
resource_index = ( u8 )
( ( resource_type & ACPI_RESOURCE_NAME_SMALL_MASK ) > > 3 ) ;
}
/* Check validity of the resource type, zero indicates name is invalid */
if ( ! acpi_gbl_resource_types [ resource_index ] ) {
return ( AE_AML_INVALID_RESOURCE_TYPE ) ;
}
/*
* 2 ) Validate the resource_length field . This ensures that the length
* is at least reasonable , and guarantees that it is non - zero .
*/
resource_length = acpi_ut_get_resource_length ( aml ) ;
minimum_resource_length = acpi_gbl_resource_aml_sizes [ resource_index ] ;
/* Validate based upon the type of resource - fixed length or variable */
switch ( acpi_gbl_resource_types [ resource_index ] ) {
case ACPI_FIXED_LENGTH :
/* Fixed length resource, length must match exactly */
if ( resource_length ! = minimum_resource_length ) {
return ( AE_AML_BAD_RESOURCE_LENGTH ) ;
}
break ;
case ACPI_VARIABLE_LENGTH :
/* Variable length resource, length must be at least the minimum */
if ( resource_length < minimum_resource_length ) {
return ( AE_AML_BAD_RESOURCE_LENGTH ) ;
}
break ;
case ACPI_SMALL_VARIABLE_LENGTH :
/* Small variable length resource, length can be (Min) or (Min-1) */
if ( ( resource_length > minimum_resource_length ) | |
( resource_length < ( minimum_resource_length - 1 ) ) ) {
return ( AE_AML_BAD_RESOURCE_LENGTH ) ;
}
break ;
default :
/* Shouldn't happen (because of validation earlier), but be sure */
return ( AE_AML_INVALID_RESOURCE_TYPE ) ;
}
/* Optionally return the resource table index */
if ( return_index ) {
* return_index = resource_index ;
}
return ( AE_OK ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_get_resource_type
*
* PARAMETERS : Aml - Pointer to the raw AML resource descriptor
*
* RETURN : The Resource Type with no extraneous bits ( except the
* Large / Small descriptor bit - - this is left alone )
*
* DESCRIPTION : Extract the Resource Type / Name from the first byte of
* a resource descriptor .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
u8 acpi_ut_get_resource_type ( void * aml )
{
ACPI_FUNCTION_ENTRY ( ) ;
/*
* Byte 0 contains the descriptor name ( Resource Type )
* Examine the large / small bit in the resource header
*/
2005-11-17 13:07:00 -05:00
if ( ACPI_GET8 ( aml ) & ACPI_RESOURCE_NAME_LARGE ) {
2005-11-02 00:00:00 -05:00
/* Large Resource Type -- bits 6:0 contain the name */
2005-11-17 13:07:00 -05:00
return ( ACPI_GET8 ( aml ) ) ;
2005-11-02 00:00:00 -05:00
} else {
/* Small Resource Type -- bits 6:3 contain the name */
2005-11-17 13:07:00 -05:00
return ( ( u8 ) ( ACPI_GET8 ( aml ) & ACPI_RESOURCE_NAME_SMALL_MASK ) ) ;
2005-11-02 00:00:00 -05:00
}
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_get_resource_length
*
* PARAMETERS : Aml - Pointer to the raw AML resource descriptor
*
* RETURN : Byte Length
*
* DESCRIPTION : Get the " Resource Length " of a raw AML descriptor . By
* definition , this does not include the size of the descriptor
* header or the length field itself .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
u16 acpi_ut_get_resource_length ( void * aml )
{
acpi_rs_length resource_length ;
ACPI_FUNCTION_ENTRY ( ) ;
/*
* Byte 0 contains the descriptor name ( Resource Type )
* Examine the large / small bit in the resource header
*/
2005-11-17 13:07:00 -05:00
if ( ACPI_GET8 ( aml ) & ACPI_RESOURCE_NAME_LARGE ) {
2005-11-02 00:00:00 -05:00
/* Large Resource type -- bytes 1-2 contain the 16-bit length */
2005-11-17 13:07:00 -05:00
ACPI_MOVE_16_TO_16 ( & resource_length , ACPI_ADD_PTR ( u8 , aml , 1 ) ) ;
2005-11-02 00:00:00 -05:00
} else {
/* Small Resource type -- bits 2:0 of byte 0 contain the length */
2005-11-17 13:07:00 -05:00
resource_length = ( u16 ) ( ACPI_GET8 ( aml ) &
2005-11-02 00:00:00 -05:00
ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK ) ;
}
return ( resource_length ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_get_resource_header_length
*
* PARAMETERS : Aml - Pointer to the raw AML resource descriptor
*
* RETURN : Length of the AML header ( depends on large / small descriptor )
*
* DESCRIPTION : Get the length of the header for this resource .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
u8 acpi_ut_get_resource_header_length ( void * aml )
{
ACPI_FUNCTION_ENTRY ( ) ;
/* Examine the large/small bit in the resource header */
2005-11-17 13:07:00 -05:00
if ( ACPI_GET8 ( aml ) & ACPI_RESOURCE_NAME_LARGE ) {
2005-11-02 00:00:00 -05:00
return ( sizeof ( struct aml_resource_large_header ) ) ;
} else {
return ( sizeof ( struct aml_resource_small_header ) ) ;
}
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_get_descriptor_length
*
* PARAMETERS : Aml - Pointer to the raw AML resource descriptor
*
* RETURN : Byte length
*
* DESCRIPTION : Get the total byte length of a raw AML descriptor , including the
* length of the descriptor header and the length field itself .
* Used to walk descriptor lists .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
u32 acpi_ut_get_descriptor_length ( void * aml )
{
ACPI_FUNCTION_ENTRY ( ) ;
/*
* Get the Resource Length ( does not include header length ) and add
* the header length ( depends on if this is a small or large resource )
*/
return ( acpi_ut_get_resource_length ( aml ) +
acpi_ut_get_resource_header_length ( aml ) ) ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ut_get_resource_end_tag
*
* PARAMETERS : obj_desc - The resource template buffer object
2005-11-17 13:07:00 -05:00
* end_tag - Where the pointer to the end_tag is returned
2005-11-02 00:00:00 -05:00
*
2005-11-17 13:07:00 -05:00
* RETURN : Status , pointer to the end tag
2005-11-02 00:00:00 -05:00
*
* DESCRIPTION : Find the end_tag resource descriptor in an AML resource template
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
acpi_ut_get_resource_end_tag ( union acpi_operand_object * obj_desc ,
u8 * * end_tag )
{
acpi_status status ;
u8 * aml ;
u8 * end_aml ;
ACPI_FUNCTION_TRACE ( " ut_get_resource_end_tag " ) ;
/* Get start and end pointers */
aml = obj_desc - > buffer . pointer ;
end_aml = aml + obj_desc - > buffer . length ;
/* Walk the resource template, one descriptor per iteration */
while ( aml < end_aml ) {
/* Validate the Resource Type and Resource Length */
status = acpi_ut_validate_resource ( aml , NULL ) ;
if ( ACPI_FAILURE ( status ) ) {
return_ACPI_STATUS ( status ) ;
}
/* end_tag resource indicates the end of the resource template */
if ( acpi_ut_get_resource_type ( aml ) = =
ACPI_RESOURCE_NAME_END_TAG ) {
/* Return the pointer to the end_tag */
* end_tag = aml ;
return_ACPI_STATUS ( AE_OK ) ;
}
/*
* Point to the next resource descriptor in the AML buffer . The
* descriptor length is guaranteed to be non - zero by resource
* validation above .
*/
aml + = acpi_ut_get_descriptor_length ( aml ) ;
}
/* Did not find an end_tag resource descriptor */
return_ACPI_STATUS ( AE_AML_NO_RESOURCE_END_TAG ) ;
}