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
acpi_get_handle(acpi_handle parent,const char * pathname,acpi_handle * ret_handle)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
ACPI_EXPORT_SYMBOL(acpi_get_handle)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
ACPI_EXPORT_SYMBOL(acpi_get_name)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
acpi_get_object_info(acpi_handle handle,struct acpi_device_info ** return_buffer)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
ACPI_EXPORT_SYMBOL(acpi_get_object_info)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