629 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: rsxface - Public interfaces to the resource manager5 *6 ******************************************************************************/7 8#define EXPORT_ACPI_INTERFACES9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acresrc.h"13#include "acnamesp.h"14 15#define _COMPONENT ACPI_RESOURCES16ACPI_MODULE_NAME("rsxface")17 18/* Local macros for 16,32-bit to 64-bit conversion */19#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)20#define ACPI_COPY_ADDRESS(out, in) \21 ACPI_COPY_FIELD(out, in, resource_type); \22 ACPI_COPY_FIELD(out, in, producer_consumer); \23 ACPI_COPY_FIELD(out, in, decode); \24 ACPI_COPY_FIELD(out, in, min_address_fixed); \25 ACPI_COPY_FIELD(out, in, max_address_fixed); \26 ACPI_COPY_FIELD(out, in, info); \27 ACPI_COPY_FIELD(out, in, address.granularity); \28 ACPI_COPY_FIELD(out, in, address.minimum); \29 ACPI_COPY_FIELD(out, in, address.maximum); \30 ACPI_COPY_FIELD(out, in, address.translation_offset); \31 ACPI_COPY_FIELD(out, in, address.address_length); \32 ACPI_COPY_FIELD(out, in, resource_source);33/* Local prototypes */34static acpi_status35acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);36 37static acpi_status38acpi_rs_validate_parameters(acpi_handle device_handle,39 struct acpi_buffer *buffer,40 struct acpi_namespace_node **return_node);41 42/*******************************************************************************43 *44 * FUNCTION: acpi_rs_validate_parameters45 *46 * PARAMETERS: device_handle - Handle to a device47 * buffer - Pointer to a data buffer48 * return_node - Pointer to where the device node is returned49 *50 * RETURN: Status51 *52 * DESCRIPTION: Common parameter validation for resource interfaces53 *54 ******************************************************************************/55 56static acpi_status57acpi_rs_validate_parameters(acpi_handle device_handle,58 struct acpi_buffer *buffer,59 struct acpi_namespace_node **return_node)60{61 acpi_status status;62 struct acpi_namespace_node *node;63 64 ACPI_FUNCTION_TRACE(rs_validate_parameters);65 66 /*67 * Must have a valid handle to an ACPI device68 */69 if (!device_handle) {70 return_ACPI_STATUS(AE_BAD_PARAMETER);71 }72 73 node = acpi_ns_validate_handle(device_handle);74 if (!node) {75 return_ACPI_STATUS(AE_BAD_PARAMETER);76 }77 78 if (node->type != ACPI_TYPE_DEVICE) {79 return_ACPI_STATUS(AE_TYPE);80 }81 82 /*83 * Validate the user buffer object84 *85 * if there is a non-zero buffer length we also need a valid pointer in86 * the buffer. If it's a zero buffer length, we'll be returning the87 * needed buffer size (later), so keep going.88 */89 status = acpi_ut_validate_buffer(buffer);90 if (ACPI_FAILURE(status)) {91 return_ACPI_STATUS(status);92 }93 94 *return_node = node;95 return_ACPI_STATUS(AE_OK);96}97 98/*******************************************************************************99 *100 * FUNCTION: acpi_get_irq_routing_table101 *102 * PARAMETERS: device_handle - Handle to the Bus device we are querying103 * ret_buffer - Pointer to a buffer to receive the104 * current resources for the device105 *106 * RETURN: Status107 *108 * DESCRIPTION: This function is called to get the IRQ routing table for a109 * specific bus. The caller must first acquire a handle for the110 * desired bus. The routine table is placed in the buffer pointed111 * to by the ret_buffer variable parameter.112 *113 * If the function fails an appropriate status will be returned114 * and the value of ret_buffer is undefined.115 *116 * This function attempts to execute the _PRT method contained in117 * the object indicated by the passed device_handle.118 *119 ******************************************************************************/120 121acpi_status122acpi_get_irq_routing_table(acpi_handle device_handle,123 struct acpi_buffer *ret_buffer)124{125 acpi_status status;126 struct acpi_namespace_node *node;127 128 ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);129 130 /* Validate parameters then dispatch to internal routine */131 132 status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);133 if (ACPI_FAILURE(status)) {134 return_ACPI_STATUS(status);135 }136 137 status = acpi_rs_get_prt_method_data(node, ret_buffer);138 return_ACPI_STATUS(status);139}140 141ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)142 143/*******************************************************************************144 *145 * FUNCTION: acpi_get_current_resources146 *147 * PARAMETERS: device_handle - Handle to the device object for the148 * device we are querying149 * ret_buffer - Pointer to a buffer to receive the150 * current resources for the device151 *152 * RETURN: Status153 *154 * DESCRIPTION: This function is called to get the current resources for a155 * specific device. The caller must first acquire a handle for156 * the desired device. The resource data is placed in the buffer157 * pointed to by the ret_buffer variable parameter.158 *159 * If the function fails an appropriate status will be returned160 * and the value of ret_buffer is undefined.161 *162 * This function attempts to execute the _CRS method contained in163 * the object indicated by the passed device_handle.164 *165 ******************************************************************************/166acpi_status167acpi_get_current_resources(acpi_handle device_handle,168 struct acpi_buffer *ret_buffer)169{170 acpi_status status;171 struct acpi_namespace_node *node;172 173 ACPI_FUNCTION_TRACE(acpi_get_current_resources);174 175 /* Validate parameters then dispatch to internal routine */176 177 status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);178 if (ACPI_FAILURE(status)) {179 return_ACPI_STATUS(status);180 }181 182 status = acpi_rs_get_crs_method_data(node, ret_buffer);183 return_ACPI_STATUS(status);184}185 186ACPI_EXPORT_SYMBOL(acpi_get_current_resources)187 188/*******************************************************************************189 *190 * FUNCTION: acpi_get_possible_resources191 *192 * PARAMETERS: device_handle - Handle to the device object for the193 * device we are querying194 * ret_buffer - Pointer to a buffer to receive the195 * resources for the device196 *197 * RETURN: Status198 *199 * DESCRIPTION: This function is called to get a list of the possible resources200 * for a specific device. The caller must first acquire a handle201 * for the desired device. The resource data is placed in the202 * buffer pointed to by the ret_buffer variable.203 *204 * If the function fails an appropriate status will be returned205 * and the value of ret_buffer is undefined.206 *207 ******************************************************************************/208acpi_status209acpi_get_possible_resources(acpi_handle device_handle,210 struct acpi_buffer *ret_buffer)211{212 acpi_status status;213 struct acpi_namespace_node *node;214 215 ACPI_FUNCTION_TRACE(acpi_get_possible_resources);216 217 /* Validate parameters then dispatch to internal routine */218 219 status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);220 if (ACPI_FAILURE(status)) {221 return_ACPI_STATUS(status);222 }223 224 status = acpi_rs_get_prs_method_data(node, ret_buffer);225 return_ACPI_STATUS(status);226}227 228ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)229 230/*******************************************************************************231 *232 * FUNCTION: acpi_set_current_resources233 *234 * PARAMETERS: device_handle - Handle to the device object for the235 * device we are setting resources236 * in_buffer - Pointer to a buffer containing the237 * resources to be set for the device238 *239 * RETURN: Status240 *241 * DESCRIPTION: This function is called to set the current resources for a242 * specific device. The caller must first acquire a handle for243 * the desired device. The resource data is passed to the routine244 * the buffer pointed to by the in_buffer variable.245 *246 ******************************************************************************/247acpi_status248acpi_set_current_resources(acpi_handle device_handle,249 struct acpi_buffer *in_buffer)250{251 acpi_status status;252 struct acpi_namespace_node *node;253 254 ACPI_FUNCTION_TRACE(acpi_set_current_resources);255 256 /* Validate the buffer, don't allow zero length */257 258 if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {259 return_ACPI_STATUS(AE_BAD_PARAMETER);260 }261 262 /* Validate parameters then dispatch to internal routine */263 264 status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);265 if (ACPI_FAILURE(status)) {266 return_ACPI_STATUS(status);267 }268 269 status = acpi_rs_set_srs_method_data(node, in_buffer);270 return_ACPI_STATUS(status);271}272 273ACPI_EXPORT_SYMBOL(acpi_set_current_resources)274 275/*******************************************************************************276 *277 * FUNCTION: acpi_get_event_resources278 *279 * PARAMETERS: device_handle - Handle to the device object for the280 * device we are getting resources281 * in_buffer - Pointer to a buffer containing the282 * resources to be set for the device283 *284 * RETURN: Status285 *286 * DESCRIPTION: This function is called to get the event resources for a287 * specific device. The caller must first acquire a handle for288 * the desired device. The resource data is passed to the routine289 * the buffer pointed to by the in_buffer variable. Uses the290 * _AEI method.291 *292 ******************************************************************************/293acpi_status294acpi_get_event_resources(acpi_handle device_handle,295 struct acpi_buffer *ret_buffer)296{297 acpi_status status;298 struct acpi_namespace_node *node;299 300 ACPI_FUNCTION_TRACE(acpi_get_event_resources);301 302 /* Validate parameters then dispatch to internal routine */303 304 status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);305 if (ACPI_FAILURE(status)) {306 return_ACPI_STATUS(status);307 }308 309 status = acpi_rs_get_aei_method_data(node, ret_buffer);310 return_ACPI_STATUS(status);311}312 313ACPI_EXPORT_SYMBOL(acpi_get_event_resources)314 315/******************************************************************************316 *317 * FUNCTION: acpi_resource_to_address64318 *319 * PARAMETERS: resource - Pointer to a resource320 * out - Pointer to the users's return buffer321 * (a struct acpi_resource_address64)322 *323 * RETURN: Status324 *325 * DESCRIPTION: If the resource is an address16, address32, or address64,326 * copy it to the address64 return buffer. This saves the327 * caller from having to duplicate code for different-sized328 * addresses.329 *330 ******************************************************************************/331acpi_status332acpi_resource_to_address64(struct acpi_resource *resource,333 struct acpi_resource_address64 *out)334{335 struct acpi_resource_address16 *address16;336 struct acpi_resource_address32 *address32;337 338 if (!resource || !out) {339 return (AE_BAD_PARAMETER);340 }341 342 /* Convert 16 or 32 address descriptor to 64 */343 344 switch (resource->type) {345 case ACPI_RESOURCE_TYPE_ADDRESS16:346 347 address16 =348 ACPI_CAST_PTR(struct acpi_resource_address16,349 &resource->data);350 ACPI_COPY_ADDRESS(out, address16);351 break;352 353 case ACPI_RESOURCE_TYPE_ADDRESS32:354 355 address32 =356 ACPI_CAST_PTR(struct acpi_resource_address32,357 &resource->data);358 ACPI_COPY_ADDRESS(out, address32);359 break;360 361 case ACPI_RESOURCE_TYPE_ADDRESS64:362 363 /* Simple copy for 64 bit source */364 365 memcpy(out, &resource->data,366 sizeof(struct acpi_resource_address64));367 break;368 369 default:370 371 return (AE_BAD_PARAMETER);372 }373 374 return (AE_OK);375}376 377ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)378 379/*******************************************************************************380 *381 * FUNCTION: acpi_get_vendor_resource382 *383 * PARAMETERS: device_handle - Handle for the parent device object384 * name - Method name for the parent resource385 * (METHOD_NAME__CRS or METHOD_NAME__PRS)386 * uuid - Pointer to the UUID to be matched.387 * includes both subtype and 16-byte UUID388 * ret_buffer - Where the vendor resource is returned389 *390 * RETURN: Status391 *392 * DESCRIPTION: Walk a resource template for the specified device to find a393 * vendor-defined resource that matches the supplied UUID and394 * UUID subtype. Returns a struct acpi_resource of type Vendor.395 *396 ******************************************************************************/397acpi_status398acpi_get_vendor_resource(acpi_handle device_handle,399 char *name,400 struct acpi_vendor_uuid *uuid,401 struct acpi_buffer *ret_buffer)402{403 struct acpi_vendor_walk_info info;404 acpi_status status;405 406 /* Other parameters are validated by acpi_walk_resources */407 408 if (!uuid || !ret_buffer) {409 return (AE_BAD_PARAMETER);410 }411 412 info.uuid = uuid;413 info.buffer = ret_buffer;414 info.status = AE_NOT_EXIST;415 416 /* Walk the _CRS or _PRS resource list for this device */417 418 status =419 acpi_walk_resources(device_handle, name,420 acpi_rs_match_vendor_resource, &info);421 if (ACPI_FAILURE(status)) {422 return (status);423 }424 425 return (info.status);426}427 428ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)429 430/*******************************************************************************431 *432 * FUNCTION: acpi_rs_match_vendor_resource433 *434 * PARAMETERS: acpi_walk_resource_callback435 *436 * RETURN: Status437 *438 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID439 *440 ******************************************************************************/441static acpi_status442acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)443{444 struct acpi_vendor_walk_info *info = context;445 struct acpi_resource_vendor_typed *vendor;446 struct acpi_buffer *buffer;447 acpi_status status;448 449 /* Ignore all descriptors except Vendor */450 451 if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {452 return (AE_OK);453 }454 455 vendor = &resource->data.vendor_typed;456 457 /*458 * For a valid match, these conditions must hold:459 *460 * 1) Length of descriptor data must be at least as long as a UUID struct461 * 2) The UUID subtypes must match462 * 3) The UUID data must match463 */464 if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||465 (vendor->uuid_subtype != info->uuid->subtype) ||466 (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {467 return (AE_OK);468 }469 470 /* Validate/Allocate/Clear caller buffer */471 472 buffer = info->buffer;473 status = acpi_ut_initialize_buffer(buffer, resource->length);474 if (ACPI_FAILURE(status)) {475 return (status);476 }477 478 /* Found the correct resource, copy and return it */479 480 memcpy(buffer->pointer, resource, resource->length);481 buffer->length = resource->length;482 483 /* Found the desired descriptor, terminate resource walk */484 485 info->status = AE_OK;486 return (AE_CTRL_TERMINATE);487}488 489/*******************************************************************************490 *491 * FUNCTION: acpi_walk_resource_buffer492 *493 * PARAMETERS: buffer - Formatted buffer returned by one of the494 * various Get*Resource functions495 * user_function - Called for each resource496 * context - Passed to user_function497 *498 * RETURN: Status499 *500 * DESCRIPTION: Walks the input resource template. The user_function is called501 * once for each resource in the list.502 *503 ******************************************************************************/504 505acpi_status506acpi_walk_resource_buffer(struct acpi_buffer *buffer,507 acpi_walk_resource_callback user_function,508 void *context)509{510 acpi_status status = AE_OK;511 struct acpi_resource *resource;512 struct acpi_resource *resource_end;513 514 ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer);515 516 /* Parameter validation */517 518 if (!buffer || !buffer->pointer || !user_function) {519 return_ACPI_STATUS(AE_BAD_PARAMETER);520 }521 522 /* Buffer contains the resource list and length */523 524 resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer);525 resource_end =526 ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length);527 528 /* Walk the resource list until the end_tag is found (or buffer end) */529 530 while (resource < resource_end) {531 532 /* Sanity check the resource type */533 534 if (resource->type > ACPI_RESOURCE_TYPE_MAX) {535 status = AE_AML_INVALID_RESOURCE_TYPE;536 break;537 }538 539 /* Sanity check the length. It must not be zero, or we loop forever */540 541 if (!resource->length) {542 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);543 }544 545 /* Invoke the user function, abort on any error returned */546 547 status = user_function(resource, context);548 if (ACPI_FAILURE(status)) {549 if (status == AE_CTRL_TERMINATE) {550 551 /* This is an OK termination by the user function */552 553 status = AE_OK;554 }555 break;556 }557 558 /* end_tag indicates end-of-list */559 560 if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {561 break;562 }563 564 /* Get the next resource descriptor */565 566 resource = ACPI_NEXT_RESOURCE(resource);567 }568 569 return_ACPI_STATUS(status);570}571 572ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)573 574/*******************************************************************************575 *576 * FUNCTION: acpi_walk_resources577 *578 * PARAMETERS: device_handle - Handle to the device object for the579 * device we are querying580 * name - Method name of the resources we want.581 * (METHOD_NAME__CRS, METHOD_NAME__PRS, or582 * METHOD_NAME__AEI or METHOD_NAME__DMA)583 * user_function - Called for each resource584 * context - Passed to user_function585 *586 * RETURN: Status587 *588 * DESCRIPTION: Retrieves the current or possible resource list for the589 * specified device. The user_function is called once for590 * each resource in the list.591 *592 ******************************************************************************/593acpi_status594acpi_walk_resources(acpi_handle device_handle,595 char *name,596 acpi_walk_resource_callback user_function, void *context)597{598 acpi_status status;599 struct acpi_buffer buffer;600 601 ACPI_FUNCTION_TRACE(acpi_walk_resources);602 603 /* Parameter validation */604 605 if (!device_handle || !user_function || !name ||606 (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) &&607 !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) &&608 !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) &&609 !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) {610 return_ACPI_STATUS(AE_BAD_PARAMETER);611 }612 613 /* Get the _CRS/_PRS/_AEI/_DMA resource list */614 615 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;616 status = acpi_rs_get_method_data(device_handle, name, &buffer);617 if (ACPI_FAILURE(status)) {618 return_ACPI_STATUS(status);619 }620 621 /* Walk the resource list and cleanup */622 623 status = acpi_walk_resource_buffer(&buffer, user_function, context);624 ACPI_FREE(buffer.pointer);625 return_ACPI_STATUS(status);626}627 628ACPI_EXPORT_SYMBOL(acpi_walk_resources)629