1*4882a593Smuzhiyun // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2*4882a593Smuzhiyun /*******************************************************************************
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Module Name: utresrc - Resource management utilities
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun ******************************************************************************/
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <acpi/acpi.h>
9*4882a593Smuzhiyun #include "accommon.h"
10*4882a593Smuzhiyun #include "acresrc.h"
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #define _COMPONENT ACPI_UTILITIES
13*4882a593Smuzhiyun ACPI_MODULE_NAME("utresrc")
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun /*
16*4882a593Smuzhiyun * Base sizes of the raw AML resource descriptors, indexed by resource type.
17*4882a593Smuzhiyun * Zero indicates a reserved (and therefore invalid) resource type.
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun const u8 acpi_gbl_resource_aml_sizes[] = {
20*4882a593Smuzhiyun /* Small descriptors */
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun 0,
23*4882a593Smuzhiyun 0,
24*4882a593Smuzhiyun 0,
25*4882a593Smuzhiyun 0,
26*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_irq),
27*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_dma),
28*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent),
29*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent),
30*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_io),
31*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io),
32*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma),
33*4882a593Smuzhiyun 0,
34*4882a593Smuzhiyun 0,
35*4882a593Smuzhiyun 0,
36*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small),
37*4882a593Smuzhiyun ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag),
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun /* Large descriptors */
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun 0,
42*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_memory24),
43*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register),
44*4882a593Smuzhiyun 0,
45*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large),
46*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_memory32),
47*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32),
48*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_address32),
49*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_address16),
50*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq),
51*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_address64),
52*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64),
53*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_gpio),
54*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_pin_function),
55*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus),
56*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_pin_config),
57*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group),
58*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_function),
59*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_pin_group_config),
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = {
63*4882a593Smuzhiyun 0,
64*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus),
65*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus),
66*4882a593Smuzhiyun ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus),
67*4882a593Smuzhiyun };
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun * Resource types, used to validate the resource length field.
71*4882a593Smuzhiyun * The length of fixed-length types must match exactly, variable
72*4882a593Smuzhiyun * lengths must meet the minimum required length, etc.
73*4882a593Smuzhiyun * Zero indicates a reserved (and therefore invalid) resource type.
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun static const u8 acpi_gbl_resource_types[] = {
76*4882a593Smuzhiyun /* Small descriptors */
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun 0,
79*4882a593Smuzhiyun 0,
80*4882a593Smuzhiyun 0,
81*4882a593Smuzhiyun 0,
82*4882a593Smuzhiyun ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */
83*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 05 DMA */
84*4882a593Smuzhiyun ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */
85*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */
86*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 08 IO */
87*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 09 fixed_IO */
88*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 0A fixed_DMA */
89*4882a593Smuzhiyun 0,
90*4882a593Smuzhiyun 0,
91*4882a593Smuzhiyun 0,
92*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0E vendor_short */
93*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 0F end_tag */
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun /* Large descriptors */
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun 0,
98*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 01 Memory24 */
99*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 02 generic_register */
100*4882a593Smuzhiyun 0,
101*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 04 vendor_long */
102*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 05 Memory32 */
103*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 06 memory32_fixed */
104*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 07 Dword* address */
105*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 08 Word* address */
106*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 09 extended_IRQ */
107*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0A Qword* address */
108*4882a593Smuzhiyun ACPI_FIXED_LENGTH, /* 0B Extended* address */
109*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0C Gpio* */
110*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0D pin_function */
111*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0E *serial_bus */
112*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 0F pin_config */
113*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 10 pin_group */
114*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 11 pin_group_function */
115*4882a593Smuzhiyun ACPI_VARIABLE_LENGTH, /* 12 pin_group_config */
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /*******************************************************************************
119*4882a593Smuzhiyun *
120*4882a593Smuzhiyun * FUNCTION: acpi_ut_walk_aml_resources
121*4882a593Smuzhiyun *
122*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk info
123*4882a593Smuzhiyun * PARAMETERS: aml - Pointer to the raw AML resource template
124*4882a593Smuzhiyun * aml_length - Length of the entire template
125*4882a593Smuzhiyun * user_function - Called once for each descriptor found. If
126*4882a593Smuzhiyun * NULL, a pointer to the end_tag is returned
127*4882a593Smuzhiyun * context - Passed to user_function
128*4882a593Smuzhiyun *
129*4882a593Smuzhiyun * RETURN: Status
130*4882a593Smuzhiyun *
131*4882a593Smuzhiyun * DESCRIPTION: Walk a raw AML resource list(buffer). User function called
132*4882a593Smuzhiyun * once for each resource found.
133*4882a593Smuzhiyun *
134*4882a593Smuzhiyun ******************************************************************************/
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun acpi_status
acpi_ut_walk_aml_resources(struct acpi_walk_state * walk_state,u8 * aml,acpi_size aml_length,acpi_walk_aml_callback user_function,void ** context)137*4882a593Smuzhiyun acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
138*4882a593Smuzhiyun u8 *aml,
139*4882a593Smuzhiyun acpi_size aml_length,
140*4882a593Smuzhiyun acpi_walk_aml_callback user_function, void **context)
141*4882a593Smuzhiyun {
142*4882a593Smuzhiyun acpi_status status;
143*4882a593Smuzhiyun u8 *end_aml;
144*4882a593Smuzhiyun u8 resource_index;
145*4882a593Smuzhiyun u32 length;
146*4882a593Smuzhiyun u32 offset = 0;
147*4882a593Smuzhiyun u8 end_tag[2] = { 0x79, 0x00 };
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ut_walk_aml_resources);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* The absolute minimum resource template is one end_tag descriptor */
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (aml_length < sizeof(struct aml_resource_end_tag)) {
154*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* Point to the end of the resource template buffer */
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun end_aml = aml + aml_length;
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun /* Walk the byte list, abort on any invalid descriptor type or length */
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun while (aml < end_aml) {
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun /* Validate the Resource Type and Resource Length */
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun status =
168*4882a593Smuzhiyun acpi_ut_validate_resource(walk_state, aml, &resource_index);
169*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
170*4882a593Smuzhiyun /*
171*4882a593Smuzhiyun * Exit on failure. Cannot continue because the descriptor
172*4882a593Smuzhiyun * length may be bogus also.
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun return_ACPI_STATUS(status);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* Get the length of this descriptor */
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun length = acpi_ut_get_descriptor_length(aml);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Invoke the user function */
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun if (user_function) {
184*4882a593Smuzhiyun status =
185*4882a593Smuzhiyun user_function(aml, length, offset, resource_index,
186*4882a593Smuzhiyun context);
187*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
188*4882a593Smuzhiyun return_ACPI_STATUS(status);
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /* An end_tag descriptor terminates this resource template */
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun if (acpi_ut_get_resource_type(aml) ==
195*4882a593Smuzhiyun ACPI_RESOURCE_NAME_END_TAG) {
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun * There must be at least one more byte in the buffer for
198*4882a593Smuzhiyun * the 2nd byte of the end_tag
199*4882a593Smuzhiyun */
200*4882a593Smuzhiyun if ((aml + 1) >= end_aml) {
201*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun /*
205*4882a593Smuzhiyun * Don't attempt to perform any validation on the 2nd byte.
206*4882a593Smuzhiyun * Although all known ASL compilers insert a zero for the 2nd
207*4882a593Smuzhiyun * byte, it can also be a checksum (as per the ACPI spec),
208*4882a593Smuzhiyun * and this is occasionally seen in the field. July 2017.
209*4882a593Smuzhiyun */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /* Return the pointer to the end_tag if requested */
212*4882a593Smuzhiyun
213*4882a593Smuzhiyun if (!user_function) {
214*4882a593Smuzhiyun *context = aml;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun /* Normal exit */
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun aml += length;
223*4882a593Smuzhiyun offset += length;
224*4882a593Smuzhiyun }
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /* Did not find an end_tag descriptor */
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun if (user_function) {
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun (void)acpi_ut_validate_resource(walk_state, end_tag,
233*4882a593Smuzhiyun &resource_index);
234*4882a593Smuzhiyun status =
235*4882a593Smuzhiyun user_function(end_tag, 2, offset, resource_index, context);
236*4882a593Smuzhiyun if (ACPI_FAILURE(status)) {
237*4882a593Smuzhiyun return_ACPI_STATUS(status);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun }
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /*******************************************************************************
245*4882a593Smuzhiyun *
246*4882a593Smuzhiyun * FUNCTION: acpi_ut_validate_resource
247*4882a593Smuzhiyun *
248*4882a593Smuzhiyun * PARAMETERS: walk_state - Current walk info
249*4882a593Smuzhiyun * aml - Pointer to the raw AML resource descriptor
250*4882a593Smuzhiyun * return_index - Where the resource index is returned. NULL
251*4882a593Smuzhiyun * if the index is not required.
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * RETURN: Status, and optionally the Index into the global resource tables
254*4882a593Smuzhiyun *
255*4882a593Smuzhiyun * DESCRIPTION: Validate an AML resource descriptor by checking the Resource
256*4882a593Smuzhiyun * Type and Resource Length. Returns an index into the global
257*4882a593Smuzhiyun * resource information/dispatch tables for later use.
258*4882a593Smuzhiyun *
259*4882a593Smuzhiyun ******************************************************************************/
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun acpi_status
acpi_ut_validate_resource(struct acpi_walk_state * walk_state,void * aml,u8 * return_index)262*4882a593Smuzhiyun acpi_ut_validate_resource(struct acpi_walk_state *walk_state,
263*4882a593Smuzhiyun void *aml, u8 *return_index)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun union aml_resource *aml_resource;
266*4882a593Smuzhiyun u8 resource_type;
267*4882a593Smuzhiyun u8 resource_index;
268*4882a593Smuzhiyun acpi_rs_length resource_length;
269*4882a593Smuzhiyun acpi_rs_length minimum_resource_length;
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun /*
274*4882a593Smuzhiyun * 1) Validate the resource_type field (Byte 0)
275*4882a593Smuzhiyun */
276*4882a593Smuzhiyun resource_type = ACPI_GET8(aml);
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun /*
279*4882a593Smuzhiyun * Byte 0 contains the descriptor name (Resource Type)
280*4882a593Smuzhiyun * Examine the large/small bit in the resource header
281*4882a593Smuzhiyun */
282*4882a593Smuzhiyun if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun /* Verify the large resource type (name) against the max */
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
287*4882a593Smuzhiyun goto invalid_resource;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /*
291*4882a593Smuzhiyun * Large Resource Type -- bits 6:0 contain the name
292*4882a593Smuzhiyun * Translate range 0x80-0x8B to index range 0x10-0x1B
293*4882a593Smuzhiyun */
294*4882a593Smuzhiyun resource_index = (u8) (resource_type - 0x70);
295*4882a593Smuzhiyun } else {
296*4882a593Smuzhiyun /*
297*4882a593Smuzhiyun * Small Resource Type -- bits 6:3 contain the name
298*4882a593Smuzhiyun * Shift range to index range 0x00-0x0F
299*4882a593Smuzhiyun */
300*4882a593Smuzhiyun resource_index = (u8)
301*4882a593Smuzhiyun ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3);
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /*
305*4882a593Smuzhiyun * Check validity of the resource type, via acpi_gbl_resource_types.
306*4882a593Smuzhiyun * Zero indicates an invalid resource.
307*4882a593Smuzhiyun */
308*4882a593Smuzhiyun if (!acpi_gbl_resource_types[resource_index]) {
309*4882a593Smuzhiyun goto invalid_resource;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /*
313*4882a593Smuzhiyun * Validate the resource_length field. This ensures that the length
314*4882a593Smuzhiyun * is at least reasonable, and guarantees that it is non-zero.
315*4882a593Smuzhiyun */
316*4882a593Smuzhiyun resource_length = acpi_ut_get_resource_length(aml);
317*4882a593Smuzhiyun minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index];
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun /* Validate based upon the type of resource - fixed length or variable */
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun switch (acpi_gbl_resource_types[resource_index]) {
322*4882a593Smuzhiyun case ACPI_FIXED_LENGTH:
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun /* Fixed length resource, length must match exactly */
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if (resource_length != minimum_resource_length) {
327*4882a593Smuzhiyun goto bad_resource_length;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun break;
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun case ACPI_VARIABLE_LENGTH:
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* Variable length resource, length must be at least the minimum */
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (resource_length < minimum_resource_length) {
336*4882a593Smuzhiyun goto bad_resource_length;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun break;
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun case ACPI_SMALL_VARIABLE_LENGTH:
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /* Small variable length resource, length can be (Min) or (Min-1) */
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun if ((resource_length > minimum_resource_length) ||
345*4882a593Smuzhiyun (resource_length < (minimum_resource_length - 1))) {
346*4882a593Smuzhiyun goto bad_resource_length;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun break;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun default:
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun /* Shouldn't happen (because of validation earlier), but be sure */
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun goto invalid_resource;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
358*4882a593Smuzhiyun if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) {
359*4882a593Smuzhiyun
360*4882a593Smuzhiyun /* Validate the bus_type field */
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun if ((aml_resource->common_serial_bus.type == 0) ||
363*4882a593Smuzhiyun (aml_resource->common_serial_bus.type >
364*4882a593Smuzhiyun AML_RESOURCE_MAX_SERIALBUSTYPE)) {
365*4882a593Smuzhiyun if (walk_state) {
366*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
367*4882a593Smuzhiyun "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X",
368*4882a593Smuzhiyun aml_resource->common_serial_bus.
369*4882a593Smuzhiyun type));
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun return (AE_AML_INVALID_RESOURCE_TYPE);
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun /* Optionally return the resource table index */
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun if (return_index) {
378*4882a593Smuzhiyun *return_index = resource_index;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun return (AE_OK);
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun invalid_resource:
384*4882a593Smuzhiyun
385*4882a593Smuzhiyun if (walk_state) {
386*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
387*4882a593Smuzhiyun "Invalid/unsupported resource descriptor: Type 0x%2.2X",
388*4882a593Smuzhiyun resource_type));
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun return (AE_AML_INVALID_RESOURCE_TYPE);
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun bad_resource_length:
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun if (walk_state) {
395*4882a593Smuzhiyun ACPI_ERROR((AE_INFO,
396*4882a593Smuzhiyun "Invalid resource descriptor length: Type "
397*4882a593Smuzhiyun "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X",
398*4882a593Smuzhiyun resource_type, resource_length,
399*4882a593Smuzhiyun minimum_resource_length));
400*4882a593Smuzhiyun }
401*4882a593Smuzhiyun return (AE_AML_BAD_RESOURCE_LENGTH);
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun /*******************************************************************************
405*4882a593Smuzhiyun *
406*4882a593Smuzhiyun * FUNCTION: acpi_ut_get_resource_type
407*4882a593Smuzhiyun *
408*4882a593Smuzhiyun * PARAMETERS: aml - Pointer to the raw AML resource descriptor
409*4882a593Smuzhiyun *
410*4882a593Smuzhiyun * RETURN: The Resource Type with no extraneous bits (except the
411*4882a593Smuzhiyun * Large/Small descriptor bit -- this is left alone)
412*4882a593Smuzhiyun *
413*4882a593Smuzhiyun * DESCRIPTION: Extract the Resource Type/Name from the first byte of
414*4882a593Smuzhiyun * a resource descriptor.
415*4882a593Smuzhiyun *
416*4882a593Smuzhiyun ******************************************************************************/
417*4882a593Smuzhiyun
acpi_ut_get_resource_type(void * aml)418*4882a593Smuzhiyun u8 acpi_ut_get_resource_type(void *aml)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
421*4882a593Smuzhiyun
422*4882a593Smuzhiyun /*
423*4882a593Smuzhiyun * Byte 0 contains the descriptor name (Resource Type)
424*4882a593Smuzhiyun * Examine the large/small bit in the resource header
425*4882a593Smuzhiyun */
426*4882a593Smuzhiyun if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun /* Large Resource Type -- bits 6:0 contain the name */
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun return (ACPI_GET8(aml));
431*4882a593Smuzhiyun } else {
432*4882a593Smuzhiyun /* Small Resource Type -- bits 6:3 contain the name */
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK));
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun /*******************************************************************************
439*4882a593Smuzhiyun *
440*4882a593Smuzhiyun * FUNCTION: acpi_ut_get_resource_length
441*4882a593Smuzhiyun *
442*4882a593Smuzhiyun * PARAMETERS: aml - Pointer to the raw AML resource descriptor
443*4882a593Smuzhiyun *
444*4882a593Smuzhiyun * RETURN: Byte Length
445*4882a593Smuzhiyun *
446*4882a593Smuzhiyun * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
447*4882a593Smuzhiyun * definition, this does not include the size of the descriptor
448*4882a593Smuzhiyun * header or the length field itself.
449*4882a593Smuzhiyun *
450*4882a593Smuzhiyun ******************************************************************************/
451*4882a593Smuzhiyun
acpi_ut_get_resource_length(void * aml)452*4882a593Smuzhiyun u16 acpi_ut_get_resource_length(void *aml)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun acpi_rs_length resource_length;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
457*4882a593Smuzhiyun
458*4882a593Smuzhiyun /*
459*4882a593Smuzhiyun * Byte 0 contains the descriptor name (Resource Type)
460*4882a593Smuzhiyun * Examine the large/small bit in the resource header
461*4882a593Smuzhiyun */
462*4882a593Smuzhiyun if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun /* Large Resource type -- bytes 1-2 contain the 16-bit length */
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1));
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun } else {
469*4882a593Smuzhiyun /* Small Resource type -- bits 2:0 of byte 0 contain the length */
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun resource_length = (u16) (ACPI_GET8(aml) &
472*4882a593Smuzhiyun ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun return (resource_length);
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun /*******************************************************************************
479*4882a593Smuzhiyun *
480*4882a593Smuzhiyun * FUNCTION: acpi_ut_get_resource_header_length
481*4882a593Smuzhiyun *
482*4882a593Smuzhiyun * PARAMETERS: aml - Pointer to the raw AML resource descriptor
483*4882a593Smuzhiyun *
484*4882a593Smuzhiyun * RETURN: Length of the AML header (depends on large/small descriptor)
485*4882a593Smuzhiyun *
486*4882a593Smuzhiyun * DESCRIPTION: Get the length of the header for this resource.
487*4882a593Smuzhiyun *
488*4882a593Smuzhiyun ******************************************************************************/
489*4882a593Smuzhiyun
acpi_ut_get_resource_header_length(void * aml)490*4882a593Smuzhiyun u8 acpi_ut_get_resource_header_length(void *aml)
491*4882a593Smuzhiyun {
492*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
493*4882a593Smuzhiyun
494*4882a593Smuzhiyun /* Examine the large/small bit in the resource header */
495*4882a593Smuzhiyun
496*4882a593Smuzhiyun if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) {
497*4882a593Smuzhiyun return (sizeof(struct aml_resource_large_header));
498*4882a593Smuzhiyun } else {
499*4882a593Smuzhiyun return (sizeof(struct aml_resource_small_header));
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun /*******************************************************************************
504*4882a593Smuzhiyun *
505*4882a593Smuzhiyun * FUNCTION: acpi_ut_get_descriptor_length
506*4882a593Smuzhiyun *
507*4882a593Smuzhiyun * PARAMETERS: aml - Pointer to the raw AML resource descriptor
508*4882a593Smuzhiyun *
509*4882a593Smuzhiyun * RETURN: Byte length
510*4882a593Smuzhiyun *
511*4882a593Smuzhiyun * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
512*4882a593Smuzhiyun * length of the descriptor header and the length field itself.
513*4882a593Smuzhiyun * Used to walk descriptor lists.
514*4882a593Smuzhiyun *
515*4882a593Smuzhiyun ******************************************************************************/
516*4882a593Smuzhiyun
acpi_ut_get_descriptor_length(void * aml)517*4882a593Smuzhiyun u32 acpi_ut_get_descriptor_length(void *aml)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun ACPI_FUNCTION_ENTRY();
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /*
522*4882a593Smuzhiyun * Get the Resource Length (does not include header length) and add
523*4882a593Smuzhiyun * the header length (depends on if this is a small or large resource)
524*4882a593Smuzhiyun */
525*4882a593Smuzhiyun return (acpi_ut_get_resource_length(aml) +
526*4882a593Smuzhiyun acpi_ut_get_resource_header_length(aml));
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /*******************************************************************************
530*4882a593Smuzhiyun *
531*4882a593Smuzhiyun * FUNCTION: acpi_ut_get_resource_end_tag
532*4882a593Smuzhiyun *
533*4882a593Smuzhiyun * PARAMETERS: obj_desc - The resource template buffer object
534*4882a593Smuzhiyun * end_tag - Where the pointer to the end_tag is returned
535*4882a593Smuzhiyun *
536*4882a593Smuzhiyun * RETURN: Status, pointer to the end tag
537*4882a593Smuzhiyun *
538*4882a593Smuzhiyun * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template
539*4882a593Smuzhiyun * Note: allows a buffer length of zero.
540*4882a593Smuzhiyun *
541*4882a593Smuzhiyun ******************************************************************************/
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun acpi_status
acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc,u8 ** end_tag)544*4882a593Smuzhiyun acpi_ut_get_resource_end_tag(union acpi_operand_object *obj_desc, u8 **end_tag)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun acpi_status status;
547*4882a593Smuzhiyun
548*4882a593Smuzhiyun ACPI_FUNCTION_TRACE(ut_get_resource_end_tag);
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun /* Allow a buffer length of zero */
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun if (!obj_desc->buffer.length) {
553*4882a593Smuzhiyun *end_tag = obj_desc->buffer.pointer;
554*4882a593Smuzhiyun return_ACPI_STATUS(AE_OK);
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /* Validate the template and get a pointer to the end_tag */
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun status = acpi_ut_walk_aml_resources(NULL, obj_desc->buffer.pointer,
560*4882a593Smuzhiyun obj_desc->buffer.length, NULL,
561*4882a593Smuzhiyun (void **)end_tag);
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun return_ACPI_STATUS(status);
564*4882a593Smuzhiyun }
565