1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: nsxfname - Public interfaces to the ACPI subsystem
5*4882a593Smuzhiyun * ACPI Namespace oriented interfaces
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (C) 2000 - 2020, Intel Corp.
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun *****************************************************************************/
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #define EXPORT_ACPI_INTERFACES
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <acpi/acpi.h>
14*4882a593Smuzhiyun #include "accommon.h"
15*4882a593Smuzhiyun #include "acnamesp.h"
16*4882a593Smuzhiyun #include "acparser.h"
17*4882a593Smuzhiyun #include "amlcode.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define _COMPONENT ACPI_NAMESPACE
20*4882a593Smuzhiyun ACPI_MODULE_NAME("nsxfname")
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun /* Local prototypes */
23*4882a593Smuzhiyun static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
24*4882a593Smuzhiyun struct acpi_pnp_device_id *source,
25*4882a593Smuzhiyun char *string_area);
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /******************************************************************************
28*4882a593Smuzhiyun *
29*4882a593Smuzhiyun * FUNCTION: acpi_get_handle
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * PARAMETERS: parent - Object to search under (search scope).
32*4882a593Smuzhiyun * pathname - Pointer to an asciiz string containing the
33*4882a593Smuzhiyun * name
34*4882a593Smuzhiyun * ret_handle - Where the return handle is returned
35*4882a593Smuzhiyun *
36*4882a593Smuzhiyun * RETURN: Status
37*4882a593Smuzhiyun *
38*4882a593Smuzhiyun * DESCRIPTION: This routine will search for a caller specified name in the
39*4882a593Smuzhiyun * name space. The caller can restrict the search region by
40*4882a593Smuzhiyun * specifying a non NULL parent. The parent value is itself a
41*4882a593Smuzhiyun * namespace handle.
42*4882a593Smuzhiyun *
43*4882a593Smuzhiyun ******************************************************************************/
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun acpi_status
acpi_get_handle(acpi_handle parent,acpi_string pathname,acpi_handle * ret_handle)46*4882a593Smuzhiyun acpi_get_handle(acpi_handle parent,
47*4882a593Smuzhiyun acpi_string pathname, acpi_handle *ret_handle)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun acpi_status status;
50*4882a593Smuzhiyun struct acpi_namespace_node *node = NULL;
51*4882a593Smuzhiyun struct acpi_namespace_node *prefix_node = NULL;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* Parameter Validation */
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun if (!ret_handle || !pathname) {
58*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* Convert a parent handle to a prefix node */
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (parent) {
64*4882a593Smuzhiyun prefix_node = acpi_ns_validate_handle(parent);
65*4882a593Smuzhiyun if (!prefix_node) {
66*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun * Valid cases are:
72*4882a593Smuzhiyun * 1) Fully qualified pathname
73*4882a593Smuzhiyun * 2) Parent + Relative pathname
74*4882a593Smuzhiyun *
75*4882a593Smuzhiyun * Error for <null Parent + relative path>
76*4882a593Smuzhiyun */
77*4882a593Smuzhiyun if (ACPI_IS_ROOT_PREFIX(pathname[0])) {
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* Pathname is fully qualified (starts with '\') */
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /* Special case for root-only, since we can't search for it */
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun if (!strcmp(pathname, ACPI_NS_ROOT_PATH)) {
84*4882a593Smuzhiyun *ret_handle =
85*4882a593Smuzhiyun ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
86*4882a593Smuzhiyun return (AE_OK);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun } else if (!prefix_node) {
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* Relative path with null prefix is disallowed */
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* Find the Node and convert to a handle */
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun status =
98*4882a593Smuzhiyun acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
99*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
100*4882a593Smuzhiyun *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun return (status);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_get_handle)106*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_get_handle)
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /******************************************************************************
109*4882a593Smuzhiyun *
110*4882a593Smuzhiyun * FUNCTION: acpi_get_name
111*4882a593Smuzhiyun *
112*4882a593Smuzhiyun * PARAMETERS: handle - Handle to be converted to a pathname
113*4882a593Smuzhiyun * name_type - Full pathname or single segment
114*4882a593Smuzhiyun * buffer - Buffer for returned path
115*4882a593Smuzhiyun *
116*4882a593Smuzhiyun * RETURN: Pointer to a string containing the fully qualified Name.
117*4882a593Smuzhiyun *
118*4882a593Smuzhiyun * DESCRIPTION: This routine returns the fully qualified name associated with
119*4882a593Smuzhiyun * the Handle parameter. This and the acpi_pathname_to_handle are
120*4882a593Smuzhiyun * complementary functions.
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun ******************************************************************************/
123*4882a593Smuzhiyun acpi_status
124*4882a593Smuzhiyun acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun acpi_status status;
127*4882a593Smuzhiyun
128*4882a593Smuzhiyun /* Parameter validation */
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (name_type > ACPI_NAME_TYPE_MAX) {
131*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun status = acpi_ut_validate_buffer(buffer);
135*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
136*4882a593Smuzhiyun return (status);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /*
140*4882a593Smuzhiyun * Wants the single segment ACPI name.
141*4882a593Smuzhiyun * Validate handle and convert to a namespace Node
142*4882a593Smuzhiyun */
143*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
144*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
145*4882a593Smuzhiyun return (status);
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (name_type == ACPI_FULL_PATHNAME ||
149*4882a593Smuzhiyun name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* Get the full pathname (From the namespace root) */
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun status = acpi_ns_handle_to_pathname(handle, buffer,
154*4882a593Smuzhiyun name_type ==
155*4882a593Smuzhiyun ACPI_FULL_PATHNAME ? FALSE :
156*4882a593Smuzhiyun TRUE);
157*4882a593Smuzhiyun } else {
158*4882a593Smuzhiyun /* Get the single name */
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun status = acpi_ns_handle_to_name(handle, buffer);
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
164*4882a593Smuzhiyun return (status);
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_get_name)167*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_get_name)
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /******************************************************************************
170*4882a593Smuzhiyun *
171*4882a593Smuzhiyun * FUNCTION: acpi_ns_copy_device_id
172*4882a593Smuzhiyun *
173*4882a593Smuzhiyun * PARAMETERS: dest - Pointer to the destination PNP_DEVICE_ID
174*4882a593Smuzhiyun * source - Pointer to the source PNP_DEVICE_ID
175*4882a593Smuzhiyun * string_area - Pointer to where to copy the dest string
176*4882a593Smuzhiyun *
177*4882a593Smuzhiyun * RETURN: Pointer to the next string area
178*4882a593Smuzhiyun *
179*4882a593Smuzhiyun * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
180*4882a593Smuzhiyun *
181*4882a593Smuzhiyun ******************************************************************************/
182*4882a593Smuzhiyun static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
183*4882a593Smuzhiyun struct acpi_pnp_device_id *source,
184*4882a593Smuzhiyun char *string_area)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun /* Create the destination PNP_DEVICE_ID */
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun dest->string = string_area;
189*4882a593Smuzhiyun dest->length = source->length;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun /* Copy actual string and return a pointer to the next string area */
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun memcpy(string_area, source->string, source->length);
194*4882a593Smuzhiyun return (string_area + source->length);
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /******************************************************************************
198*4882a593Smuzhiyun *
199*4882a593Smuzhiyun * FUNCTION: acpi_get_object_info
200*4882a593Smuzhiyun *
201*4882a593Smuzhiyun * PARAMETERS: handle - Object Handle
202*4882a593Smuzhiyun * return_buffer - Where the info is returned
203*4882a593Smuzhiyun *
204*4882a593Smuzhiyun * RETURN: Status
205*4882a593Smuzhiyun *
206*4882a593Smuzhiyun * DESCRIPTION: Returns information about an object as gleaned from the
207*4882a593Smuzhiyun * namespace node and possibly by running several standard
208*4882a593Smuzhiyun * control methods (Such as in the case of a device.)
209*4882a593Smuzhiyun *
210*4882a593Smuzhiyun * For Device and Processor objects, run the Device _HID, _UID, _CID,
211*4882a593Smuzhiyun * _CLS, _ADR, _sx_w, and _sx_d methods.
212*4882a593Smuzhiyun *
213*4882a593Smuzhiyun * Note: Allocates the return buffer, must be freed by the caller.
214*4882a593Smuzhiyun *
215*4882a593Smuzhiyun * Note: This interface is intended to be used during the initial device
216*4882a593Smuzhiyun * discovery namespace traversal. Therefore, no complex methods can be
217*4882a593Smuzhiyun * executed, especially those that access operation regions. Therefore, do
218*4882a593Smuzhiyun * not add any additional methods that could cause problems in this area.
219*4882a593Smuzhiyun * Because of this reason support for the following methods has been removed:
220*4882a593Smuzhiyun * 1) _SUB method was removed (11/2015)
221*4882a593Smuzhiyun * 2) _STA method was removed (02/2018)
222*4882a593Smuzhiyun *
223*4882a593Smuzhiyun ******************************************************************************/
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun acpi_status
acpi_get_object_info(acpi_handle handle,struct acpi_device_info ** return_buffer)226*4882a593Smuzhiyun acpi_get_object_info(acpi_handle handle,
227*4882a593Smuzhiyun struct acpi_device_info **return_buffer)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct acpi_namespace_node *node;
230*4882a593Smuzhiyun struct acpi_device_info *info;
231*4882a593Smuzhiyun struct acpi_pnp_device_id_list *cid_list = NULL;
232*4882a593Smuzhiyun struct acpi_pnp_device_id *hid = NULL;
233*4882a593Smuzhiyun struct acpi_pnp_device_id *uid = NULL;
234*4882a593Smuzhiyun struct acpi_pnp_device_id *cls = NULL;
235*4882a593Smuzhiyun char *next_id_string;
236*4882a593Smuzhiyun acpi_object_type type;
237*4882a593Smuzhiyun acpi_name name;
238*4882a593Smuzhiyun u8 param_count = 0;
239*4882a593Smuzhiyun u16 valid = 0;
240*4882a593Smuzhiyun u32 info_size;
241*4882a593Smuzhiyun u32 i;
242*4882a593Smuzhiyun acpi_status status;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /* Parameter validation */
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun if (!handle || !return_buffer) {
247*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
251*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
252*4882a593Smuzhiyun return (status);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun node = acpi_ns_validate_handle(handle);
256*4882a593Smuzhiyun if (!node) {
257*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
258*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun /* Get the namespace node data while the namespace is locked */
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun info_size = sizeof(struct acpi_device_info);
264*4882a593Smuzhiyun type = node->type;
265*4882a593Smuzhiyun name = node->name.integer;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun if (node->type == ACPI_TYPE_METHOD) {
268*4882a593Smuzhiyun param_count = node->object->method.param_count;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
272*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
273*4882a593Smuzhiyun return (status);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
276*4882a593Smuzhiyun if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
277*4882a593Smuzhiyun /*
278*4882a593Smuzhiyun * Get extra info for ACPI Device/Processor objects only:
279*4882a593Smuzhiyun * Run the Device _HID, _UID, _CLS, and _CID methods.
280*4882a593Smuzhiyun *
281*4882a593Smuzhiyun * Note: none of these methods are required, so they may or may
282*4882a593Smuzhiyun * not be present for this device. The Info->Valid bitfield is used
283*4882a593Smuzhiyun * to indicate which methods were found and run successfully.
284*4882a593Smuzhiyun */
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /* Execute the Device._HID method */
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun status = acpi_ut_execute_HID(node, &hid);
289*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
290*4882a593Smuzhiyun info_size += hid->length;
291*4882a593Smuzhiyun valid |= ACPI_VALID_HID;
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun /* Execute the Device._UID method */
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun status = acpi_ut_execute_UID(node, &uid);
297*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
298*4882a593Smuzhiyun info_size += uid->length;
299*4882a593Smuzhiyun valid |= ACPI_VALID_UID;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /* Execute the Device._CID method */
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun status = acpi_ut_execute_CID(node, &cid_list);
305*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun /* Add size of CID strings and CID pointer array */
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun info_size +=
310*4882a593Smuzhiyun (cid_list->list_size -
311*4882a593Smuzhiyun sizeof(struct acpi_pnp_device_id_list));
312*4882a593Smuzhiyun valid |= ACPI_VALID_CID;
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Execute the Device._CLS method */
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun status = acpi_ut_execute_CLS(node, &cls);
318*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
319*4882a593Smuzhiyun info_size += cls->length;
320*4882a593Smuzhiyun valid |= ACPI_VALID_CLS;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun }
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /*
325*4882a593Smuzhiyun * Now that we have the variable-length data, we can allocate the
326*4882a593Smuzhiyun * return buffer
327*4882a593Smuzhiyun */
328*4882a593Smuzhiyun info = ACPI_ALLOCATE_ZEROED(info_size);
329*4882a593Smuzhiyun if (!info) {
330*4882a593Smuzhiyun status = AE_NO_MEMORY;
331*4882a593Smuzhiyun goto cleanup;
332*4882a593Smuzhiyun }
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun /* Get the fixed-length data */
335*4882a593Smuzhiyun
336*4882a593Smuzhiyun if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
337*4882a593Smuzhiyun /*
338*4882a593Smuzhiyun * Get extra info for ACPI Device/Processor objects only:
339*4882a593Smuzhiyun * Run the _ADR and, sx_w, and _sx_d methods.
340*4882a593Smuzhiyun *
341*4882a593Smuzhiyun * Notes: none of these methods are required, so they may or may
342*4882a593Smuzhiyun * not be present for this device. The Info->Valid bitfield is used
343*4882a593Smuzhiyun * to indicate which methods were found and run successfully.
344*4882a593Smuzhiyun */
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /* Execute the Device._ADR method */
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
349*4882a593Smuzhiyun &info->address);
350*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
351*4882a593Smuzhiyun valid |= ACPI_VALID_ADR;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun /* Execute the Device._sx_w methods */
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun status = acpi_ut_execute_power_methods(node,
357*4882a593Smuzhiyun acpi_gbl_lowest_dstate_names,
358*4882a593Smuzhiyun ACPI_NUM_sx_w_METHODS,
359*4882a593Smuzhiyun info->lowest_dstates);
360*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
361*4882a593Smuzhiyun valid |= ACPI_VALID_SXWS;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Execute the Device._sx_d methods */
365*4882a593Smuzhiyun
366*4882a593Smuzhiyun status = acpi_ut_execute_power_methods(node,
367*4882a593Smuzhiyun acpi_gbl_highest_dstate_names,
368*4882a593Smuzhiyun ACPI_NUM_sx_d_METHODS,
369*4882a593Smuzhiyun info->highest_dstates);
370*4882a593Smuzhiyun if (ACPI_SUCCESS(status)) {
371*4882a593Smuzhiyun valid |= ACPI_VALID_SXDS;
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /*
376*4882a593Smuzhiyun * Create a pointer to the string area of the return buffer.
377*4882a593Smuzhiyun * Point to the end of the base struct acpi_device_info structure.
378*4882a593Smuzhiyun */
379*4882a593Smuzhiyun next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
380*4882a593Smuzhiyun if (cid_list) {
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* Point past the CID PNP_DEVICE_ID array */
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun next_id_string +=
385*4882a593Smuzhiyun ((acpi_size)cid_list->count *
386*4882a593Smuzhiyun sizeof(struct acpi_pnp_device_id));
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /*
390*4882a593Smuzhiyun * Copy the HID, UID, and CIDs to the return buffer. The variable-length
391*4882a593Smuzhiyun * strings are copied to the reserved area at the end of the buffer.
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * For HID and CID, check if the ID is a PCI Root Bridge.
394*4882a593Smuzhiyun */
395*4882a593Smuzhiyun if (hid) {
396*4882a593Smuzhiyun next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
397*4882a593Smuzhiyun hid, next_id_string);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun if (acpi_ut_is_pci_root_bridge(hid->string)) {
400*4882a593Smuzhiyun info->flags |= ACPI_PCI_ROOT_BRIDGE;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun if (uid) {
405*4882a593Smuzhiyun next_id_string = acpi_ns_copy_device_id(&info->unique_id,
406*4882a593Smuzhiyun uid, next_id_string);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (cid_list) {
410*4882a593Smuzhiyun info->compatible_id_list.count = cid_list->count;
411*4882a593Smuzhiyun info->compatible_id_list.list_size = cid_list->list_size;
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun /* Copy each CID */
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun for (i = 0; i < cid_list->count; i++) {
416*4882a593Smuzhiyun next_id_string =
417*4882a593Smuzhiyun acpi_ns_copy_device_id(&info->compatible_id_list.
418*4882a593Smuzhiyun ids[i], &cid_list->ids[i],
419*4882a593Smuzhiyun next_id_string);
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
422*4882a593Smuzhiyun info->flags |= ACPI_PCI_ROOT_BRIDGE;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun }
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun if (cls) {
428*4882a593Smuzhiyun (void)acpi_ns_copy_device_id(&info->class_code,
429*4882a593Smuzhiyun cls, next_id_string);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun /* Copy the fixed-length data */
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun info->info_size = info_size;
435*4882a593Smuzhiyun info->type = type;
436*4882a593Smuzhiyun info->name = name;
437*4882a593Smuzhiyun info->param_count = param_count;
438*4882a593Smuzhiyun info->valid = valid;
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun *return_buffer = info;
441*4882a593Smuzhiyun status = AE_OK;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun cleanup:
444*4882a593Smuzhiyun if (hid) {
445*4882a593Smuzhiyun ACPI_FREE(hid);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun if (uid) {
448*4882a593Smuzhiyun ACPI_FREE(uid);
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun if (cid_list) {
451*4882a593Smuzhiyun ACPI_FREE(cid_list);
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun if (cls) {
454*4882a593Smuzhiyun ACPI_FREE(cls);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun return (status);
457*4882a593Smuzhiyun }
458*4882a593Smuzhiyun
ACPI_EXPORT_SYMBOL(acpi_get_object_info)459*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_get_object_info)
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun /******************************************************************************
462*4882a593Smuzhiyun *
463*4882a593Smuzhiyun * FUNCTION: acpi_install_method
464*4882a593Smuzhiyun *
465*4882a593Smuzhiyun * PARAMETERS: buffer - An ACPI table containing one control method
466*4882a593Smuzhiyun *
467*4882a593Smuzhiyun * RETURN: Status
468*4882a593Smuzhiyun *
469*4882a593Smuzhiyun * DESCRIPTION: Install a control method into the namespace. If the method
470*4882a593Smuzhiyun * name already exists in the namespace, it is overwritten. The
471*4882a593Smuzhiyun * input buffer must contain a valid DSDT or SSDT containing a
472*4882a593Smuzhiyun * single control method.
473*4882a593Smuzhiyun *
474*4882a593Smuzhiyun ******************************************************************************/
475*4882a593Smuzhiyun acpi_status acpi_install_method(u8 *buffer)
476*4882a593Smuzhiyun {
477*4882a593Smuzhiyun struct acpi_table_header *table =
478*4882a593Smuzhiyun ACPI_CAST_PTR(struct acpi_table_header, buffer);
479*4882a593Smuzhiyun u8 *aml_buffer;
480*4882a593Smuzhiyun u8 *aml_start;
481*4882a593Smuzhiyun char *path;
482*4882a593Smuzhiyun struct acpi_namespace_node *node;
483*4882a593Smuzhiyun union acpi_operand_object *method_obj;
484*4882a593Smuzhiyun struct acpi_parse_state parser_state;
485*4882a593Smuzhiyun u32 aml_length;
486*4882a593Smuzhiyun u16 opcode;
487*4882a593Smuzhiyun u8 method_flags;
488*4882a593Smuzhiyun acpi_status status;
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /* Parameter validation */
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if (!buffer) {
493*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun /* Table must be a DSDT or SSDT */
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun if (!ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) &&
499*4882a593Smuzhiyun !ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT)) {
500*4882a593Smuzhiyun return (AE_BAD_HEADER);
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /* First AML opcode in the table must be a control method */
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun parser_state.aml = buffer + sizeof(struct acpi_table_header);
506*4882a593Smuzhiyun opcode = acpi_ps_peek_opcode(&parser_state);
507*4882a593Smuzhiyun if (opcode != AML_METHOD_OP) {
508*4882a593Smuzhiyun return (AE_BAD_PARAMETER);
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /* Extract method information from the raw AML */
512*4882a593Smuzhiyun
513*4882a593Smuzhiyun parser_state.aml += acpi_ps_get_opcode_size(opcode);
514*4882a593Smuzhiyun parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
515*4882a593Smuzhiyun path = acpi_ps_get_next_namestring(&parser_state);
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun method_flags = *parser_state.aml++;
518*4882a593Smuzhiyun aml_start = parser_state.aml;
519*4882a593Smuzhiyun aml_length = (u32)ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /*
522*4882a593Smuzhiyun * Allocate resources up-front. We don't want to have to delete a new
523*4882a593Smuzhiyun * node from the namespace if we cannot allocate memory.
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun aml_buffer = ACPI_ALLOCATE(aml_length);
526*4882a593Smuzhiyun if (!aml_buffer) {
527*4882a593Smuzhiyun return (AE_NO_MEMORY);
528*4882a593Smuzhiyun }
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
531*4882a593Smuzhiyun if (!method_obj) {
532*4882a593Smuzhiyun ACPI_FREE(aml_buffer);
533*4882a593Smuzhiyun return (AE_NO_MEMORY);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun /* Lock namespace for acpi_ns_lookup, we may be creating a new node */
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
539*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
540*4882a593Smuzhiyun goto error_exit;
541*4882a593Smuzhiyun }
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun /* The lookup either returns an existing node or creates a new one */
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun status =
546*4882a593Smuzhiyun acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
547*4882a593Smuzhiyun ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
548*4882a593Smuzhiyun NULL, &node);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun if (ACPI_FAILURE(status)) { /* ns_lookup */
553*4882a593Smuzhiyun if (status != AE_ALREADY_EXISTS) {
554*4882a593Smuzhiyun goto error_exit;
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /* Node existed previously, make sure it is a method node */
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun if (node->type != ACPI_TYPE_METHOD) {
560*4882a593Smuzhiyun status = AE_TYPE;
561*4882a593Smuzhiyun goto error_exit;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun }
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun /* Copy the method AML to the local buffer */
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun memcpy(aml_buffer, aml_start, aml_length);
568*4882a593Smuzhiyun
569*4882a593Smuzhiyun /* Initialize the method object with the new method's information */
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun method_obj->method.aml_start = aml_buffer;
572*4882a593Smuzhiyun method_obj->method.aml_length = aml_length;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun method_obj->method.param_count = (u8)
575*4882a593Smuzhiyun (method_flags & AML_METHOD_ARG_COUNT);
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (method_flags & AML_METHOD_SERIALIZED) {
578*4882a593Smuzhiyun method_obj->method.info_flags = ACPI_METHOD_SERIALIZED;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun method_obj->method.sync_level = (u8)
581*4882a593Smuzhiyun ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /*
585*4882a593Smuzhiyun * Now that it is complete, we can attach the new method object to
586*4882a593Smuzhiyun * the method Node (detaches/deletes any existing object)
587*4882a593Smuzhiyun */
588*4882a593Smuzhiyun status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /*
591*4882a593Smuzhiyun * Flag indicates AML buffer is dynamic, must be deleted later.
592*4882a593Smuzhiyun * Must be set only after attach above.
593*4882a593Smuzhiyun */
594*4882a593Smuzhiyun node->flags |= ANOBJ_ALLOCATED_BUFFER;
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun /* Remove local reference to the method object */
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun acpi_ut_remove_reference(method_obj);
599*4882a593Smuzhiyun return (status);
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun error_exit:
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun ACPI_FREE(aml_buffer);
604*4882a593Smuzhiyun ACPI_FREE(method_obj);
605*4882a593Smuzhiyun return (status);
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun ACPI_EXPORT_SYMBOL(acpi_install_method)
608