diff options
Diffstat (limited to 'drivers/acpi/acpica/utresrc.c')
-rw-r--r-- | drivers/acpi/acpica/utresrc.c | 276 |
1 files changed, 242 insertions, 34 deletions
diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index 6ffd3a8bdaa5..cd7fbbf57f30 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c | |||
@@ -43,7 +43,7 @@ | |||
43 | 43 | ||
44 | #include <acpi/acpi.h> | 44 | #include <acpi/acpi.h> |
45 | #include "accommon.h" | 45 | #include "accommon.h" |
46 | #include "amlresrc.h" | 46 | #include "acresrc.h" |
47 | 47 | ||
48 | #define _COMPONENT ACPI_UTILITIES | 48 | #define _COMPONENT ACPI_UTILITIES |
49 | ACPI_MODULE_NAME("utresrc") | 49 | ACPI_MODULE_NAME("utresrc") |
@@ -154,6 +154,138 @@ const char *acpi_gbl_typ_decode[] = { | |||
154 | "TypeF" | 154 | "TypeF" |
155 | }; | 155 | }; |
156 | 156 | ||
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 | |||
157 | #endif | 289 | #endif |
158 | 290 | ||
159 | /* | 291 | /* |
@@ -173,7 +305,7 @@ const u8 acpi_gbl_resource_aml_sizes[] = { | |||
173 | ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), | 305 | ACPI_AML_SIZE_SMALL(struct aml_resource_end_dependent), |
174 | ACPI_AML_SIZE_SMALL(struct aml_resource_io), | 306 | ACPI_AML_SIZE_SMALL(struct aml_resource_io), |
175 | ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), | 307 | ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_io), |
176 | 0, | 308 | ACPI_AML_SIZE_SMALL(struct aml_resource_fixed_dma), |
177 | 0, | 309 | 0, |
178 | 0, | 310 | 0, |
179 | 0, | 311 | 0, |
@@ -193,7 +325,17 @@ const u8 acpi_gbl_resource_aml_sizes[] = { | |||
193 | ACPI_AML_SIZE_LARGE(struct aml_resource_address16), | 325 | ACPI_AML_SIZE_LARGE(struct aml_resource_address16), |
194 | ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), | 326 | ACPI_AML_SIZE_LARGE(struct aml_resource_extended_irq), |
195 | ACPI_AML_SIZE_LARGE(struct aml_resource_address64), | 327 | ACPI_AML_SIZE_LARGE(struct aml_resource_address64), |
196 | ACPI_AML_SIZE_LARGE(struct aml_resource_extended_address64) | 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), | ||
197 | }; | 339 | }; |
198 | 340 | ||
199 | /* | 341 | /* |
@@ -209,35 +351,49 @@ static const u8 acpi_gbl_resource_types[] = { | |||
209 | 0, | 351 | 0, |
210 | 0, | 352 | 0, |
211 | 0, | 353 | 0, |
212 | ACPI_SMALL_VARIABLE_LENGTH, | 354 | ACPI_SMALL_VARIABLE_LENGTH, /* 04 IRQ */ |
213 | ACPI_FIXED_LENGTH, | 355 | ACPI_FIXED_LENGTH, /* 05 DMA */ |
214 | ACPI_SMALL_VARIABLE_LENGTH, | 356 | ACPI_SMALL_VARIABLE_LENGTH, /* 06 start_dependent_functions */ |
215 | ACPI_FIXED_LENGTH, | 357 | ACPI_FIXED_LENGTH, /* 07 end_dependent_functions */ |
216 | ACPI_FIXED_LENGTH, | 358 | ACPI_FIXED_LENGTH, /* 08 IO */ |
217 | ACPI_FIXED_LENGTH, | 359 | ACPI_FIXED_LENGTH, /* 09 fixed_iO */ |
218 | 0, | 360 | ACPI_FIXED_LENGTH, /* 0_a fixed_dMA */ |
219 | 0, | 361 | 0, |
220 | 0, | 362 | 0, |
221 | 0, | 363 | 0, |
222 | ACPI_VARIABLE_LENGTH, | 364 | ACPI_VARIABLE_LENGTH, /* 0_e vendor_short */ |
223 | ACPI_FIXED_LENGTH, | 365 | ACPI_FIXED_LENGTH, /* 0_f end_tag */ |
224 | 366 | ||
225 | /* Large descriptors */ | 367 | /* Large descriptors */ |
226 | 368 | ||
227 | 0, | 369 | 0, |
228 | ACPI_FIXED_LENGTH, | 370 | ACPI_FIXED_LENGTH, /* 01 Memory24 */ |
229 | ACPI_FIXED_LENGTH, | 371 | ACPI_FIXED_LENGTH, /* 02 generic_register */ |
230 | 0, | 372 | 0, |
231 | ACPI_VARIABLE_LENGTH, | 373 | ACPI_VARIABLE_LENGTH, /* 04 vendor_long */ |
232 | ACPI_FIXED_LENGTH, | 374 | ACPI_FIXED_LENGTH, /* 05 Memory32 */ |
233 | ACPI_FIXED_LENGTH, | 375 | ACPI_FIXED_LENGTH, /* 06 memory32_fixed */ |
234 | ACPI_VARIABLE_LENGTH, | 376 | ACPI_VARIABLE_LENGTH, /* 07 Dword* address */ |
235 | ACPI_VARIABLE_LENGTH, | 377 | ACPI_VARIABLE_LENGTH, /* 08 Word* address */ |
236 | ACPI_VARIABLE_LENGTH, | 378 | ACPI_VARIABLE_LENGTH, /* 09 extended_iRQ */ |
237 | ACPI_VARIABLE_LENGTH, | 379 | ACPI_VARIABLE_LENGTH, /* 0_a Qword* address */ |
238 | ACPI_FIXED_LENGTH | 380 | ACPI_FIXED_LENGTH, /* 0_b Extended* address */ |
381 | ACPI_VARIABLE_LENGTH, /* 0_c Gpio* */ | ||
382 | 0, | ||
383 | ACPI_VARIABLE_LENGTH /* 0_e *serial_bus */ | ||
239 | }; | 384 | }; |
240 | 385 | ||
386 | /* | ||
387 | * For the i_aSL compiler/disassembler, we don't want any error messages | ||
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 | |||
241 | /******************************************************************************* | 397 | /******************************************************************************* |
242 | * | 398 | * |
243 | * FUNCTION: acpi_ut_walk_aml_resources | 399 | * FUNCTION: acpi_ut_walk_aml_resources |
@@ -265,6 +421,7 @@ acpi_ut_walk_aml_resources(u8 * aml, | |||
265 | u8 resource_index; | 421 | u8 resource_index; |
266 | u32 length; | 422 | u32 length; |
267 | u32 offset = 0; | 423 | u32 offset = 0; |
424 | u8 end_tag[2] = { 0x79, 0x00 }; | ||
268 | 425 | ||
269 | ACPI_FUNCTION_TRACE(ut_walk_aml_resources); | 426 | ACPI_FUNCTION_TRACE(ut_walk_aml_resources); |
270 | 427 | ||
@@ -286,6 +443,10 @@ acpi_ut_walk_aml_resources(u8 * aml, | |||
286 | 443 | ||
287 | status = acpi_ut_validate_resource(aml, &resource_index); | 444 | status = acpi_ut_validate_resource(aml, &resource_index); |
288 | if (ACPI_FAILURE(status)) { | 445 | if (ACPI_FAILURE(status)) { |
446 | /* | ||
447 | * Exit on failure. Cannot continue because the descriptor length | ||
448 | * may be bogus also. | ||
449 | */ | ||
289 | return_ACPI_STATUS(status); | 450 | return_ACPI_STATUS(status); |
290 | } | 451 | } |
291 | 452 | ||
@@ -300,7 +461,7 @@ acpi_ut_walk_aml_resources(u8 * aml, | |||
300 | user_function(aml, length, offset, resource_index, | 461 | user_function(aml, length, offset, resource_index, |
301 | context); | 462 | context); |
302 | if (ACPI_FAILURE(status)) { | 463 | if (ACPI_FAILURE(status)) { |
303 | return (status); | 464 | return_ACPI_STATUS(status); |
304 | } | 465 | } |
305 | } | 466 | } |
306 | 467 | ||
@@ -333,7 +494,19 @@ acpi_ut_walk_aml_resources(u8 * aml, | |||
333 | 494 | ||
334 | /* Did not find an end_tag descriptor */ | 495 | /* Did not find an end_tag descriptor */ |
335 | 496 | ||
336 | return (AE_AML_NO_RESOURCE_END_TAG); | 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); | ||
337 | } | 510 | } |
338 | 511 | ||
339 | /******************************************************************************* | 512 | /******************************************************************************* |
@@ -354,6 +527,7 @@ acpi_ut_walk_aml_resources(u8 * aml, | |||
354 | 527 | ||
355 | acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | 528 | acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) |
356 | { | 529 | { |
530 | union aml_resource *aml_resource; | ||
357 | u8 resource_type; | 531 | u8 resource_type; |
358 | u8 resource_index; | 532 | u8 resource_index; |
359 | acpi_rs_length resource_length; | 533 | acpi_rs_length resource_length; |
@@ -375,7 +549,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
375 | /* Verify the large resource type (name) against the max */ | 549 | /* Verify the large resource type (name) against the max */ |
376 | 550 | ||
377 | if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { | 551 | if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) { |
378 | return (AE_AML_INVALID_RESOURCE_TYPE); | 552 | goto invalid_resource; |
379 | } | 553 | } |
380 | 554 | ||
381 | /* | 555 | /* |
@@ -392,15 +566,17 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
392 | ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); | 566 | ((resource_type & ACPI_RESOURCE_NAME_SMALL_MASK) >> 3); |
393 | } | 567 | } |
394 | 568 | ||
395 | /* Check validity of the resource type, zero indicates name is invalid */ | 569 | /* |
396 | 570 | * Check validity of the resource type, via acpi_gbl_resource_types. Zero | |
571 | * indicates an invalid resource. | ||
572 | */ | ||
397 | if (!acpi_gbl_resource_types[resource_index]) { | 573 | if (!acpi_gbl_resource_types[resource_index]) { |
398 | return (AE_AML_INVALID_RESOURCE_TYPE); | 574 | goto invalid_resource; |
399 | } | 575 | } |
400 | 576 | ||
401 | /* | 577 | /* |
402 | * 2) Validate the resource_length field. This ensures that the length | 578 | * Validate the resource_length field. This ensures that the length |
403 | * is at least reasonable, and guarantees that it is non-zero. | 579 | * is at least reasonable, and guarantees that it is non-zero. |
404 | */ | 580 | */ |
405 | resource_length = acpi_ut_get_resource_length(aml); | 581 | resource_length = acpi_ut_get_resource_length(aml); |
406 | minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; | 582 | minimum_resource_length = acpi_gbl_resource_aml_sizes[resource_index]; |
@@ -413,7 +589,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
413 | /* Fixed length resource, length must match exactly */ | 589 | /* Fixed length resource, length must match exactly */ |
414 | 590 | ||
415 | if (resource_length != minimum_resource_length) { | 591 | if (resource_length != minimum_resource_length) { |
416 | return (AE_AML_BAD_RESOURCE_LENGTH); | 592 | goto bad_resource_length; |
417 | } | 593 | } |
418 | break; | 594 | break; |
419 | 595 | ||
@@ -422,7 +598,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
422 | /* Variable length resource, length must be at least the minimum */ | 598 | /* Variable length resource, length must be at least the minimum */ |
423 | 599 | ||
424 | if (resource_length < minimum_resource_length) { | 600 | if (resource_length < minimum_resource_length) { |
425 | return (AE_AML_BAD_RESOURCE_LENGTH); | 601 | goto bad_resource_length; |
426 | } | 602 | } |
427 | break; | 603 | break; |
428 | 604 | ||
@@ -432,7 +608,7 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
432 | 608 | ||
433 | if ((resource_length > minimum_resource_length) || | 609 | if ((resource_length > minimum_resource_length) || |
434 | (resource_length < (minimum_resource_length - 1))) { | 610 | (resource_length < (minimum_resource_length - 1))) { |
435 | return (AE_AML_BAD_RESOURCE_LENGTH); | 611 | goto bad_resource_length; |
436 | } | 612 | } |
437 | break; | 613 | break; |
438 | 614 | ||
@@ -440,7 +616,23 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
440 | 616 | ||
441 | /* Shouldn't happen (because of validation earlier), but be sure */ | 617 | /* Shouldn't happen (because of validation earlier), but be sure */ |
442 | 618 | ||
443 | return (AE_AML_INVALID_RESOURCE_TYPE); | 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 | } | ||
444 | } | 636 | } |
445 | 637 | ||
446 | /* Optionally return the resource table index */ | 638 | /* Optionally return the resource table index */ |
@@ -450,6 +642,22 @@ acpi_status acpi_ut_validate_resource(void *aml, u8 * return_index) | |||
450 | } | 642 | } |
451 | 643 | ||
452 | return (AE_OK); | 644 | return (AE_OK); |
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); | ||
453 | } | 661 | } |
454 | 662 | ||
455 | /******************************************************************************* | 663 | /******************************************************************************* |