aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/resources/rsxface.c
diff options
context:
space:
mode:
authorBob Moore <robert.moore@intel.com>2005-11-17 13:07:00 -0500
committerLen Brown <len.brown@intel.com>2005-12-10 00:27:56 -0500
commitc51a4de85de720670f2fbc592a6f8040af72ad87 (patch)
treeccaa60c483fcc904abd63d936ff7dc380bf28e7b /drivers/acpi/resources/rsxface.c
parent96db255c8f014ae3497507104e8df809785a619f (diff)
[ACPI] ACPICA 20051117
Fixed a problem in the AML parser where the method thread count could be decremented below zero if any errors occurred during the method parse phase. This should eliminate AE_AML_METHOD_LIMIT exceptions seen on some machines. This also fixed a related regression with the mechanism that detects and corrects methods that cannot properly handle reentrancy (related to the deployment of the new OwnerId mechanism.) Eliminated the pre-parsing of control methods (to detect errors) during table load. Related to the problem above, this was causing unwind issues if any errors occurred during the parse, and it seemed to be overkill. A table load should not be aborted if there are problems with any single control method, thus rendering this feature rather pointless. Fixed a problem with the new table-driven resource manager where an internal buffer overflow could occur for small resource templates. Implemented a new external interface, acpi_get_vendor_resource() This interface will find and return a vendor-defined resource descriptor within a _CRS or _PRS method via an ACPI 3.0 UUID match. (from Bjorn Helgaas) Removed the length limit (200) on string objects as per the upcoming ACPI 3.0A specification. This affects the following areas of the interpreter: 1) any implicit conversion of a Buffer to a String, 2) a String object result of the ASL Concatentate operator, 3) the String object result of the ASL ToString operator. Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/resources/rsxface.c')
-rw-r--r--drivers/acpi/resources/rsxface.c208
1 files changed, 162 insertions, 46 deletions
diff --git a/drivers/acpi/resources/rsxface.c b/drivers/acpi/resources/rsxface.c
index 09d250ab9872..50a956b705b0 100644
--- a/drivers/acpi/resources/rsxface.c
+++ b/drivers/acpi/resources/rsxface.c
@@ -64,6 +64,10 @@ ACPI_MODULE_NAME("rsxface")
64 ACPI_COPY_FIELD(out, in, translation_offset); \ 64 ACPI_COPY_FIELD(out, in, translation_offset); \
65 ACPI_COPY_FIELD(out, in, address_length); \ 65 ACPI_COPY_FIELD(out, in, address_length); \
66 ACPI_COPY_FIELD(out, in, resource_source); 66 ACPI_COPY_FIELD(out, in, resource_source);
67/* Local prototypes */
68static acpi_status
69acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
70
67/******************************************************************************* 71/*******************************************************************************
68 * 72 *
69 * FUNCTION: acpi_get_irq_routing_table 73 * FUNCTION: acpi_get_irq_routing_table
@@ -86,6 +90,7 @@ ACPI_MODULE_NAME("rsxface")
86 * the object indicated by the passed device_handle. 90 * the object indicated by the passed device_handle.
87 * 91 *
88 ******************************************************************************/ 92 ******************************************************************************/
93
89acpi_status 94acpi_status
90acpi_get_irq_routing_table(acpi_handle device_handle, 95acpi_get_irq_routing_table(acpi_handle device_handle,
91 struct acpi_buffer *ret_buffer) 96 struct acpi_buffer *ret_buffer)
@@ -222,12 +227,12 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
222 * 227 *
223 * FUNCTION: acpi_walk_resources 228 * FUNCTION: acpi_walk_resources
224 * 229 *
225 * PARAMETERS: device_handle - a handle to the device object for the 230 * PARAMETERS: device_handle - Handle to the device object for the
226 * device we are querying 231 * device we are querying
227 * Path - method name of the resources we want 232 * Name - Method name of the resources we want
228 * (METHOD_NAME__CRS or METHOD_NAME__PRS) 233 * (METHOD_NAME__CRS or METHOD_NAME__PRS)
229 * user_function - called for each resource 234 * user_function - Called for each resource
230 * Context - passed to user_function 235 * Context - Passed to user_function
231 * 236 *
232 * RETURN: Status 237 * RETURN: Status
233 * 238 *
@@ -239,79 +244,74 @@ EXPORT_SYMBOL(acpi_get_possible_resources);
239 244
240acpi_status 245acpi_status
241acpi_walk_resources(acpi_handle device_handle, 246acpi_walk_resources(acpi_handle device_handle,
242 char *path, 247 char *name,
243 ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) 248 ACPI_WALK_RESOURCE_CALLBACK user_function, void *context)
244{ 249{
245 acpi_status status; 250 acpi_status status;
246 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 251 struct acpi_buffer buffer;
247 struct acpi_resource *resource; 252 struct acpi_resource *resource;
248 struct acpi_resource *buffer_end; 253 struct acpi_resource *resource_end;
249 254
250 ACPI_FUNCTION_TRACE("acpi_walk_resources"); 255 ACPI_FUNCTION_TRACE("acpi_walk_resources");
251 256
252 if (!device_handle || 257 /* Parameter validation */
253 (ACPI_STRNCMP(path, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) && 258
254 ACPI_STRNCMP(path, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) { 259 if (!device_handle || !user_function || !name ||
260 (ACPI_STRNCMP(name, METHOD_NAME__CRS, sizeof(METHOD_NAME__CRS)) &&
261 ACPI_STRNCMP(name, METHOD_NAME__PRS, sizeof(METHOD_NAME__PRS)))) {
255 return_ACPI_STATUS(AE_BAD_PARAMETER); 262 return_ACPI_STATUS(AE_BAD_PARAMETER);
256 } 263 }
257 264
258 status = acpi_rs_get_method_data(device_handle, path, &buffer); 265 /* Get the _CRS or _PRS resource list */
266
267 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
268 status = acpi_rs_get_method_data(device_handle, name, &buffer);
259 if (ACPI_FAILURE(status)) { 269 if (ACPI_FAILURE(status)) {
260 return_ACPI_STATUS(status); 270 return_ACPI_STATUS(status);
261 } 271 }
262 272
263 /* Setup pointers */ 273 /* Buffer now contains the resource list */
264 274
265 resource = (struct acpi_resource *)buffer.pointer; 275 resource = ACPI_CAST_PTR(struct acpi_resource, buffer.pointer);
266 buffer_end = ACPI_CAST_PTR(struct acpi_resource, 276 resource_end =
267 ((u8 *) buffer.pointer + buffer.length)); 277 ACPI_ADD_PTR(struct acpi_resource, buffer.pointer, buffer.length);
268 278
269 /* Walk the resource list */ 279 /* Walk the resource list until the end_tag is found (or buffer end) */
270 280
271 for (;;) { 281 while (resource < resource_end) {
272 if (!resource || resource->type == ACPI_RESOURCE_TYPE_END_TAG) { 282 /* Sanity check the resource */
283
284 if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
285 status = AE_AML_INVALID_RESOURCE_TYPE;
273 break; 286 break;
274 } 287 }
275 288
276 status = user_function(resource, context); 289 /* Invoke the user function, abort on any error returned */
277
278 switch (status) {
279 case AE_OK:
280 case AE_CTRL_DEPTH:
281 290
282 /* Just keep going */ 291 status = user_function(resource, context);
292 if (ACPI_FAILURE(status)) {
293 if (status == AE_CTRL_TERMINATE) {
294 /* This is an OK termination by the user function */
283 295
284 status = AE_OK; 296 status = AE_OK;
297 }
285 break; 298 break;
299 }
286 300
287 case AE_CTRL_TERMINATE: 301 /* end_tag indicates end-of-list */
288
289 /* Exit now, with OK stats */
290
291 status = AE_OK;
292 goto cleanup;
293
294 default:
295
296 /* All others are valid exceptions */
297 302
298 goto cleanup; 303 if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
304 break;
299 } 305 }
300 306
301 /* Get the next resource descriptor */ 307 /* Get the next resource descriptor */
302 308
303 resource = ACPI_NEXT_RESOURCE(resource); 309 resource =
304 310 ACPI_ADD_PTR(struct acpi_resource, resource,
305 /* Check for end-of-buffer */ 311 resource->length);
306
307 if (resource >= buffer_end) {
308 goto cleanup;
309 }
310 } 312 }
311 313
312 cleanup: 314 ACPI_MEM_FREE(buffer.pointer);
313
314 acpi_os_free(buffer.pointer);
315 return_ACPI_STATUS(status); 315 return_ACPI_STATUS(status);
316} 316}
317 317
@@ -381,6 +381,12 @@ acpi_resource_to_address64(struct acpi_resource *resource,
381 struct acpi_resource_address16 *address16; 381 struct acpi_resource_address16 *address16;
382 struct acpi_resource_address32 *address32; 382 struct acpi_resource_address32 *address32;
383 383
384 if (!resource || !out) {
385 return (AE_BAD_PARAMETER);
386 }
387
388 /* Convert 16 or 32 address descriptor to 64 */
389
384 switch (resource->type) { 390 switch (resource->type) {
385 case ACPI_RESOURCE_TYPE_ADDRESS16: 391 case ACPI_RESOURCE_TYPE_ADDRESS16:
386 392
@@ -410,3 +416,113 @@ acpi_resource_to_address64(struct acpi_resource *resource,
410} 416}
411 417
412EXPORT_SYMBOL(acpi_resource_to_address64); 418EXPORT_SYMBOL(acpi_resource_to_address64);
419
420/*******************************************************************************
421 *
422 * FUNCTION: acpi_get_vendor_resource
423 *
424 * PARAMETERS: device_handle - Handle for the parent device object
425 * Name - Method name for the parent resource
426 * (METHOD_NAME__CRS or METHOD_NAME__PRS)
427 * Uuid - Pointer to the UUID to be matched.
428 * includes both subtype and 16-byte UUID
429 * ret_buffer - Where the vendor resource is returned
430 *
431 * RETURN: Status
432 *
433 * DESCRIPTION: Walk a resource template for the specified evice to find a
434 * vendor-defined resource that matches the supplied UUID and
435 * UUID subtype. Returns a struct acpi_resource of type Vendor.
436 *
437 ******************************************************************************/
438
439acpi_status
440acpi_get_vendor_resource(acpi_handle device_handle,
441 char *name,
442 struct acpi_vendor_uuid * uuid,
443 struct acpi_buffer * ret_buffer)
444{
445 struct acpi_vendor_walk_info info;
446 acpi_status status;
447
448 /* Other parameters are validated by acpi_walk_resources */
449
450 if (!uuid || !ret_buffer) {
451 return (AE_BAD_PARAMETER);
452 }
453
454 info.uuid = uuid;
455 info.buffer = ret_buffer;
456 info.status = AE_NOT_EXIST;
457
458 /* Walk the _CRS or _PRS resource list for this device */
459
460 status =
461 acpi_walk_resources(device_handle, name,
462 acpi_rs_match_vendor_resource, &info);
463 if (ACPI_FAILURE(status)) {
464 return (status);
465 }
466
467 return (info.status);
468}
469
470/*******************************************************************************
471 *
472 * FUNCTION: acpi_rs_match_vendor_resource
473 *
474 * PARAMETERS: ACPI_WALK_RESOURCE_CALLBACK
475 *
476 * RETURN: Status
477 *
478 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
479 *
480 ******************************************************************************/
481
482static acpi_status
483acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
484{
485 struct acpi_vendor_walk_info *info = context;
486 struct acpi_resource_vendor_typed *vendor;
487 struct acpi_buffer *buffer;
488 acpi_status status;
489
490 /* Ignore all descriptors except Vendor */
491
492 if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
493 return (AE_OK);
494 }
495
496 vendor = &resource->data.vendor_typed;
497
498 /*
499 * For a valid match, these conditions must hold:
500 *
501 * 1) Length of descriptor data must be at least as long as a UUID struct
502 * 2) The UUID subtypes must match
503 * 3) The UUID data must match
504 */
505 if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
506 (vendor->uuid_subtype != info->uuid->subtype) ||
507 (ACPI_MEMCMP(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
508 return (AE_OK);
509 }
510
511 /* Validate/Allocate/Clear caller buffer */
512
513 buffer = info->buffer;
514 status = acpi_ut_initialize_buffer(buffer, resource->length);
515 if (ACPI_FAILURE(status)) {
516 return (status);
517 }
518
519 /* Found the correct resource, copy and return it */
520
521 ACPI_MEMCPY(buffer->pointer, resource, resource->length);
522 buffer->length = resource->length;
523
524 /* Found the desired descriptor, terminate resource walk */
525
526 info->status = AE_OK;
527 return (AE_CTRL_TERMINATE);
528}