2018-03-15 02:13:07 +03:00
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2005-04-17 02:20:36 +04:00
/******************************************************************************
*
* Module Name : nsxfname - Public interfaces to the ACPI subsystem
* ACPI Namespace oriented interfaces
*
2022-04-11 21:54:22 +03:00
* Copyright ( C ) 2000 - 2022 , Intel Corp .
2005-04-17 02:20:36 +04:00
*
2018-03-15 02:13:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-04-17 02:20:36 +04:00
2013-10-29 05:29:51 +04:00
# define EXPORT_ACPI_INTERFACES
2005-04-17 02:20:36 +04:00
# include <acpi/acpi.h>
2009-01-09 08:30:03 +03:00
# include "accommon.h"
# include "acnamesp.h"
2009-05-21 06:42:09 +04:00
# include "acparser.h"
# include "amlcode.h"
2005-04-17 02:20:36 +04:00
# define _COMPONENT ACPI_NAMESPACE
2005-08-05 08:44:28 +04:00
ACPI_MODULE_NAME ( " nsxfname " )
2005-04-17 02:20:36 +04:00
2009-06-29 09:39:29 +04:00
/* Local prototypes */
2012-10-31 06:25:24 +04:00
static char * acpi_ns_copy_device_id ( struct acpi_pnp_device_id * dest ,
struct acpi_pnp_device_id * source ,
2009-06-29 09:39:29 +04:00
char * string_area ) ;
2005-04-17 02:20:36 +04:00
/******************************************************************************
*
* FUNCTION : acpi_get_handle
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : parent - Object to search under ( search scope ) .
* pathname - Pointer to an asciiz string containing the
2005-04-19 06:49:35 +04:00
* name
* ret_handle - Where the return handle is returned
2005-04-17 02:20:36 +04:00
*
* RETURN : Status
*
* DESCRIPTION : This routine will search for a caller specified name in the
2012-10-31 06:26:55 +04:00
* name space . The caller can restrict the search region by
* specifying a non NULL parent . The parent value is itself a
2005-04-17 02:20:36 +04:00
* namespace handle .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-29 09:39:29 +04:00
2005-04-17 02:20:36 +04:00
acpi_status
2005-08-05 08:44:28 +04:00
acpi_get_handle ( acpi_handle parent ,
2016-05-05 07:57:53 +03:00
acpi_string pathname , acpi_handle * ret_handle )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
acpi_status status ;
struct acpi_namespace_node * node = NULL ;
struct acpi_namespace_node * prefix_node = NULL ;
2005-04-17 02:20:36 +04:00
2005-08-05 08:44:28 +04:00
ACPI_FUNCTION_ENTRY ( ) ;
2005-04-17 02:20:36 +04:00
/* Parameter Validation */
if ( ! ret_handle | | ! pathname ) {
return ( AE_BAD_PARAMETER ) ;
}
/* Convert a parent handle to a prefix node */
if ( parent ) {
2009-12-11 09:57:00 +03:00
prefix_node = acpi_ns_validate_handle ( parent ) ;
2005-04-17 02:20:36 +04:00
if ( ! prefix_node ) {
return ( AE_BAD_PARAMETER ) ;
}
2007-02-02 19:48:22 +03:00
}
/*
* Valid cases are :
* 1 ) Fully qualified pathname
* 2 ) Parent + Relative pathname
*
* Error for < null Parent + relative path >
*/
2012-12-31 04:05:17 +04:00
if ( ACPI_IS_ROOT_PREFIX ( pathname [ 0 ] ) ) {
2005-04-17 02:20:36 +04:00
2007-02-02 19:48:22 +03:00
/* Pathname is fully qualified (starts with '\') */
/* Special case for root-only, since we can't search for it */
2015-07-01 09:45:11 +03:00
if ( ! strcmp ( pathname , ACPI_NS_ROOT_PATH ) ) {
2007-02-02 19:48:22 +03:00
* ret_handle =
2009-12-11 09:57:00 +03:00
ACPI_CAST_PTR ( acpi_handle , acpi_gbl_root_node ) ;
2007-02-02 19:48:22 +03:00
return ( AE_OK ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-02 19:48:22 +03:00
} else if ( ! prefix_node ) {
2005-04-17 02:20:36 +04:00
2007-02-02 19:48:22 +03:00
/* Relative path with null prefix is disallowed */
2005-04-17 02:20:36 +04:00
2007-02-02 19:48:22 +03:00
return ( AE_BAD_PARAMETER ) ;
2005-04-17 02:20:36 +04:00
}
2007-02-02 19:48:22 +03:00
/* Find the Node and convert to a handle */
2005-04-17 02:20:36 +04:00
2007-02-02 19:48:22 +03:00
status =
acpi_ns_get_node ( prefix_node , pathname , ACPI_NS_NO_UPSEARCH , & node ) ;
2005-08-05 08:44:28 +04:00
if ( ACPI_SUCCESS ( status ) ) {
2009-12-11 09:57:00 +03:00
* ret_handle = ACPI_CAST_PTR ( acpi_handle , node ) ;
2005-04-17 02:20:36 +04:00
}
return ( status ) ;
}
2006-10-03 08:00:00 +04:00
ACPI_EXPORT_SYMBOL ( acpi_get_handle )
2005-04-17 02:20:36 +04:00
/******************************************************************************
*
* FUNCTION : acpi_get_name
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : handle - Handle to be converted to a pathname
2005-04-17 02:20:36 +04:00
* name_type - Full pathname or single segment
2012-07-12 05:40:10 +04:00
* buffer - Buffer for returned path
2005-04-17 02:20:36 +04:00
*
* RETURN : Pointer to a string containing the fully qualified Name .
*
* DESCRIPTION : This routine returns the fully qualified name associated with
2012-10-31 06:26:55 +04:00
* the Handle parameter . This and the acpi_pathname_to_handle are
2005-04-17 02:20:36 +04:00
* complementary functions .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status
2016-05-05 07:57:53 +03:00
acpi_get_name ( acpi_handle handle , u32 name_type , struct acpi_buffer * buffer )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
acpi_status status ;
2005-04-17 02:20:36 +04:00
/* Parameter validation */
if ( name_type > ACPI_NAME_TYPE_MAX ) {
return ( AE_BAD_PARAMETER ) ;
}
2005-08-05 08:44:28 +04:00
status = acpi_ut_validate_buffer ( buffer ) ;
if ( ACPI_FAILURE ( status ) ) {
2005-04-17 02:20:36 +04:00
return ( status ) ;
}
/*
* Wants the single segment ACPI name .
* Validate handle and convert to a namespace Node
*/
2005-08-05 08:44:28 +04:00
status = acpi_ut_acquire_mutex ( ACPI_MTX_NAMESPACE ) ;
if ( ACPI_FAILURE ( status ) ) {
2005-04-17 02:20:36 +04:00
return ( status ) ;
}
2016-11-30 10:20:52 +03:00
if ( name_type = = ACPI_FULL_PATHNAME | |
name_type = = ACPI_FULL_PATHNAME_NO_TRAILING ) {
2005-04-17 02:20:36 +04:00
2016-11-30 10:20:52 +03:00
/* Get the full pathname (From the namespace root) */
2005-04-17 02:20:36 +04:00
2016-11-30 10:20:52 +03:00
status = acpi_ns_handle_to_pathname ( handle , buffer ,
name_type = =
ACPI_FULL_PATHNAME ? FALSE :
TRUE ) ;
} else {
/* Get the single name */
2005-04-17 02:20:36 +04:00
2016-11-30 10:20:52 +03:00
status = acpi_ns_handle_to_name ( handle , buffer ) ;
}
2005-04-17 02:20:36 +04:00
2005-08-05 08:44:28 +04:00
( void ) acpi_ut_release_mutex ( ACPI_MTX_NAMESPACE ) ;
2005-04-17 02:20:36 +04:00
return ( status ) ;
}
2006-10-03 08:00:00 +04:00
ACPI_EXPORT_SYMBOL ( acpi_get_name )
2005-04-17 02:20:36 +04:00
2009-06-29 09:39:29 +04:00
/******************************************************************************
*
* FUNCTION : acpi_ns_copy_device_id
*
2012-10-31 06:25:24 +04:00
* PARAMETERS : dest - Pointer to the destination PNP_DEVICE_ID
* source - Pointer to the source PNP_DEVICE_ID
2009-06-29 09:39:29 +04:00
* string_area - Pointer to where to copy the dest string
*
* RETURN : Pointer to the next string area
*
2012-10-31 06:25:24 +04:00
* DESCRIPTION : Copy a single PNP_DEVICE_ID , including the string data .
2009-06-29 09:39:29 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-10-31 06:25:24 +04:00
static char * acpi_ns_copy_device_id ( struct acpi_pnp_device_id * dest ,
struct acpi_pnp_device_id * source ,
2009-06-29 09:39:29 +04:00
char * string_area )
{
2012-10-31 06:25:24 +04:00
/* Create the destination PNP_DEVICE_ID */
2009-06-29 09:39:29 +04:00
dest - > string = string_area ;
dest - > length = source - > length ;
/* Copy actual string and return a pointer to the next string area */
2015-07-01 09:45:11 +03:00
memcpy ( string_area , source - > string , source - > length ) ;
2009-06-29 09:39:29 +04:00
return ( string_area + source - > length ) ;
}
2005-04-17 02:20:36 +04:00
/******************************************************************************
*
* FUNCTION : acpi_get_object_info
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : handle - Object Handle
2009-06-29 09:39:29 +04:00
* return_buffer - Where the info is returned
2005-04-17 02:20:36 +04:00
*
* RETURN : Status
*
* DESCRIPTION : Returns information about an object as gleaned from the
* namespace node and possibly by running several standard
* control methods ( Such as in the case of a device . )
*
2018-03-15 02:13:03 +03:00
* For Device and Processor objects , run the Device _HID , _UID , _CID ,
2015-12-29 08:55:47 +03:00
* _CLS , _ADR , _sx_w , and _sx_d methods .
2009-06-29 09:39:29 +04:00
*
* Note : Allocates the return buffer , must be freed by the caller .
*
2015-12-29 08:56:14 +03:00
* Note : This interface is intended to be used during the initial device
* discovery namespace traversal . Therefore , no complex methods can be
* executed , especially those that access operation regions . Therefore , do
* not add any additional methods that could cause problems in this area .
2018-03-15 02:13:03 +03:00
* Because of this reason support for the following methods has been removed :
* 1 ) _SUB method was removed ( 11 / 2015 )
* 2 ) _STA method was removed ( 02 / 2018 )
2015-12-29 08:56:14 +03:00
*
2005-04-17 02:20:36 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-06-29 09:39:29 +04:00
2005-04-17 02:20:36 +04:00
acpi_status
2009-06-29 09:39:29 +04:00
acpi_get_object_info ( acpi_handle handle ,
struct acpi_device_info * * return_buffer )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct acpi_namespace_node * node ;
struct acpi_device_info * info ;
2012-10-31 06:25:24 +04:00
struct acpi_pnp_device_id_list * cid_list = NULL ;
struct acpi_pnp_device_id * hid = NULL ;
struct acpi_pnp_device_id * uid = NULL ;
2015-07-01 09:44:04 +03:00
struct acpi_pnp_device_id * cls = NULL ;
2009-06-29 09:39:29 +04:00
char * next_id_string ;
acpi_object_type type ;
acpi_name name ;
u8 param_count = 0 ;
2015-07-01 09:44:04 +03:00
u16 valid = 0 ;
2009-06-29 09:39:29 +04:00
u32 info_size ;
u32 i ;
acpi_status status ;
2005-04-17 02:20:36 +04:00
/* Parameter validation */
2009-06-29 09:39:29 +04:00
if ( ! handle | | ! return_buffer ) {
2005-04-17 02:20:36 +04:00
return ( AE_BAD_PARAMETER ) ;
}
2005-08-05 08:44:28 +04:00
status = acpi_ut_acquire_mutex ( ACPI_MTX_NAMESPACE ) ;
if ( ACPI_FAILURE ( status ) ) {
2012-12-19 09:38:36 +04:00
return ( status ) ;
2005-04-17 02:20:36 +04:00
}
2009-12-11 09:57:00 +03:00
node = acpi_ns_validate_handle ( handle ) ;
2005-04-17 02:20:36 +04:00
if ( ! node ) {
2005-08-05 08:44:28 +04:00
( void ) acpi_ut_release_mutex ( ACPI_MTX_NAMESPACE ) ;
2009-06-29 09:39:29 +04:00
return ( AE_BAD_PARAMETER ) ;
2005-04-17 02:20:36 +04:00
}
2009-06-29 09:39:29 +04:00
/* Get the namespace node data while the namespace is locked */
2005-04-17 02:20:36 +04:00
2009-06-29 09:39:29 +04:00
info_size = sizeof ( struct acpi_device_info ) ;
type = node - > type ;
name = node - > name . integer ;
2005-04-17 02:20:36 +04:00
2008-07-04 06:53:58 +04:00
if ( node - > type = = ACPI_TYPE_METHOD ) {
2009-06-29 09:39:29 +04:00
param_count = node - > object - > method . param_count ;
2008-07-04 06:53:58 +04:00
}
2005-08-05 08:44:28 +04:00
status = acpi_ut_release_mutex ( ACPI_MTX_NAMESPACE ) ;
if ( ACPI_FAILURE ( status ) ) {
2009-06-29 09:39:29 +04:00
return ( status ) ;
2005-04-17 02:20:36 +04:00
}
2009-06-29 09:39:29 +04:00
if ( ( type = = ACPI_TYPE_DEVICE ) | | ( type = = ACPI_TYPE_PROCESSOR ) ) {
2005-04-17 02:20:36 +04:00
/*
2009-06-29 09:39:29 +04:00
* Get extra info for ACPI Device / Processor objects only :
2015-12-29 08:55:47 +03:00
* Run the Device _HID , _UID , _CLS , and _CID methods .
2005-04-17 02:20:36 +04:00
*
* Note : none of these methods are required , so they may or may
2009-06-29 09:39:29 +04:00
* not be present for this device . The Info - > Valid bitfield is used
* to indicate which methods were found and run successfully .
2005-04-17 02:20:36 +04:00
*/
/* Execute the Device._HID method */
2009-06-29 09:39:29 +04:00
status = acpi_ut_execute_HID ( node , & hid ) ;
2005-08-05 08:44:28 +04:00
if ( ACPI_SUCCESS ( status ) ) {
2009-06-29 09:39:29 +04:00
info_size + = hid - > length ;
valid | = ACPI_VALID_HID ;
2005-04-17 02:20:36 +04:00
}
/* Execute the Device._UID method */
2009-06-29 09:39:29 +04:00
status = acpi_ut_execute_UID ( node , & uid ) ;
2005-08-05 08:44:28 +04:00
if ( ACPI_SUCCESS ( status ) ) {
2009-06-29 09:39:29 +04:00
info_size + = uid - > length ;
valid | = ACPI_VALID_UID ;
2005-04-17 02:20:36 +04:00
}
/* Execute the Device._CID method */
2005-08-05 08:44:28 +04:00
status = acpi_ut_execute_CID ( node , & cid_list ) ;
if ( ACPI_SUCCESS ( status ) ) {
2009-06-29 09:39:29 +04:00
/* Add size of CID strings and CID pointer array */
info_size + =
( cid_list - > list_size -
2012-10-31 06:25:24 +04:00
sizeof ( struct acpi_pnp_device_id_list ) ) ;
2009-06-29 09:39:29 +04:00
valid | = ACPI_VALID_CID ;
2005-04-17 02:20:36 +04:00
}
2015-07-01 09:44:04 +03:00
/* Execute the Device._CLS method */
status = acpi_ut_execute_CLS ( node , & cls ) ;
if ( ACPI_SUCCESS ( status ) ) {
info_size + = cls - > length ;
valid | = ACPI_VALID_CLS ;
}
2009-06-29 09:39:29 +04:00
}
/*
* Now that we have the variable - length data , we can allocate the
* return buffer
*/
info = ACPI_ALLOCATE_ZEROED ( info_size ) ;
if ( ! info ) {
status = AE_NO_MEMORY ;
goto cleanup ;
}
/* Get the fixed-length data */
if ( ( type = = ACPI_TYPE_DEVICE ) | | ( type = = ACPI_TYPE_PROCESSOR ) ) {
/*
* Get extra info for ACPI Device / Processor objects only :
2018-03-15 02:13:03 +03:00
* Run the _ADR and , sx_w , and _sx_d methods .
2009-06-29 09:39:29 +04:00
*
2013-07-17 05:48:15 +04:00
* Notes : none of these methods are required , so they may or may
2009-06-29 09:39:29 +04:00
* not be present for this device . The Info - > Valid bitfield is used
* to indicate which methods were found and run successfully .
*/
2005-04-17 02:20:36 +04:00
/* Execute the Device._ADR method */
2005-08-05 08:44:28 +04:00
status = acpi_ut_evaluate_numeric_object ( METHOD_NAME__ADR , node ,
& info - > address ) ;
if ( ACPI_SUCCESS ( status ) ) {
2009-06-29 09:39:29 +04:00
valid | = ACPI_VALID_ADR ;
}
/* Execute the Device._sx_w methods */
status = acpi_ut_execute_power_methods ( node ,
acpi_gbl_lowest_dstate_names ,
ACPI_NUM_sx_w_METHODS ,
info - > lowest_dstates ) ;
if ( ACPI_SUCCESS ( status ) ) {
valid | = ACPI_VALID_SXWS ;
2005-04-17 02:20:36 +04:00
}
/* Execute the Device._sx_d methods */
2009-06-29 09:39:29 +04:00
status = acpi_ut_execute_power_methods ( node ,
acpi_gbl_highest_dstate_names ,
ACPI_NUM_sx_d_METHODS ,
info - > highest_dstates ) ;
2005-08-05 08:44:28 +04:00
if ( ACPI_SUCCESS ( status ) ) {
2009-06-29 09:39:29 +04:00
valid | = ACPI_VALID_SXDS ;
2005-04-17 02:20:36 +04:00
}
}
2009-06-29 09:39:29 +04:00
/*
* Create a pointer to the string area of the return buffer .
* Point to the end of the base struct acpi_device_info structure .
*/
next_id_string = ACPI_CAST_PTR ( char , info - > compatible_id_list . ids ) ;
if ( cid_list ) {
2005-04-17 02:20:36 +04:00
2012-10-31 06:25:24 +04:00
/* Point past the CID PNP_DEVICE_ID array */
2009-06-29 09:39:29 +04:00
next_id_string + =
2016-05-05 07:57:53 +03:00
( ( acpi_size ) cid_list - > count *
2012-10-31 06:25:24 +04:00
sizeof ( struct acpi_pnp_device_id ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-06-29 09:39:29 +04:00
/*
2015-12-29 08:55:47 +03:00
* Copy the HID , UID , and CIDs to the return buffer . The variable - length
* strings are copied to the reserved area at the end of the buffer .
2009-06-29 09:39:29 +04:00
*
* For HID and CID , check if the ID is a PCI Root Bridge .
*/
if ( hid ) {
next_id_string = acpi_ns_copy_device_id ( & info - > hardware_id ,
hid , next_id_string ) ;
if ( acpi_ut_is_pci_root_bridge ( hid - > string ) ) {
info - > flags | = ACPI_PCI_ROOT_BRIDGE ;
}
}
2005-04-17 02:20:36 +04:00
2009-06-29 09:39:29 +04:00
if ( uid ) {
next_id_string = acpi_ns_copy_device_id ( & info - > unique_id ,
uid , next_id_string ) ;
}
2005-04-17 02:20:36 +04:00
if ( cid_list ) {
2009-06-29 09:39:29 +04:00
info - > compatible_id_list . count = cid_list - > count ;
info - > compatible_id_list . list_size = cid_list - > list_size ;
/* Copy each CID */
for ( i = 0 ; i < cid_list - > count ; i + + ) {
next_id_string =
acpi_ns_copy_device_id ( & info - > compatible_id_list .
ids [ i ] , & cid_list - > ids [ i ] ,
next_id_string ) ;
if ( acpi_ut_is_pci_root_bridge ( cid_list - > ids [ i ] . string ) ) {
info - > flags | = ACPI_PCI_ROOT_BRIDGE ;
}
}
2005-04-17 02:20:36 +04:00
}
2015-07-01 09:44:04 +03:00
if ( cls ) {
2019-10-26 00:36:51 +03:00
( void ) acpi_ns_copy_device_id ( & info - > class_code ,
cls , next_id_string ) ;
2015-07-01 09:44:04 +03:00
}
2009-06-29 09:39:29 +04:00
/* Copy the fixed-length data */
info - > info_size = info_size ;
info - > type = type ;
info - > name = name ;
info - > param_count = param_count ;
info - > valid = valid ;
* return_buffer = info ;
status = AE_OK ;
2013-10-29 05:30:02 +04:00
cleanup :
2009-06-29 09:39:29 +04:00
if ( hid ) {
ACPI_FREE ( hid ) ;
}
if ( uid ) {
ACPI_FREE ( uid ) ;
}
2005-04-17 02:20:36 +04:00
if ( cid_list ) {
2006-10-03 08:00:00 +04:00
ACPI_FREE ( cid_list ) ;
2015-07-01 09:44:04 +03:00
}
if ( cls ) {
ACPI_FREE ( cls ) ;
2005-04-17 02:20:36 +04:00
}
return ( status ) ;
}
2006-10-03 08:00:00 +04:00
ACPI_EXPORT_SYMBOL ( acpi_get_object_info )
2009-05-21 06:42:09 +04:00
/******************************************************************************
*
* FUNCTION : acpi_install_method
*
2012-07-12 05:40:10 +04:00
* PARAMETERS : buffer - An ACPI table containing one control method
2009-05-21 06:42:09 +04:00
*
* RETURN : Status
*
* DESCRIPTION : Install a control method into the namespace . If the method
* name already exists in the namespace , it is overwritten . The
* input buffer must contain a valid DSDT or SSDT containing a
* single control method .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
acpi_status acpi_install_method ( u8 * buffer )
{
struct acpi_table_header * table =
ACPI_CAST_PTR ( struct acpi_table_header , buffer ) ;
u8 * aml_buffer ;
u8 * aml_start ;
char * path ;
struct acpi_namespace_node * node ;
union acpi_operand_object * method_obj ;
struct acpi_parse_state parser_state ;
u32 aml_length ;
u16 opcode ;
u8 method_flags ;
acpi_status status ;
/* Parameter validation */
if ( ! buffer ) {
2012-12-19 09:37:21 +04:00
return ( AE_BAD_PARAMETER ) ;
2009-05-21 06:42:09 +04:00
}
/* Table must be a DSDT or SSDT */
2019-04-08 23:42:24 +03:00
if ( ! ACPI_COMPARE_NAMESEG ( table - > signature , ACPI_SIG_DSDT ) & &
! ACPI_COMPARE_NAMESEG ( table - > signature , ACPI_SIG_SSDT ) ) {
2012-12-19 09:37:21 +04:00
return ( AE_BAD_HEADER ) ;
2009-05-21 06:42:09 +04:00
}
/* First AML opcode in the table must be a control method */
parser_state . aml = buffer + sizeof ( struct acpi_table_header ) ;
opcode = acpi_ps_peek_opcode ( & parser_state ) ;
if ( opcode ! = AML_METHOD_OP ) {
2012-12-19 09:37:21 +04:00
return ( AE_BAD_PARAMETER ) ;
2009-05-21 06:42:09 +04:00
}
/* Extract method information from the raw AML */
parser_state . aml + = acpi_ps_get_opcode_size ( opcode ) ;
parser_state . pkg_end = acpi_ps_get_next_package_end ( & parser_state ) ;
path = acpi_ps_get_next_namestring ( & parser_state ) ;
2015-12-29 08:54:36 +03:00
2009-05-21 06:42:09 +04:00
method_flags = * parser_state . aml + + ;
aml_start = parser_state . aml ;
2020-02-14 21:48:00 +03:00
aml_length = ( u32 ) ACPI_PTR_DIFF ( parser_state . pkg_end , aml_start ) ;
2009-05-21 06:42:09 +04:00
/*
* Allocate resources up - front . We don ' t want to have to delete a new
* node from the namespace if we cannot allocate memory .
*/
aml_buffer = ACPI_ALLOCATE ( aml_length ) ;
if ( ! aml_buffer ) {
2012-12-19 09:37:21 +04:00
return ( AE_NO_MEMORY ) ;
2009-05-21 06:42:09 +04:00
}
method_obj = acpi_ut_create_internal_object ( ACPI_TYPE_METHOD ) ;
if ( ! method_obj ) {
ACPI_FREE ( aml_buffer ) ;
2012-12-19 09:37:21 +04:00
return ( AE_NO_MEMORY ) ;
2009-05-21 06:42:09 +04:00
}
/* Lock namespace for acpi_ns_lookup, we may be creating a new node */
status = acpi_ut_acquire_mutex ( ACPI_MTX_NAMESPACE ) ;
if ( ACPI_FAILURE ( status ) ) {
goto error_exit ;
}
/* The lookup either returns an existing node or creates a new one */
status =
acpi_ns_lookup ( NULL , path , ACPI_TYPE_METHOD , ACPI_IMODE_LOAD_PASS1 ,
ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND ,
NULL , & node ) ;
( void ) acpi_ut_release_mutex ( ACPI_MTX_NAMESPACE ) ;
if ( ACPI_FAILURE ( status ) ) { /* ns_lookup */
if ( status ! = AE_ALREADY_EXISTS ) {
goto error_exit ;
}
/* Node existed previously, make sure it is a method node */
if ( node - > type ! = ACPI_TYPE_METHOD ) {
status = AE_TYPE ;
goto error_exit ;
}
}
/* Copy the method AML to the local buffer */
2015-07-01 09:45:11 +03:00
memcpy ( aml_buffer , aml_start , aml_length ) ;
2009-05-21 06:42:09 +04:00
/* Initialize the method object with the new method's information */
method_obj - > method . aml_start = aml_buffer ;
method_obj - > method . aml_length = aml_length ;
method_obj - > method . param_count = ( u8 )
( method_flags & AML_METHOD_ARG_COUNT ) ;
if ( method_flags & AML_METHOD_SERIALIZED ) {
2011-01-12 04:19:43 +03:00
method_obj - > method . info_flags = ACPI_METHOD_SERIALIZED ;
2009-05-21 06:42:09 +04:00
method_obj - > method . sync_level = ( u8 )
( ( method_flags & AML_METHOD_SYNC_LEVEL ) > > 4 ) ;
}
/*
* Now that it is complete , we can attach the new method object to
* the method Node ( detaches / deletes any existing object )
*/
status = acpi_ns_attach_object ( node , method_obj , ACPI_TYPE_METHOD ) ;
/*
* Flag indicates AML buffer is dynamic , must be deleted later .
* Must be set only after attach above .
*/
node - > flags | = ANOBJ_ALLOCATED_BUFFER ;
/* Remove local reference to the method object */
acpi_ut_remove_reference ( method_obj ) ;
2012-12-19 09:37:21 +04:00
return ( status ) ;
2009-05-21 06:42:09 +04:00
error_exit :
ACPI_FREE ( aml_buffer ) ;
ACPI_FREE ( method_obj ) ;
2012-12-19 09:37:21 +04:00
return ( status ) ;
2009-05-21 06:42:09 +04:00
}
ACPI_EXPORT_SYMBOL ( acpi_install_method )