rsxface.c (19649B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/******************************************************************************* 3 * 4 * Module Name: rsxface - Public interfaces to the resource manager 5 * 6 ******************************************************************************/ 7 8#define EXPORT_ACPI_INTERFACES 9 10#include <acpi/acpi.h> 11#include "accommon.h" 12#include "acresrc.h" 13#include "acnamesp.h" 14 15#define _COMPONENT ACPI_RESOURCES 16ACPI_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_status 35acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context); 36 37static acpi_status 38acpi_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_parameters 45 * 46 * PARAMETERS: device_handle - Handle to a device 47 * buffer - Pointer to a data buffer 48 * return_node - Pointer to where the device node is returned 49 * 50 * RETURN: Status 51 * 52 * DESCRIPTION: Common parameter validation for resource interfaces 53 * 54 ******************************************************************************/ 55 56static acpi_status 57acpi_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 device 68 */ 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 object 84 * 85 * if there is a non-zero buffer length we also need a valid pointer in 86 * the buffer. If it's a zero buffer length, we'll be returning the 87 * 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_table 101 * 102 * PARAMETERS: device_handle - Handle to the Bus device we are querying 103 * ret_buffer - Pointer to a buffer to receive the 104 * current resources for the device 105 * 106 * RETURN: Status 107 * 108 * DESCRIPTION: This function is called to get the IRQ routing table for a 109 * specific bus. The caller must first acquire a handle for the 110 * desired bus. The routine table is placed in the buffer pointed 111 * to by the ret_buffer variable parameter. 112 * 113 * If the function fails an appropriate status will be returned 114 * and the value of ret_buffer is undefined. 115 * 116 * This function attempts to execute the _PRT method contained in 117 * the object indicated by the passed device_handle. 118 * 119 ******************************************************************************/ 120 121acpi_status 122acpi_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_resources 146 * 147 * PARAMETERS: device_handle - Handle to the device object for the 148 * device we are querying 149 * ret_buffer - Pointer to a buffer to receive the 150 * current resources for the device 151 * 152 * RETURN: Status 153 * 154 * DESCRIPTION: This function is called to get the current resources for a 155 * specific device. The caller must first acquire a handle for 156 * the desired device. The resource data is placed in the buffer 157 * pointed to by the ret_buffer variable parameter. 158 * 159 * If the function fails an appropriate status will be returned 160 * and the value of ret_buffer is undefined. 161 * 162 * This function attempts to execute the _CRS method contained in 163 * the object indicated by the passed device_handle. 164 * 165 ******************************************************************************/ 166acpi_status 167acpi_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_resources 191 * 192 * PARAMETERS: device_handle - Handle to the device object for the 193 * device we are querying 194 * ret_buffer - Pointer to a buffer to receive the 195 * resources for the device 196 * 197 * RETURN: Status 198 * 199 * DESCRIPTION: This function is called to get a list of the possible resources 200 * for a specific device. The caller must first acquire a handle 201 * for the desired device. The resource data is placed in the 202 * buffer pointed to by the ret_buffer variable. 203 * 204 * If the function fails an appropriate status will be returned 205 * and the value of ret_buffer is undefined. 206 * 207 ******************************************************************************/ 208acpi_status 209acpi_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_resources 233 * 234 * PARAMETERS: device_handle - Handle to the device object for the 235 * device we are setting resources 236 * in_buffer - Pointer to a buffer containing the 237 * resources to be set for the device 238 * 239 * RETURN: Status 240 * 241 * DESCRIPTION: This function is called to set the current resources for a 242 * specific device. The caller must first acquire a handle for 243 * the desired device. The resource data is passed to the routine 244 * the buffer pointed to by the in_buffer variable. 245 * 246 ******************************************************************************/ 247acpi_status 248acpi_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_resources 278 * 279 * PARAMETERS: device_handle - Handle to the device object for the 280 * device we are getting resources 281 * in_buffer - Pointer to a buffer containing the 282 * resources to be set for the device 283 * 284 * RETURN: Status 285 * 286 * DESCRIPTION: This function is called to get the event resources for a 287 * specific device. The caller must first acquire a handle for 288 * the desired device. The resource data is passed to the routine 289 * the buffer pointed to by the in_buffer variable. Uses the 290 * _AEI method. 291 * 292 ******************************************************************************/ 293acpi_status 294acpi_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_address64 318 * 319 * PARAMETERS: resource - Pointer to a resource 320 * out - Pointer to the users's return buffer 321 * (a struct acpi_resource_address64) 322 * 323 * RETURN: Status 324 * 325 * DESCRIPTION: If the resource is an address16, address32, or address64, 326 * copy it to the address64 return buffer. This saves the 327 * caller from having to duplicate code for different-sized 328 * addresses. 329 * 330 ******************************************************************************/ 331acpi_status 332acpi_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_resource 382 * 383 * PARAMETERS: device_handle - Handle for the parent device object 384 * name - Method name for the parent resource 385 * (METHOD_NAME__CRS or METHOD_NAME__PRS) 386 * uuid - Pointer to the UUID to be matched. 387 * includes both subtype and 16-byte UUID 388 * ret_buffer - Where the vendor resource is returned 389 * 390 * RETURN: Status 391 * 392 * DESCRIPTION: Walk a resource template for the specified device to find a 393 * vendor-defined resource that matches the supplied UUID and 394 * UUID subtype. Returns a struct acpi_resource of type Vendor. 395 * 396 ******************************************************************************/ 397acpi_status 398acpi_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_resource 433 * 434 * PARAMETERS: acpi_walk_resource_callback 435 * 436 * RETURN: Status 437 * 438 * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID 439 * 440 ******************************************************************************/ 441static acpi_status 442acpi_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 struct 461 * 2) The UUID subtypes must match 462 * 3) The UUID data must match 463 */ 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_buffer 492 * 493 * PARAMETERS: buffer - Formatted buffer returned by one of the 494 * various Get*Resource functions 495 * user_function - Called for each resource 496 * context - Passed to user_function 497 * 498 * RETURN: Status 499 * 500 * DESCRIPTION: Walks the input resource template. The user_function is called 501 * once for each resource in the list. 502 * 503 ******************************************************************************/ 504 505acpi_status 506acpi_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_resources 577 * 578 * PARAMETERS: device_handle - Handle to the device object for the 579 * device we are querying 580 * name - Method name of the resources we want. 581 * (METHOD_NAME__CRS, METHOD_NAME__PRS, or 582 * METHOD_NAME__AEI or METHOD_NAME__DMA) 583 * user_function - Called for each resource 584 * context - Passed to user_function 585 * 586 * RETURN: Status 587 * 588 * DESCRIPTION: Retrieves the current or possible resource list for the 589 * specified device. The user_function is called once for 590 * each resource in the list. 591 * 592 ******************************************************************************/ 593acpi_status 594acpi_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)