Commit | Line | Data |
---|---|---|
96db255c BM |
1 | /******************************************************************************* |
2 | * | |
3c5f9be4 | 3 | * Module Name: utresrc - Resource management utilities |
96db255c BM |
4 | * |
5 | ******************************************************************************/ | |
6 | ||
7 | /* | |
77848130 | 8 | * Copyright (C) 2000 - 2012, Intel Corp. |
96db255c BM |
9 | * All rights reserved. |
10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions, and the following disclaimer, | |
16 | * without modification. | |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | |
18 | * substantially similar to the "NO WARRANTY" disclaimer below | |
19 | * ("Disclaimer") and any redistribution must be conditioned upon | |
20 | * including a substantially similar Disclaimer requirement for further | |
21 | * binary redistribution. | |
22 | * 3. Neither the names of the above-listed copyright holders nor the names | |
23 | * of any contributors may be used to endorse or promote products derived | |
24 | * from this software without specific prior written permission. | |
25 | * | |
26 | * Alternatively, this software may be distributed under the terms of the | |
27 | * GNU General Public License ("GPL") version 2 as published by the Free | |
28 | * Software Foundation. | |
29 | * | |
30 | * NO WARRANTY | |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
41 | * POSSIBILITY OF SUCH DAMAGES. | |
42 | */ | |
43 | ||
44 | #include <acpi/acpi.h> | |
e2f7a777 | 45 | #include "accommon.h" |
e0fe0a8d | 46 | #include "acresrc.h" |
96db255c BM |
47 | |
48 | #define _COMPONENT ACPI_UTILITIES | |
b229cf92 | 49 | ACPI_MODULE_NAME("utresrc") |
defba1d8 BM |
50 | #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUGGER) |
51 | /* | |
52 | * Strings used to decode resource descriptors. | |
70f23fd6 | 53 | * Used by both the disassembler and the debugger resource dump routines |
defba1d8 | 54 | */ |
b229cf92 BM |
55 | const char *acpi_gbl_bm_decode[] = { |
56 | "NotBusMaster", | |
57 | "BusMaster" | |
defba1d8 BM |
58 | }; |
59 | ||
b229cf92 | 60 | const char *acpi_gbl_config_decode[] = { |
defba1d8 BM |
61 | "0 - Good Configuration", |
62 | "1 - Acceptable Configuration", | |
63 | "2 - Suboptimal Configuration", | |
64 | "3 - ***Invalid Configuration***", | |
65 | }; | |
66 | ||
b229cf92 BM |
67 | const char *acpi_gbl_consume_decode[] = { |
68 | "ResourceProducer", | |
69 | "ResourceConsumer" | |
defba1d8 BM |
70 | }; |
71 | ||
b229cf92 BM |
72 | const char *acpi_gbl_dec_decode[] = { |
73 | "PosDecode", | |
74 | "SubDecode" | |
defba1d8 BM |
75 | }; |
76 | ||
b229cf92 | 77 | const char *acpi_gbl_he_decode[] = { |
defba1d8 BM |
78 | "Level", |
79 | "Edge" | |
80 | }; | |
81 | ||
b229cf92 | 82 | const char *acpi_gbl_io_decode[] = { |
defba1d8 BM |
83 | "Decode10", |
84 | "Decode16" | |
85 | }; | |
86 | ||
b229cf92 BM |
87 | const char *acpi_gbl_ll_decode[] = { |
88 | "ActiveHigh", | |
89 | "ActiveLow" | |
defba1d8 BM |
90 | }; |
91 | ||
b229cf92 BM |
92 | const char *acpi_gbl_max_decode[] = { |
93 | "MaxNotFixed", | |
94 | "MaxFixed" | |
defba1d8 BM |
95 | }; |
96 | ||
b229cf92 BM |
97 | const char *acpi_gbl_mem_decode[] = { |
98 | "NonCacheable", | |
defba1d8 | 99 | "Cacheable", |
b229cf92 | 100 | "WriteCombining", |
defba1d8 BM |
101 | "Prefetchable" |
102 | }; | |
103 | ||
b229cf92 BM |
104 | const char *acpi_gbl_min_decode[] = { |
105 | "MinNotFixed", | |
106 | "MinFixed" | |
defba1d8 BM |
107 | }; |
108 | ||
b229cf92 BM |
109 | const char *acpi_gbl_mtp_decode[] = { |
110 | "AddressRangeMemory", | |
111 | "AddressRangeReserved", | |
112 | "AddressRangeACPI", | |
113 | "AddressRangeNVS" | |
defba1d8 BM |
114 | }; |
115 | ||
b229cf92 BM |
116 | const char *acpi_gbl_rng_decode[] = { |
117 | "InvalidRanges", | |
118 | "NonISAOnlyRanges", | |
119 | "ISAOnlyRanges", | |
120 | "EntireRange" | |
defba1d8 BM |
121 | }; |
122 | ||
b229cf92 BM |
123 | const char *acpi_gbl_rw_decode[] = { |
124 | "ReadOnly", | |
125 | "ReadWrite" | |
defba1d8 BM |
126 | }; |
127 | ||
b229cf92 | 128 | const char *acpi_gbl_shr_decode[] = { |
defba1d8 BM |
129 | "Exclusive", |
130 | "Shared" | |
131 | }; | |
132 | ||
b229cf92 | 133 | const char *acpi_gbl_siz_decode[] = { |
defba1d8 BM |
134 | "Transfer8", |
135 | "Transfer8_16", | |
136 | "Transfer16", | |
b229cf92 | 137 | "InvalidSize" |
defba1d8 BM |
138 | }; |
139 | ||
b229cf92 BM |
140 | const char *acpi_gbl_trs_decode[] = { |
141 | "DenseTranslation", | |
142 | "SparseTranslation" | |
defba1d8 BM |
143 | }; |
144 | ||
b229cf92 BM |
145 | const char *acpi_gbl_ttp_decode[] = { |
146 | "TypeStatic", | |
147 | "TypeTranslation" | |
defba1d8 BM |
148 | }; |
149 | ||
b229cf92 | 150 | const char *acpi_gbl_typ_decode[] = { |
defba1d8 | 151 | "Compatibility", |
b229cf92 BM |
152 | "TypeA", |
153 | "TypeB", | |
154 | "TypeF" | |
defba1d8 BM |
155 | }; |
156 | ||
e0fe0a8d LM |
157 | const char *acpi_gbl_ppc_decode[] = { |
158 | "PullDefault", | |
159 | "PullUp", | |
160 | "PullDown", | |
161 | "PullNone" | |
162 | }; | |
163 | ||
164 | const char *acpi_gbl_ior_decode[] = { | |
165 | "IoRestrictionNone", | |
166 | "IoRestrictionInputOnly", | |
167 | "IoRestrictionOutputOnly", | |
168 | "IoRestrictionNoneAndPreserve" | |
169 | }; | |
170 | ||
171 | const char *acpi_gbl_dts_decode[] = { | |
172 | "Width8bit", | |
173 | "Width16bit", | |
174 | "Width32bit", | |
175 | "Width64bit", | |
176 | "Width128bit", | |
177 | "Width256bit", | |
178 | }; | |
179 | ||
180 | /* GPIO connection type */ | |
181 | ||
182 | const char *acpi_gbl_ct_decode[] = { | |
183 | "Interrupt", | |
184 | "I/O" | |
185 | }; | |
186 | ||
187 | /* Serial bus type */ | |
188 | ||
189 | const char *acpi_gbl_sbt_decode[] = { | |
190 | "/* UNKNOWN serial bus type */", | |
191 | "I2C", | |
192 | "SPI", | |
193 | "UART" | |
194 | }; | |
195 | ||
196 | /* I2C serial bus access mode */ | |
197 | ||
198 | const char *acpi_gbl_am_decode[] = { | |
199 | "AddressingMode7Bit", | |
200 | "AddressingMode10Bit" | |
201 | }; | |
202 | ||
203 | /* I2C serial bus slave mode */ | |
204 | ||
205 | const char *acpi_gbl_sm_decode[] = { | |
206 | "ControllerInitiated", | |
207 | "DeviceInitiated" | |
208 | }; | |
209 | ||
210 | /* SPI serial bus wire mode */ | |
211 | ||
212 | const char *acpi_gbl_wm_decode[] = { | |
213 | "FourWireMode", | |
214 | "ThreeWireMode" | |
215 | }; | |
216 | ||
217 | /* SPI serial clock phase */ | |
218 | ||
219 | const char *acpi_gbl_cph_decode[] = { | |
220 | "ClockPhaseFirst", | |
221 | "ClockPhaseSecond" | |
222 | }; | |
223 | ||
224 | /* SPI serial bus clock polarity */ | |
225 | ||
226 | const char *acpi_gbl_cpo_decode[] = { | |
227 | "ClockPolarityLow", | |
228 | "ClockPolarityHigh" | |
229 | }; | |
230 | ||
231 | /* SPI serial bus device polarity */ | |
232 | ||
233 | const char *acpi_gbl_dp_decode[] = { | |
234 | "PolarityLow", | |
235 | "PolarityHigh" | |
236 | }; | |
237 | ||
238 | /* UART serial bus endian */ | |
239 | ||
240 | const char *acpi_gbl_ed_decode[] = { | |
241 | "LittleEndian", | |
242 | "BigEndian" | |
243 | }; | |
244 | ||
245 | /* UART serial bus bits per byte */ | |
246 | ||
247 | const char *acpi_gbl_bpb_decode[] = { | |
248 | "DataBitsFive", | |
249 | "DataBitsSix", | |
250 | "DataBitsSeven", | |
251 | "DataBitsEight", | |
252 | "DataBitsNine", | |
253 | "/* UNKNOWN Bits per byte */", | |
254 | "/* UNKNOWN Bits per byte */", | |
255 | "/* UNKNOWN Bits per byte */" | |
256 | }; | |
257 | ||
258 | /* UART serial bus stop bits */ | |
259 | ||
260 | const char *acpi_gbl_sb_decode[] = { | |
261 | "StopBitsNone", | |
262 | "StopBitsOne", | |
263 | "StopBitsOnePlusHalf", | |
264 | "StopBitsTwo" | |
265 | }; | |
266 | ||
267 | /* UART serial bus flow control */ | |
268 | ||
269 | const char *acpi_gbl_fc_decode[] = { | |
270 | "FlowControlNone", | |
271 | "FlowControlHardware", | |
272 | "FlowControlXON", | |
273 | "/* UNKNOWN flow control keyword */" | |
274 | }; | |
275 | ||
276 | /* UART serial bus parity type */ | |
277 | ||
278 | const char *acpi_gbl_pt_decode[] = { | |
279 | "ParityTypeNone", | |
280 | "ParityTypeEven", | |
281 | "ParityTypeOdd", | |
282 | "ParityTypeMark", | |
283 | "ParityTypeSpace", | |
284 | "/* UNKNOWN parity keyword */", | |
285 | "/* UNKNOWN parity keyword */", | |
286 | "/* UNKNOWN parity keyword */" | |
287 | }; | |
288 | ||
defba1d8 BM |
289 | #endif |
290 | ||
96db255c BM |
291 | /* |
292 | * Base sizes of the raw AML resource descriptors, indexed by resource type. | |
293 | * Zero indicates a reserved (and therefore invalid) resource type. | |
294 | */ | |
295 | const u8 acpi_gbl_resource_aml_sizes[] = { | |
296 | /* Small descriptors */ | |
297 | ||
298 | 0, | |
299 | 0, | |
300 | 0, | |
301 | 0, | |
302 | ACPI_AML_SIZE_SMALL(struct aml_resource_irq), | |
303 | ACPI_AML_SIZE_SMALL(struct aml_resource_dma), | |
304 | ACPI_AML_SIZE_SMALL(struct aml_resource_start_dependent), | |
305 | ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), | |
306 | ACPI_AML_SIZE_SMALL(struct aml_resource_io), | |
307 | ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), | |
e0fe0a8d | 308 | ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma), |
96db255c BM |
309 | 0, |
310 | 0, | |
311 | 0, | |
312 | ACPI_AML_SIZE_SMALL(struct aml_resource_vendor_small), | |
313 | ACPI_AML_SIZE_SMALL(struct aml_resource_end_tag), | |
314 | ||
315 | /* Large descriptors */ | |
316 | ||
317 | 0, | |
318 | ACPI_AML_SIZE_LARGE(struct aml_resource_memory24), | |
319 | ACPI_AML_SIZE_LARGE(struct aml_resource_generic_register), | |
320 | 0, | |
321 | ACPI_AML_SIZE_LARGE(struct aml_resource_vendor_large), | |
322 | ACPI_AML_SIZE_LARGE(struct aml_resource_memory32), | |
323 | ACPI_AML_SIZE_LARGE(struct aml_resource_fixed_memory32), | |
324 | ACPI_AML_SIZE_LARGE(struct aml_resource_address32), | |
325 | ACPI_AML_SIZE_LARGE(struct aml_resource_address16), | |
326 | ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), | |
327 | ACPI_AML_SIZE_LARGE(struct aml_resource_address64), | |
e0fe0a8d LM |
328 | ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64), |
329 | ACPI_AML_SIZE_LARGE(struct aml_resource_gpio), | |
330 | 0, | |
331 | ACPI_AML_SIZE_LARGE(struct aml_resource_common_serialbus), | |
332 | }; | |
333 | ||
334 | const u8 acpi_gbl_resource_aml_serial_bus_sizes[] = { | |
335 | 0, | |
336 | ACPI_AML_SIZE_LARGE(struct aml_resource_i2c_serialbus), | |
337 | ACPI_AML_SIZE_LARGE(struct aml_resource_spi_serialbus), | |
338 | ACPI_AML_SIZE_LARGE(struct aml_resource_uart_serialbus), | |
96db255c BM |
339 | }; |
340 | ||
341 | /* | |
342 | * Resource types, used to validate the resource length field. | |
343 | * The length of fixed-length types must match exactly, variable | |
344 | * lengths must meet the minimum required length, etc. | |
345 | * Zero indicates a reserved (and therefore invalid) resource type. | |
346 | */ | |
347 | static const u8 acpi_gbl_resource_types[] = { | |
348 | /* Small descriptors */ | |
349 | ||
350 | 0, | |
351 | 0, | |
352 | 0, | |
353 | 0, | |
e0fe0a8d LM |
354 | ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ |
355 | ACPI_FIXED_LENGTH, /* 05 DMA */ | |
356 | ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */ | |
357 | ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */ | |
358 | ACPI_FIXED_LENGTH, /* 08 IO */ | |
ba494bee BM |
359 | ACPI_FIXED_LENGTH, /* 09 fixed_IO */ |
360 | ACPI_FIXED_LENGTH, /* 0A fixed_DMA */ | |
96db255c BM |
361 | 0, |
362 | 0, | |
363 | 0, | |
ba494bee BM |
364 | ACPI_VARIABLE_LENGTH, /* 0E vendor_short */ |
365 | ACPI_FIXED_LENGTH, /* 0F end_tag */ | |
96db255c BM |
366 | |
367 | /* Large descriptors */ | |
368 | ||
369 | 0, | |
e0fe0a8d LM |
370 | ACPI_FIXED_LENGTH, /* 01 Memory24 */ |
371 | ACPI_FIXED_LENGTH, /* 02 generic_register */ | |
96db255c | 372 | 0, |
e0fe0a8d LM |
373 | ACPI_VARIABLE_LENGTH, /* 04 vendor_long */ |
374 | ACPI_FIXED_LENGTH, /* 05 Memory32 */ | |
375 | ACPI_FIXED_LENGTH, /* 06 memory32_fixed */ | |
376 | ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ | |
377 | ACPI_VARIABLE_LENGTH, /* 08 Word* address */ | |
ba494bee BM |
378 | ACPI_VARIABLE_LENGTH, /* 09 extended_IRQ */ |
379 | ACPI_VARIABLE_LENGTH, /* 0A Qword* address */ | |
380 | ACPI_FIXED_LENGTH, /* 0B Extended* address */ | |
381 | ACPI_VARIABLE_LENGTH, /* 0C Gpio* */ | |
e0fe0a8d | 382 | 0, |
ba494bee | 383 | ACPI_VARIABLE_LENGTH /* 0E *serial_bus */ |
96db255c BM |
384 | }; |
385 | ||
e0fe0a8d | 386 | /* |
ba494bee | 387 | * For the iASL compiler/disassembler, we don't want any error messages |
e0fe0a8d LM |
388 | * because the disassembler uses the resource validation code to determine |
389 | * if Buffer objects are actually Resource Templates. | |
390 | */ | |
391 | #ifdef ACPI_ASL_COMPILER | |
392 | #define ACPI_RESOURCE_ERROR(plist) | |
393 | #else | |
394 | #define ACPI_RESOURCE_ERROR(plist) ACPI_ERROR(plist) | |
395 | #endif | |
396 | ||
61686124 BM |
397 | /******************************************************************************* |
398 | * | |
399 | * FUNCTION: acpi_ut_walk_aml_resources | |
400 | * | |
ba494bee | 401 | * PARAMETERS: aml - Pointer to the raw AML resource template |
61686124 BM |
402 | * aml_length - Length of the entire template |
403 | * user_function - Called once for each descriptor found. If | |
404 | * NULL, a pointer to the end_tag is returned | |
ba494bee | 405 | * context - Passed to user_function |
61686124 BM |
406 | * |
407 | * RETURN: Status | |
408 | * | |
409 | * DESCRIPTION: Walk a raw AML resource list(buffer). User function called | |
410 | * once for each resource found. | |
411 | * | |
412 | ******************************************************************************/ | |
413 | ||
414 | acpi_status | |
415 | acpi_ut_walk_aml_resources(u8 * aml, | |
416 | acpi_size aml_length, | |
793c2388 | 417 | acpi_walk_aml_callback user_function, void **context) |
61686124 BM |
418 | { |
419 | acpi_status status; | |
420 | u8 *end_aml; | |
421 | u8 resource_index; | |
422 | u32 length; | |
423 | u32 offset = 0; | |
e0fe0a8d | 424 | u8 end_tag[2] = { 0x79, 0x00 }; |
61686124 | 425 | |
b229cf92 | 426 | ACPI_FUNCTION_TRACE(ut_walk_aml_resources); |
61686124 BM |
427 | |
428 | /* The absolute minimum resource template is one end_tag descriptor */ | |
429 | ||
430 | if (aml_length < sizeof(struct aml_resource_end_tag)) { | |
431 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); | |
432 | } | |
433 | ||
434 | /* Point to the end of the resource template buffer */ | |
435 | ||
436 | end_aml = aml + aml_length; | |
437 | ||
438 | /* Walk the byte list, abort on any invalid descriptor type or length */ | |
439 | ||
440 | while (aml < end_aml) { | |
441 | ||
442 | /* Validate the Resource Type and Resource Length */ | |
443 | ||
444 | status = acpi_ut_validate_resource(aml, &resource_index); | |
445 | if (ACPI_FAILURE(status)) { | |
e0fe0a8d LM |
446 | /* |
447 | * Exit on failure. Cannot continue because the descriptor length | |
448 | * may be bogus also. | |
449 | */ | |
61686124 BM |
450 | return_ACPI_STATUS(status); |
451 | } | |
452 | ||
453 | /* Get the length of this descriptor */ | |
454 | ||
455 | length = acpi_ut_get_descriptor_length(aml); | |
456 | ||
457 | /* Invoke the user function */ | |
458 | ||
459 | if (user_function) { | |
460 | status = | |
461 | user_function(aml, length, offset, resource_index, | |
462 | context); | |
463 | if (ACPI_FAILURE(status)) { | |
e0fe0a8d | 464 | return_ACPI_STATUS(status); |
61686124 BM |
465 | } |
466 | } | |
467 | ||
468 | /* An end_tag descriptor terminates this resource template */ | |
469 | ||
470 | if (acpi_ut_get_resource_type(aml) == | |
471 | ACPI_RESOURCE_NAME_END_TAG) { | |
472 | /* | |
473 | * There must be at least one more byte in the buffer for | |
474 | * the 2nd byte of the end_tag | |
475 | */ | |
476 | if ((aml + 1) >= end_aml) { | |
477 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); | |
478 | } | |
479 | ||
480 | /* Return the pointer to the end_tag if requested */ | |
481 | ||
482 | if (!user_function) { | |
793c2388 | 483 | *context = aml; |
61686124 BM |
484 | } |
485 | ||
486 | /* Normal exit */ | |
487 | ||
488 | return_ACPI_STATUS(AE_OK); | |
489 | } | |
490 | ||
491 | aml += length; | |
492 | offset += length; | |
493 | } | |
494 | ||
495 | /* Did not find an end_tag descriptor */ | |
496 | ||
e0fe0a8d LM |
497 | if (user_function) { |
498 | ||
499 | /* Insert an end_tag anyway. acpi_rs_get_list_length always leaves room */ | |
500 | ||
501 | (void)acpi_ut_validate_resource(end_tag, &resource_index); | |
502 | status = | |
503 | user_function(end_tag, 2, offset, resource_index, context); | |
504 | if (ACPI_FAILURE(status)) { | |
505 | return_ACPI_STATUS(status); | |
506 | } | |
507 | } | |
508 | ||
509 | return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG); | |
61686124 BM |
510 | } |
511 | ||
96db255c BM |
512 | /******************************************************************************* |
513 | * | |
514 | * FUNCTION: acpi_ut_validate_resource | |
515 | * | |
ba494bee | 516 | * PARAMETERS: aml - Pointer to the raw AML resource descriptor |
96db255c BM |
517 | * return_index - Where the resource index is returned. NULL |
518 | * if the index is not required. | |
519 | * | |
520 | * RETURN: Status, and optionally the Index into the global resource tables | |
521 | * | |
522 | * DESCRIPTION: Validate an AML resource descriptor by checking the Resource | |
523 | * Type and Resource Length. Returns an index into the global | |
524 | * resource information/dispatch tables for later use. | |
525 | * | |
526 | ******************************************************************************/ | |
527 | ||
528 | acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |
529 | { | |
e0fe0a8d | 530 | union aml_resource *aml_resource; |
96db255c BM |
531 | u8 resource_type; |
532 | u8 resource_index; | |
533 | acpi_rs_length resource_length; | |
534 | acpi_rs_length minimum_resource_length; | |
535 | ||
536 | ACPI_FUNCTION_ENTRY(); | |
537 | ||
538 | /* | |
539 | * 1) Validate the resource_type field (Byte 0) | |
540 | */ | |
c51a4de8 | 541 | resource_type = ACPI_GET8(aml); |
96db255c BM |
542 | |
543 | /* | |
544 | * Byte 0 contains the descriptor name (Resource Type) | |
545 | * Examine the large/small bit in the resource header | |
546 | */ | |
547 | if (resource_type & ACPI_RESOURCE_NAME_LARGE) { | |
52fc0b02 | 548 | |
96db255c BM |
549 | /* Verify the large resource type (name) against the max */ |
550 | ||
551 | if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { | |
e0fe0a8d | 552 | goto invalid_resource; |
96db255c BM |
553 | } |
554 | ||
555 | /* | |
556 | * Large Resource Type -- bits 6:0 contain the name | |
557 | * Translate range 0x80-0x8B to index range 0x10-0x1B | |
558 | */ | |
559 | resource_index = (u8) (resource_type - 0x70); | |
560 | } else { | |
561 | /* | |
562 | * Small Resource Type -- bits 6:3 contain the name | |
563 | * Shift range to index range 0x00-0x0F | |
564 | */ | |
565 | resource_index = (u8) | |
566 | ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); | |
567 | } | |
568 | ||
e0fe0a8d LM |
569 | /* |
570 | * Check validity of the resource type, via acpi_gbl_resource_types. Zero | |
571 | * indicates an invalid resource. | |
572 | */ | |
96db255c | 573 | if (!acpi_gbl_resource_types[resource_index]) { |
e0fe0a8d | 574 | goto invalid_resource; |
96db255c BM |
575 | } |
576 | ||
577 | /* | |
e0fe0a8d LM |
578 | * Validate the resource_length field. This ensures that the length |
579 | * is at least reasonable, and guarantees that it is non-zero. | |
96db255c BM |
580 | */ |
581 | resource_length = acpi_ut_get_resource_length(aml); | |
582 | minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; | |
583 | ||
584 | /* Validate based upon the type of resource - fixed length or variable */ | |
585 | ||
586 | switch (acpi_gbl_resource_types[resource_index]) { | |
587 | case ACPI_FIXED_LENGTH: | |
588 | ||
589 | /* Fixed length resource, length must match exactly */ | |
590 | ||
591 | if (resource_length != minimum_resource_length) { | |
e0fe0a8d | 592 | goto bad_resource_length; |
96db255c BM |
593 | } |
594 | break; | |
595 | ||
596 | case ACPI_VARIABLE_LENGTH: | |
597 | ||
598 | /* Variable length resource, length must be at least the minimum */ | |
599 | ||
600 | if (resource_length < minimum_resource_length) { | |
e0fe0a8d | 601 | goto bad_resource_length; |
96db255c BM |
602 | } |
603 | break; | |
604 | ||
605 | case ACPI_SMALL_VARIABLE_LENGTH: | |
606 | ||
607 | /* Small variable length resource, length can be (Min) or (Min-1) */ | |
608 | ||
609 | if ((resource_length > minimum_resource_length) || | |
610 | (resource_length < (minimum_resource_length - 1))) { | |
e0fe0a8d | 611 | goto bad_resource_length; |
96db255c BM |
612 | } |
613 | break; | |
614 | ||
615 | default: | |
616 | ||
617 | /* Shouldn't happen (because of validation earlier), but be sure */ | |
618 | ||
e0fe0a8d LM |
619 | goto invalid_resource; |
620 | } | |
621 | ||
622 | aml_resource = ACPI_CAST_PTR(union aml_resource, aml); | |
623 | if (resource_type == ACPI_RESOURCE_NAME_SERIAL_BUS) { | |
624 | ||
625 | /* Validate the bus_type field */ | |
626 | ||
627 | if ((aml_resource->common_serial_bus.type == 0) || | |
628 | (aml_resource->common_serial_bus.type > | |
629 | AML_RESOURCE_MAX_SERIALBUSTYPE)) { | |
630 | ACPI_RESOURCE_ERROR((AE_INFO, | |
631 | "Invalid/unsupported SerialBus resource descriptor: BusType 0x%2.2X", | |
632 | aml_resource->common_serial_bus. | |
633 | type)); | |
634 | return (AE_AML_INVALID_RESOURCE_TYPE); | |
635 | } | |
96db255c BM |
636 | } |
637 | ||
638 | /* Optionally return the resource table index */ | |
639 | ||
640 | if (return_index) { | |
641 | *return_index = resource_index; | |
642 | } | |
643 | ||
644 | return (AE_OK); | |
e0fe0a8d LM |
645 | |
646 | invalid_resource: | |
647 | ||
648 | ACPI_RESOURCE_ERROR((AE_INFO, | |
649 | "Invalid/unsupported resource descriptor: Type 0x%2.2X", | |
650 | resource_type)); | |
651 | return (AE_AML_INVALID_RESOURCE_TYPE); | |
652 | ||
653 | bad_resource_length: | |
654 | ||
655 | ACPI_RESOURCE_ERROR((AE_INFO, | |
656 | "Invalid resource descriptor length: Type " | |
657 | "0x%2.2X, Length 0x%4.4X, MinLength 0x%4.4X", | |
658 | resource_type, resource_length, | |
659 | minimum_resource_length)); | |
660 | return (AE_AML_BAD_RESOURCE_LENGTH); | |
96db255c BM |
661 | } |
662 | ||
663 | /******************************************************************************* | |
664 | * | |
665 | * FUNCTION: acpi_ut_get_resource_type | |
666 | * | |
ba494bee | 667 | * PARAMETERS: aml - Pointer to the raw AML resource descriptor |
96db255c BM |
668 | * |
669 | * RETURN: The Resource Type with no extraneous bits (except the | |
670 | * Large/Small descriptor bit -- this is left alone) | |
671 | * | |
672 | * DESCRIPTION: Extract the Resource Type/Name from the first byte of | |
673 | * a resource descriptor. | |
674 | * | |
675 | ******************************************************************************/ | |
676 | ||
677 | u8 acpi_ut_get_resource_type(void *aml) | |
678 | { | |
679 | ACPI_FUNCTION_ENTRY(); | |
680 | ||
681 | /* | |
682 | * Byte 0 contains the descriptor name (Resource Type) | |
683 | * Examine the large/small bit in the resource header | |
684 | */ | |
c51a4de8 | 685 | if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { |
52fc0b02 | 686 | |
96db255c BM |
687 | /* Large Resource Type -- bits 6:0 contain the name */ |
688 | ||
c51a4de8 | 689 | return (ACPI_GET8(aml)); |
96db255c BM |
690 | } else { |
691 | /* Small Resource Type -- bits 6:3 contain the name */ | |
692 | ||
c51a4de8 | 693 | return ((u8) (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_SMALL_MASK)); |
96db255c BM |
694 | } |
695 | } | |
696 | ||
697 | /******************************************************************************* | |
698 | * | |
699 | * FUNCTION: acpi_ut_get_resource_length | |
700 | * | |
ba494bee | 701 | * PARAMETERS: aml - Pointer to the raw AML resource descriptor |
96db255c BM |
702 | * |
703 | * RETURN: Byte Length | |
704 | * | |
705 | * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By | |
706 | * definition, this does not include the size of the descriptor | |
707 | * header or the length field itself. | |
708 | * | |
709 | ******************************************************************************/ | |
710 | ||
711 | u16 acpi_ut_get_resource_length(void *aml) | |
712 | { | |
713 | acpi_rs_length resource_length; | |
714 | ||
715 | ACPI_FUNCTION_ENTRY(); | |
716 | ||
717 | /* | |
718 | * Byte 0 contains the descriptor name (Resource Type) | |
719 | * Examine the large/small bit in the resource header | |
720 | */ | |
c51a4de8 | 721 | if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { |
52fc0b02 | 722 | |
96db255c BM |
723 | /* Large Resource type -- bytes 1-2 contain the 16-bit length */ |
724 | ||
c51a4de8 | 725 | ACPI_MOVE_16_TO_16(&resource_length, ACPI_ADD_PTR(u8, aml, 1)); |
96db255c BM |
726 | |
727 | } else { | |
728 | /* Small Resource type -- bits 2:0 of byte 0 contain the length */ | |
729 | ||
c51a4de8 | 730 | resource_length = (u16) (ACPI_GET8(aml) & |
96db255c BM |
731 | ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK); |
732 | } | |
733 | ||
734 | return (resource_length); | |
735 | } | |
736 | ||
737 | /******************************************************************************* | |
738 | * | |
739 | * FUNCTION: acpi_ut_get_resource_header_length | |
740 | * | |
ba494bee | 741 | * PARAMETERS: aml - Pointer to the raw AML resource descriptor |
96db255c BM |
742 | * |
743 | * RETURN: Length of the AML header (depends on large/small descriptor) | |
744 | * | |
745 | * DESCRIPTION: Get the length of the header for this resource. | |
746 | * | |
747 | ******************************************************************************/ | |
748 | ||
749 | u8 acpi_ut_get_resource_header_length(void *aml) | |
750 | { | |
751 | ACPI_FUNCTION_ENTRY(); | |
752 | ||
753 | /* Examine the large/small bit in the resource header */ | |
754 | ||
c51a4de8 | 755 | if (ACPI_GET8(aml) & ACPI_RESOURCE_NAME_LARGE) { |
96db255c BM |
756 | return (sizeof(struct aml_resource_large_header)); |
757 | } else { | |
758 | return (sizeof(struct aml_resource_small_header)); | |
759 | } | |
760 | } | |
761 | ||
762 | /******************************************************************************* | |
763 | * | |
764 | * FUNCTION: acpi_ut_get_descriptor_length | |
765 | * | |
ba494bee | 766 | * PARAMETERS: aml - Pointer to the raw AML resource descriptor |
96db255c BM |
767 | * |
768 | * RETURN: Byte length | |
769 | * | |
770 | * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the | |
771 | * length of the descriptor header and the length field itself. | |
772 | * Used to walk descriptor lists. | |
773 | * | |
774 | ******************************************************************************/ | |
775 | ||
776 | u32 acpi_ut_get_descriptor_length(void *aml) | |
777 | { | |
778 | ACPI_FUNCTION_ENTRY(); | |
779 | ||
780 | /* | |
781 | * Get the Resource Length (does not include header length) and add | |
782 | * the header length (depends on if this is a small or large resource) | |
783 | */ | |
784 | return (acpi_ut_get_resource_length(aml) + | |
785 | acpi_ut_get_resource_header_length(aml)); | |
786 | } | |
787 | ||
788 | /******************************************************************************* | |
789 | * | |
790 | * FUNCTION: acpi_ut_get_resource_end_tag | |
791 | * | |
792 | * PARAMETERS: obj_desc - The resource template buffer object | |
c51a4de8 | 793 | * end_tag - Where the pointer to the end_tag is returned |
96db255c | 794 | * |
c51a4de8 | 795 | * RETURN: Status, pointer to the end tag |
96db255c BM |
796 | * |
797 | * DESCRIPTION: Find the end_tag resource descriptor in an AML resource template | |
b8e4d893 | 798 | * Note: allows a buffer length of zero. |
96db255c BM |
799 | * |
800 | ******************************************************************************/ | |
801 | ||
802 | acpi_status | |
803 | acpi_ut_get_resource_end_tag(union acpi_operand_object * obj_desc, | |
804 | u8 ** end_tag) | |
805 | { | |
806 | acpi_status status; | |
96db255c | 807 | |
b229cf92 | 808 | ACPI_FUNCTION_TRACE(ut_get_resource_end_tag); |
96db255c | 809 | |
b8e4d893 BM |
810 | /* Allow a buffer length of zero */ |
811 | ||
812 | if (!obj_desc->buffer.length) { | |
61686124 | 813 | *end_tag = obj_desc->buffer.pointer; |
b8e4d893 BM |
814 | return_ACPI_STATUS(AE_OK); |
815 | } | |
816 | ||
61686124 | 817 | /* Validate the template and get a pointer to the end_tag */ |
96db255c | 818 | |
61686124 BM |
819 | status = acpi_ut_walk_aml_resources(obj_desc->buffer.pointer, |
820 | obj_desc->buffer.length, NULL, | |
793c2388 | 821 | (void **)end_tag); |
96db255c | 822 | |
61686124 | 823 | return_ACPI_STATUS(status); |
96db255c | 824 | } |