195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 295b482a8SLen Brown /****************************************************************************** 395b482a8SLen Brown * 495b482a8SLen Brown * Module Name: nsxfname - Public interfaces to the ACPI subsystem 595b482a8SLen Brown * ACPI Namespace oriented interfaces 695b482a8SLen Brown * 7*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp. 895b482a8SLen Brown * 995857638SErik Schmauss *****************************************************************************/ 1095b482a8SLen Brown 11839e928fSLv Zheng #define EXPORT_ACPI_INTERFACES 12839e928fSLv Zheng 1395b482a8SLen Brown #include <acpi/acpi.h> 14e2f7a777SLen Brown #include "accommon.h" 15e2f7a777SLen Brown #include "acnamesp.h" 16b2f7ddcfSLin Ming #include "acparser.h" 17b2f7ddcfSLin Ming #include "amlcode.h" 1895b482a8SLen Brown 1995b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE 2095b482a8SLen Brown ACPI_MODULE_NAME("nsxfname") 2195b482a8SLen Brown 2215b8dd53SBob Moore /* Local prototypes */ 2378e25fefSLv Zheng static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, 2478e25fefSLv Zheng struct acpi_pnp_device_id *source, 2515b8dd53SBob Moore char *string_area); 2615b8dd53SBob Moore 2795b482a8SLen Brown /****************************************************************************** 2895b482a8SLen Brown * 2995b482a8SLen Brown * FUNCTION: acpi_get_handle 3095b482a8SLen Brown * 31ba494beeSBob Moore * PARAMETERS: parent - Object to search under (search scope). 32ba494beeSBob Moore * pathname - Pointer to an asciiz string containing the 3395b482a8SLen Brown * name 3495b482a8SLen Brown * ret_handle - Where the return handle is returned 3595b482a8SLen Brown * 3695b482a8SLen Brown * RETURN: Status 3795b482a8SLen Brown * 3895b482a8SLen Brown * DESCRIPTION: This routine will search for a caller specified name in the 3995b482a8SLen Brown * name space. The caller can restrict the search region by 4095b482a8SLen Brown * specifying a non NULL parent. The parent value is itself a 4195b482a8SLen Brown * namespace handle. 4295b482a8SLen Brown * 4395b482a8SLen Brown ******************************************************************************/ 4415b8dd53SBob Moore 4595b482a8SLen Brown acpi_status 4695b482a8SLen Brown acpi_get_handle(acpi_handle parent, 4791fdb91cSSakari Ailus const char *pathname, acpi_handle *ret_handle) 4895b482a8SLen Brown { 4995b482a8SLen Brown acpi_status status; 5095b482a8SLen Brown struct acpi_namespace_node *node = NULL; 5195b482a8SLen Brown struct acpi_namespace_node *prefix_node = NULL; 5295b482a8SLen Brown 5395b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 5495b482a8SLen Brown 5595b482a8SLen Brown /* Parameter Validation */ 5695b482a8SLen Brown 5795b482a8SLen Brown if (!ret_handle || !pathname) { 5895b482a8SLen Brown return (AE_BAD_PARAMETER); 5995b482a8SLen Brown } 6095b482a8SLen Brown 6195b482a8SLen Brown /* Convert a parent handle to a prefix node */ 6295b482a8SLen Brown 6395b482a8SLen Brown if (parent) { 64f24b664dSBob Moore prefix_node = acpi_ns_validate_handle(parent); 6595b482a8SLen Brown if (!prefix_node) { 6695b482a8SLen Brown return (AE_BAD_PARAMETER); 6795b482a8SLen Brown } 6895b482a8SLen Brown } 6995b482a8SLen Brown 7095b482a8SLen Brown /* 7195b482a8SLen Brown * Valid cases are: 7295b482a8SLen Brown * 1) Fully qualified pathname 7395b482a8SLen Brown * 2) Parent + Relative pathname 7495b482a8SLen Brown * 7595b482a8SLen Brown * Error for <null Parent + relative path> 7695b482a8SLen Brown */ 7704a81dceSBob Moore if (ACPI_IS_ROOT_PREFIX(pathname[0])) { 7895b482a8SLen Brown 7995b482a8SLen Brown /* Pathname is fully qualified (starts with '\') */ 8095b482a8SLen Brown 8195b482a8SLen Brown /* Special case for root-only, since we can't search for it */ 8295b482a8SLen Brown 834fa4616eSBob Moore if (!strcmp(pathname, ACPI_NS_ROOT_PATH)) { 8495b482a8SLen Brown *ret_handle = 85f24b664dSBob Moore ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node); 8695b482a8SLen Brown return (AE_OK); 8795b482a8SLen Brown } 8895b482a8SLen Brown } else if (!prefix_node) { 8995b482a8SLen Brown 9095b482a8SLen Brown /* Relative path with null prefix is disallowed */ 9195b482a8SLen Brown 9295b482a8SLen Brown return (AE_BAD_PARAMETER); 9395b482a8SLen Brown } 9495b482a8SLen Brown 9595b482a8SLen Brown /* Find the Node and convert to a handle */ 9695b482a8SLen Brown 9795b482a8SLen Brown status = 9895b482a8SLen Brown acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); 9995b482a8SLen Brown if (ACPI_SUCCESS(status)) { 100f24b664dSBob Moore *ret_handle = ACPI_CAST_PTR(acpi_handle, node); 10195b482a8SLen Brown } 10295b482a8SLen Brown 10395b482a8SLen Brown return (status); 10495b482a8SLen Brown } 10595b482a8SLen Brown 10695b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_handle) 10795b482a8SLen Brown 10895b482a8SLen Brown /****************************************************************************** 10995b482a8SLen Brown * 11095b482a8SLen Brown * FUNCTION: acpi_get_name 11195b482a8SLen Brown * 112ba494beeSBob Moore * PARAMETERS: handle - Handle to be converted to a pathname 11395b482a8SLen Brown * name_type - Full pathname or single segment 114ba494beeSBob Moore * buffer - Buffer for returned path 11595b482a8SLen Brown * 11695b482a8SLen Brown * RETURN: Pointer to a string containing the fully qualified Name. 11795b482a8SLen Brown * 11895b482a8SLen Brown * DESCRIPTION: This routine returns the fully qualified name associated with 11995b482a8SLen Brown * the Handle parameter. This and the acpi_pathname_to_handle are 12095b482a8SLen Brown * complementary functions. 12195b482a8SLen Brown * 12295b482a8SLen Brown ******************************************************************************/ 12395b482a8SLen Brown acpi_status 12495b482a8SLen Brown acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer) 12595b482a8SLen Brown { 12695b482a8SLen Brown acpi_status status; 12795b482a8SLen Brown 12895b482a8SLen Brown /* Parameter validation */ 12995b482a8SLen Brown 13095b482a8SLen Brown if (name_type > ACPI_NAME_TYPE_MAX) { 13195b482a8SLen Brown return (AE_BAD_PARAMETER); 13295b482a8SLen Brown } 13395b482a8SLen Brown 13495b482a8SLen Brown status = acpi_ut_validate_buffer(buffer); 13595b482a8SLen Brown if (ACPI_FAILURE(status)) { 13695b482a8SLen Brown return (status); 13795b482a8SLen Brown } 13895b482a8SLen Brown 139523db19bSLv Zheng /* 140523db19bSLv Zheng * Wants the single segment ACPI name. 141523db19bSLv Zheng * Validate handle and convert to a namespace Node 142523db19bSLv Zheng */ 143523db19bSLv Zheng status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 144523db19bSLv Zheng if (ACPI_FAILURE(status)) { 145523db19bSLv Zheng return (status); 146523db19bSLv Zheng } 147523db19bSLv Zheng 148d1e7ffe5SLv Zheng if (name_type == ACPI_FULL_PATHNAME || 149d1e7ffe5SLv Zheng name_type == ACPI_FULL_PATHNAME_NO_TRAILING) { 15095b482a8SLen Brown 15195b482a8SLen Brown /* Get the full pathname (From the namespace root) */ 15295b482a8SLen Brown 153d1e7ffe5SLv Zheng status = acpi_ns_handle_to_pathname(handle, buffer, 154d1e7ffe5SLv Zheng name_type == 155d1e7ffe5SLv Zheng ACPI_FULL_PATHNAME ? FALSE : 156d1e7ffe5SLv Zheng TRUE); 157523db19bSLv Zheng } else { 158523db19bSLv Zheng /* Get the single name */ 159523db19bSLv Zheng 160523db19bSLv Zheng status = acpi_ns_handle_to_name(handle, buffer); 16195b482a8SLen Brown } 16295b482a8SLen Brown 16395b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 16495b482a8SLen Brown return (status); 16595b482a8SLen Brown } 16695b482a8SLen Brown 16795b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_name) 16895b482a8SLen Brown 16995b482a8SLen Brown /****************************************************************************** 17095b482a8SLen Brown * 17115b8dd53SBob Moore * FUNCTION: acpi_ns_copy_device_id 17215b8dd53SBob Moore * 17378e25fefSLv Zheng * PARAMETERS: dest - Pointer to the destination PNP_DEVICE_ID 17478e25fefSLv Zheng * source - Pointer to the source PNP_DEVICE_ID 17515b8dd53SBob Moore * string_area - Pointer to where to copy the dest string 17615b8dd53SBob Moore * 17715b8dd53SBob Moore * RETURN: Pointer to the next string area 17815b8dd53SBob Moore * 17978e25fefSLv Zheng * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data. 18015b8dd53SBob Moore * 18115b8dd53SBob Moore ******************************************************************************/ 18278e25fefSLv Zheng static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, 18378e25fefSLv Zheng struct acpi_pnp_device_id *source, 18415b8dd53SBob Moore char *string_area) 18515b8dd53SBob Moore { 18678e25fefSLv Zheng /* Create the destination PNP_DEVICE_ID */ 18715b8dd53SBob Moore 18815b8dd53SBob Moore dest->string = string_area; 18915b8dd53SBob Moore dest->length = source->length; 19015b8dd53SBob Moore 19115b8dd53SBob Moore /* Copy actual string and return a pointer to the next string area */ 19215b8dd53SBob Moore 1934fa4616eSBob Moore memcpy(string_area, source->string, source->length); 19415b8dd53SBob Moore return (string_area + source->length); 19515b8dd53SBob Moore } 19615b8dd53SBob Moore 19715b8dd53SBob Moore /****************************************************************************** 19815b8dd53SBob Moore * 19995b482a8SLen Brown * FUNCTION: acpi_get_object_info 20095b482a8SLen Brown * 201ba494beeSBob Moore * PARAMETERS: handle - Object Handle 20215b8dd53SBob Moore * return_buffer - Where the info is returned 20395b482a8SLen Brown * 20495b482a8SLen Brown * RETURN: Status 20595b482a8SLen Brown * 20695b482a8SLen Brown * DESCRIPTION: Returns information about an object as gleaned from the 20795b482a8SLen Brown * namespace node and possibly by running several standard 20895b482a8SLen Brown * control methods (Such as in the case of a device.) 20995b482a8SLen Brown * 210e7c2c3c9SHans de Goede * For Device and Processor objects, run the Device _HID, _UID, _CID, 21107cb390fSBob Moore * _CLS, _ADR, _sx_w, and _sx_d methods. 21215b8dd53SBob Moore * 21315b8dd53SBob Moore * Note: Allocates the return buffer, must be freed by the caller. 21415b8dd53SBob Moore * 215c6c6069cSBob Moore * Note: This interface is intended to be used during the initial device 216c6c6069cSBob Moore * discovery namespace traversal. Therefore, no complex methods can be 217c6c6069cSBob Moore * executed, especially those that access operation regions. Therefore, do 218c6c6069cSBob Moore * not add any additional methods that could cause problems in this area. 219e7c2c3c9SHans de Goede * Because of this reason support for the following methods has been removed: 220e7c2c3c9SHans de Goede * 1) _SUB method was removed (11/2015) 221e7c2c3c9SHans de Goede * 2) _STA method was removed (02/2018) 222c6c6069cSBob Moore * 22395b482a8SLen Brown ******************************************************************************/ 22415b8dd53SBob Moore 22595b482a8SLen Brown acpi_status 22615b8dd53SBob Moore acpi_get_object_info(acpi_handle handle, 22715b8dd53SBob Moore struct acpi_device_info **return_buffer) 22895b482a8SLen Brown { 22995b482a8SLen Brown struct acpi_namespace_node *node; 23095b482a8SLen Brown struct acpi_device_info *info; 23178e25fefSLv Zheng struct acpi_pnp_device_id_list *cid_list = NULL; 23278e25fefSLv Zheng struct acpi_pnp_device_id *hid = NULL; 23378e25fefSLv Zheng struct acpi_pnp_device_id *uid = NULL; 234f65358e5SSuravee Suthikulpanit struct acpi_pnp_device_id *cls = NULL; 23515b8dd53SBob Moore char *next_id_string; 23615b8dd53SBob Moore acpi_object_type type; 23715b8dd53SBob Moore acpi_name name; 23815b8dd53SBob Moore u8 param_count = 0; 239f65358e5SSuravee Suthikulpanit u16 valid = 0; 24015b8dd53SBob Moore u32 info_size; 24115b8dd53SBob Moore u32 i; 24215b8dd53SBob Moore acpi_status status; 24395b482a8SLen Brown 24495b482a8SLen Brown /* Parameter validation */ 24595b482a8SLen Brown 24615b8dd53SBob Moore if (!handle || !return_buffer) { 24795b482a8SLen Brown return (AE_BAD_PARAMETER); 24895b482a8SLen Brown } 24995b482a8SLen Brown 25095b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 25195b482a8SLen Brown if (ACPI_FAILURE(status)) { 252ef0b67feSBob Moore return (status); 25395b482a8SLen Brown } 25495b482a8SLen Brown 255f24b664dSBob Moore node = acpi_ns_validate_handle(handle); 25695b482a8SLen Brown if (!node) { 25795b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 25815b8dd53SBob Moore return (AE_BAD_PARAMETER); 25995b482a8SLen Brown } 26095b482a8SLen Brown 26115b8dd53SBob Moore /* Get the namespace node data while the namespace is locked */ 26295b482a8SLen Brown 26315b8dd53SBob Moore info_size = sizeof(struct acpi_device_info); 26415b8dd53SBob Moore type = node->type; 26515b8dd53SBob Moore name = node->name.integer; 26695b482a8SLen Brown 26795b482a8SLen Brown if (node->type == ACPI_TYPE_METHOD) { 26815b8dd53SBob Moore param_count = node->object->method.param_count; 26995b482a8SLen Brown } 27095b482a8SLen Brown 27195b482a8SLen Brown status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 27295b482a8SLen Brown if (ACPI_FAILURE(status)) { 27315b8dd53SBob Moore return (status); 27495b482a8SLen Brown } 27595b482a8SLen Brown 27615b8dd53SBob Moore if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { 27795b482a8SLen Brown /* 27815b8dd53SBob Moore * Get extra info for ACPI Device/Processor objects only: 27907cb390fSBob Moore * Run the Device _HID, _UID, _CLS, and _CID methods. 28095b482a8SLen Brown * 28195b482a8SLen Brown * Note: none of these methods are required, so they may or may 28295b482a8SLen Brown * not be present for this device. The Info->Valid bitfield is used 28315b8dd53SBob Moore * to indicate which methods were found and run successfully. 28495b482a8SLen Brown */ 28595b482a8SLen Brown 28695b482a8SLen Brown /* Execute the Device._HID method */ 28795b482a8SLen Brown 28815b8dd53SBob Moore status = acpi_ut_execute_HID(node, &hid); 28995b482a8SLen Brown if (ACPI_SUCCESS(status)) { 29015b8dd53SBob Moore info_size += hid->length; 29115b8dd53SBob Moore valid |= ACPI_VALID_HID; 29295b482a8SLen Brown } 29395b482a8SLen Brown 29495b482a8SLen Brown /* Execute the Device._UID method */ 29595b482a8SLen Brown 29615b8dd53SBob Moore status = acpi_ut_execute_UID(node, &uid); 29795b482a8SLen Brown if (ACPI_SUCCESS(status)) { 29815b8dd53SBob Moore info_size += uid->length; 29915b8dd53SBob Moore valid |= ACPI_VALID_UID; 30095b482a8SLen Brown } 30195b482a8SLen Brown 30295b482a8SLen Brown /* Execute the Device._CID method */ 30395b482a8SLen Brown 30495b482a8SLen Brown status = acpi_ut_execute_CID(node, &cid_list); 30595b482a8SLen Brown if (ACPI_SUCCESS(status)) { 30615b8dd53SBob Moore 30715b8dd53SBob Moore /* Add size of CID strings and CID pointer array */ 30815b8dd53SBob Moore 30915b8dd53SBob Moore info_size += 31015b8dd53SBob Moore (cid_list->list_size - 31178e25fefSLv Zheng sizeof(struct acpi_pnp_device_id_list)); 31215b8dd53SBob Moore valid |= ACPI_VALID_CID; 31395b482a8SLen Brown } 314f65358e5SSuravee Suthikulpanit 315f65358e5SSuravee Suthikulpanit /* Execute the Device._CLS method */ 316f65358e5SSuravee Suthikulpanit 317f65358e5SSuravee Suthikulpanit status = acpi_ut_execute_CLS(node, &cls); 318f65358e5SSuravee Suthikulpanit if (ACPI_SUCCESS(status)) { 319f65358e5SSuravee Suthikulpanit info_size += cls->length; 320f65358e5SSuravee Suthikulpanit valid |= ACPI_VALID_CLS; 321f65358e5SSuravee Suthikulpanit } 32215b8dd53SBob Moore } 32315b8dd53SBob Moore 32415b8dd53SBob Moore /* 32515b8dd53SBob Moore * Now that we have the variable-length data, we can allocate the 32615b8dd53SBob Moore * return buffer 32715b8dd53SBob Moore */ 32815b8dd53SBob Moore info = ACPI_ALLOCATE_ZEROED(info_size); 32915b8dd53SBob Moore if (!info) { 33015b8dd53SBob Moore status = AE_NO_MEMORY; 33115b8dd53SBob Moore goto cleanup; 33215b8dd53SBob Moore } 33315b8dd53SBob Moore 33415b8dd53SBob Moore /* Get the fixed-length data */ 33515b8dd53SBob Moore 33615b8dd53SBob Moore if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { 33715b8dd53SBob Moore /* 33815b8dd53SBob Moore * Get extra info for ACPI Device/Processor objects only: 339e7c2c3c9SHans de Goede * Run the _ADR and, sx_w, and _sx_d methods. 34015b8dd53SBob Moore * 341a7d5caf6SBob Moore * Notes: none of these methods are required, so they may or may 34215b8dd53SBob Moore * not be present for this device. The Info->Valid bitfield is used 34315b8dd53SBob Moore * to indicate which methods were found and run successfully. 34415b8dd53SBob Moore */ 34595b482a8SLen Brown 34695b482a8SLen Brown /* Execute the Device._ADR method */ 34795b482a8SLen Brown 34895b482a8SLen Brown status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, 34995b482a8SLen Brown &info->address); 35095b482a8SLen Brown if (ACPI_SUCCESS(status)) { 35115b8dd53SBob Moore valid |= ACPI_VALID_ADR; 35215b8dd53SBob Moore } 35315b8dd53SBob Moore 35415b8dd53SBob Moore /* Execute the Device._sx_w methods */ 35515b8dd53SBob Moore 35615b8dd53SBob Moore status = acpi_ut_execute_power_methods(node, 35715b8dd53SBob Moore acpi_gbl_lowest_dstate_names, 35815b8dd53SBob Moore ACPI_NUM_sx_w_METHODS, 35915b8dd53SBob Moore info->lowest_dstates); 36015b8dd53SBob Moore if (ACPI_SUCCESS(status)) { 36115b8dd53SBob Moore valid |= ACPI_VALID_SXWS; 36295b482a8SLen Brown } 36395b482a8SLen Brown 36495b482a8SLen Brown /* Execute the Device._sx_d methods */ 36595b482a8SLen Brown 36615b8dd53SBob Moore status = acpi_ut_execute_power_methods(node, 36715b8dd53SBob Moore acpi_gbl_highest_dstate_names, 36815b8dd53SBob Moore ACPI_NUM_sx_d_METHODS, 36915b8dd53SBob Moore info->highest_dstates); 37095b482a8SLen Brown if (ACPI_SUCCESS(status)) { 37115b8dd53SBob Moore valid |= ACPI_VALID_SXDS; 37295b482a8SLen Brown } 37395b482a8SLen Brown } 37495b482a8SLen Brown 37515b8dd53SBob Moore /* 37615b8dd53SBob Moore * Create a pointer to the string area of the return buffer. 37715b8dd53SBob Moore * Point to the end of the base struct acpi_device_info structure. 37815b8dd53SBob Moore */ 37915b8dd53SBob Moore next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); 38015b8dd53SBob Moore if (cid_list) { 38195b482a8SLen Brown 38278e25fefSLv Zheng /* Point past the CID PNP_DEVICE_ID array */ 38315b8dd53SBob Moore 38415b8dd53SBob Moore next_id_string += 38515b8dd53SBob Moore ((acpi_size)cid_list->count * 38678e25fefSLv Zheng sizeof(struct acpi_pnp_device_id)); 38795b482a8SLen Brown } 38895b482a8SLen Brown 38915b8dd53SBob Moore /* 39007cb390fSBob Moore * Copy the HID, UID, and CIDs to the return buffer. The variable-length 39107cb390fSBob Moore * strings are copied to the reserved area at the end of the buffer. 39215b8dd53SBob Moore * 39315b8dd53SBob Moore * For HID and CID, check if the ID is a PCI Root Bridge. 39415b8dd53SBob Moore */ 39515b8dd53SBob Moore if (hid) { 39615b8dd53SBob Moore next_id_string = acpi_ns_copy_device_id(&info->hardware_id, 39715b8dd53SBob Moore hid, next_id_string); 39895b482a8SLen Brown 39915b8dd53SBob Moore if (acpi_ut_is_pci_root_bridge(hid->string)) { 40015b8dd53SBob Moore info->flags |= ACPI_PCI_ROOT_BRIDGE; 40115b8dd53SBob Moore } 40215b8dd53SBob Moore } 40315b8dd53SBob Moore 40415b8dd53SBob Moore if (uid) { 40515b8dd53SBob Moore next_id_string = acpi_ns_copy_device_id(&info->unique_id, 40615b8dd53SBob Moore uid, next_id_string); 40715b8dd53SBob Moore } 40895b482a8SLen Brown 40995b482a8SLen Brown if (cid_list) { 41015b8dd53SBob Moore info->compatible_id_list.count = cid_list->count; 41115b8dd53SBob Moore info->compatible_id_list.list_size = cid_list->list_size; 41215b8dd53SBob Moore 41315b8dd53SBob Moore /* Copy each CID */ 41415b8dd53SBob Moore 41515b8dd53SBob Moore for (i = 0; i < cid_list->count; i++) { 41615b8dd53SBob Moore next_id_string = 41715b8dd53SBob Moore acpi_ns_copy_device_id(&info->compatible_id_list. 41815b8dd53SBob Moore ids[i], &cid_list->ids[i], 41915b8dd53SBob Moore next_id_string); 42015b8dd53SBob Moore 42115b8dd53SBob Moore if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) { 42215b8dd53SBob Moore info->flags |= ACPI_PCI_ROOT_BRIDGE; 42315b8dd53SBob Moore } 42415b8dd53SBob Moore } 42595b482a8SLen Brown } 42695b482a8SLen Brown 427f65358e5SSuravee Suthikulpanit if (cls) { 428aaf7566fSBob Moore (void)acpi_ns_copy_device_id(&info->class_code, 429f65358e5SSuravee Suthikulpanit cls, next_id_string); 430f65358e5SSuravee Suthikulpanit } 431f65358e5SSuravee Suthikulpanit 43215b8dd53SBob Moore /* Copy the fixed-length data */ 43315b8dd53SBob Moore 43415b8dd53SBob Moore info->info_size = info_size; 43515b8dd53SBob Moore info->type = type; 43615b8dd53SBob Moore info->name = name; 43715b8dd53SBob Moore info->param_count = param_count; 43815b8dd53SBob Moore info->valid = valid; 43915b8dd53SBob Moore 44015b8dd53SBob Moore *return_buffer = info; 44115b8dd53SBob Moore status = AE_OK; 44215b8dd53SBob Moore 44395b482a8SLen Brown cleanup: 44415b8dd53SBob Moore if (hid) { 44515b8dd53SBob Moore ACPI_FREE(hid); 44615b8dd53SBob Moore } 44715b8dd53SBob Moore if (uid) { 44815b8dd53SBob Moore ACPI_FREE(uid); 44915b8dd53SBob Moore } 45095b482a8SLen Brown if (cid_list) { 45195b482a8SLen Brown ACPI_FREE(cid_list); 45295b482a8SLen Brown } 453f65358e5SSuravee Suthikulpanit if (cls) { 454f65358e5SSuravee Suthikulpanit ACPI_FREE(cls); 455f65358e5SSuravee Suthikulpanit } 45695b482a8SLen Brown return (status); 45795b482a8SLen Brown } 45895b482a8SLen Brown 45995b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_object_info) 460b2f7ddcfSLin Ming 461b2f7ddcfSLin Ming /****************************************************************************** 462b2f7ddcfSLin Ming * 463b2f7ddcfSLin Ming * FUNCTION: acpi_install_method 464b2f7ddcfSLin Ming * 465ba494beeSBob Moore * PARAMETERS: buffer - An ACPI table containing one control method 466b2f7ddcfSLin Ming * 467b2f7ddcfSLin Ming * RETURN: Status 468b2f7ddcfSLin Ming * 469b2f7ddcfSLin Ming * DESCRIPTION: Install a control method into the namespace. If the method 470b2f7ddcfSLin Ming * name already exists in the namespace, it is overwritten. The 471b2f7ddcfSLin Ming * input buffer must contain a valid DSDT or SSDT containing a 472b2f7ddcfSLin Ming * single control method. 473b2f7ddcfSLin Ming * 474b2f7ddcfSLin Ming ******************************************************************************/ 475b2f7ddcfSLin Ming acpi_status acpi_install_method(u8 *buffer) 476b2f7ddcfSLin Ming { 477b2f7ddcfSLin Ming struct acpi_table_header *table = 478b2f7ddcfSLin Ming ACPI_CAST_PTR(struct acpi_table_header, buffer); 479b2f7ddcfSLin Ming u8 *aml_buffer; 480b2f7ddcfSLin Ming u8 *aml_start; 481b2f7ddcfSLin Ming char *path; 482b2f7ddcfSLin Ming struct acpi_namespace_node *node; 483b2f7ddcfSLin Ming union acpi_operand_object *method_obj; 484b2f7ddcfSLin Ming struct acpi_parse_state parser_state; 485b2f7ddcfSLin Ming u32 aml_length; 486b2f7ddcfSLin Ming u16 opcode; 487b2f7ddcfSLin Ming u8 method_flags; 488b2f7ddcfSLin Ming acpi_status status; 489b2f7ddcfSLin Ming 490b2f7ddcfSLin Ming /* Parameter validation */ 491b2f7ddcfSLin Ming 492b2f7ddcfSLin Ming if (!buffer) { 4939c0d7939SLv Zheng return (AE_BAD_PARAMETER); 494b2f7ddcfSLin Ming } 495b2f7ddcfSLin Ming 496b2f7ddcfSLin Ming /* Table must be a DSDT or SSDT */ 497b2f7ddcfSLin Ming 4985599fb69SBob Moore if (!ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) && 4995599fb69SBob Moore !ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT)) { 5009c0d7939SLv Zheng return (AE_BAD_HEADER); 501b2f7ddcfSLin Ming } 502b2f7ddcfSLin Ming 503b2f7ddcfSLin Ming /* First AML opcode in the table must be a control method */ 504b2f7ddcfSLin Ming 505b2f7ddcfSLin Ming parser_state.aml = buffer + sizeof(struct acpi_table_header); 506b2f7ddcfSLin Ming opcode = acpi_ps_peek_opcode(&parser_state); 507b2f7ddcfSLin Ming if (opcode != AML_METHOD_OP) { 5089c0d7939SLv Zheng return (AE_BAD_PARAMETER); 509b2f7ddcfSLin Ming } 510b2f7ddcfSLin Ming 511b2f7ddcfSLin Ming /* Extract method information from the raw AML */ 512b2f7ddcfSLin Ming 513b2f7ddcfSLin Ming parser_state.aml += acpi_ps_get_opcode_size(opcode); 514b2f7ddcfSLin Ming parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state); 515b2f7ddcfSLin Ming path = acpi_ps_get_next_namestring(&parser_state); 5161fad8738SBob Moore 517b2f7ddcfSLin Ming method_flags = *parser_state.aml++; 518b2f7ddcfSLin Ming aml_start = parser_state.aml; 51945bbbbe2SSven Barth aml_length = (u32)ACPI_PTR_DIFF(parser_state.pkg_end, aml_start); 520b2f7ddcfSLin Ming 521b2f7ddcfSLin Ming /* 522b2f7ddcfSLin Ming * Allocate resources up-front. We don't want to have to delete a new 523b2f7ddcfSLin Ming * node from the namespace if we cannot allocate memory. 524b2f7ddcfSLin Ming */ 525b2f7ddcfSLin Ming aml_buffer = ACPI_ALLOCATE(aml_length); 526b2f7ddcfSLin Ming if (!aml_buffer) { 5279c0d7939SLv Zheng return (AE_NO_MEMORY); 528b2f7ddcfSLin Ming } 529b2f7ddcfSLin Ming 530b2f7ddcfSLin Ming method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); 531b2f7ddcfSLin Ming if (!method_obj) { 532b2f7ddcfSLin Ming ACPI_FREE(aml_buffer); 5339c0d7939SLv Zheng return (AE_NO_MEMORY); 534b2f7ddcfSLin Ming } 535b2f7ddcfSLin Ming 536b2f7ddcfSLin Ming /* Lock namespace for acpi_ns_lookup, we may be creating a new node */ 537b2f7ddcfSLin Ming 538b2f7ddcfSLin Ming status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 539b2f7ddcfSLin Ming if (ACPI_FAILURE(status)) { 540b2f7ddcfSLin Ming goto error_exit; 541b2f7ddcfSLin Ming } 542b2f7ddcfSLin Ming 543b2f7ddcfSLin Ming /* The lookup either returns an existing node or creates a new one */ 544b2f7ddcfSLin Ming 545b2f7ddcfSLin Ming status = 546b2f7ddcfSLin Ming acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1, 547b2f7ddcfSLin Ming ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, 548b2f7ddcfSLin Ming NULL, &node); 549b2f7ddcfSLin Ming 550b2f7ddcfSLin Ming (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 551b2f7ddcfSLin Ming 552b2f7ddcfSLin Ming if (ACPI_FAILURE(status)) { /* ns_lookup */ 553b2f7ddcfSLin Ming if (status != AE_ALREADY_EXISTS) { 554b2f7ddcfSLin Ming goto error_exit; 555b2f7ddcfSLin Ming } 556b2f7ddcfSLin Ming 557b2f7ddcfSLin Ming /* Node existed previously, make sure it is a method node */ 558b2f7ddcfSLin Ming 559b2f7ddcfSLin Ming if (node->type != ACPI_TYPE_METHOD) { 560b2f7ddcfSLin Ming status = AE_TYPE; 561b2f7ddcfSLin Ming goto error_exit; 562b2f7ddcfSLin Ming } 563b2f7ddcfSLin Ming } 564b2f7ddcfSLin Ming 565b2f7ddcfSLin Ming /* Copy the method AML to the local buffer */ 566b2f7ddcfSLin Ming 5674fa4616eSBob Moore memcpy(aml_buffer, aml_start, aml_length); 568b2f7ddcfSLin Ming 569b2f7ddcfSLin Ming /* Initialize the method object with the new method's information */ 570b2f7ddcfSLin Ming 571b2f7ddcfSLin Ming method_obj->method.aml_start = aml_buffer; 572b2f7ddcfSLin Ming method_obj->method.aml_length = aml_length; 573b2f7ddcfSLin Ming 574b2f7ddcfSLin Ming method_obj->method.param_count = (u8) 575b2f7ddcfSLin Ming (method_flags & AML_METHOD_ARG_COUNT); 576b2f7ddcfSLin Ming 577b2f7ddcfSLin Ming if (method_flags & AML_METHOD_SERIALIZED) { 57826294842SLin Ming method_obj->method.info_flags = ACPI_METHOD_SERIALIZED; 57926294842SLin Ming 580b2f7ddcfSLin Ming method_obj->method.sync_level = (u8) 581b2f7ddcfSLin Ming ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); 582b2f7ddcfSLin Ming } 583b2f7ddcfSLin Ming 584b2f7ddcfSLin Ming /* 585b2f7ddcfSLin Ming * Now that it is complete, we can attach the new method object to 586b2f7ddcfSLin Ming * the method Node (detaches/deletes any existing object) 587b2f7ddcfSLin Ming */ 588b2f7ddcfSLin Ming status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD); 589b2f7ddcfSLin Ming 590b2f7ddcfSLin Ming /* 591b2f7ddcfSLin Ming * Flag indicates AML buffer is dynamic, must be deleted later. 592b2f7ddcfSLin Ming * Must be set only after attach above. 593b2f7ddcfSLin Ming */ 594b2f7ddcfSLin Ming node->flags |= ANOBJ_ALLOCATED_BUFFER; 595b2f7ddcfSLin Ming 596b2f7ddcfSLin Ming /* Remove local reference to the method object */ 597b2f7ddcfSLin Ming 598b2f7ddcfSLin Ming acpi_ut_remove_reference(method_obj); 5999c0d7939SLv Zheng return (status); 600b2f7ddcfSLin Ming 601b2f7ddcfSLin Ming error_exit: 602b2f7ddcfSLin Ming 603b2f7ddcfSLin Ming ACPI_FREE(aml_buffer); 604b2f7ddcfSLin Ming ACPI_FREE(method_obj); 6059c0d7939SLv Zheng return (status); 606b2f7ddcfSLin Ming } 607b2f7ddcfSLin Ming ACPI_EXPORT_SYMBOL(acpi_install_method) 608