Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /*******************************************************************************
0003  *
0004  * Module Name: rsxface - Public interfaces to the resource manager
0005  *
0006  ******************************************************************************/
0007 
0008 #define EXPORT_ACPI_INTERFACES
0009 
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acresrc.h"
0013 #include "acnamesp.h"
0014 
0015 #define _COMPONENT          ACPI_RESOURCES
0016 ACPI_MODULE_NAME("rsxface")
0017 
0018 /* Local macros for 16,32-bit to 64-bit conversion */
0019 #define ACPI_COPY_FIELD(out, in, field)  ((out)->field = (in)->field)
0020 #define ACPI_COPY_ADDRESS(out, in)                       \
0021     ACPI_COPY_FIELD(out, in, resource_type);             \
0022     ACPI_COPY_FIELD(out, in, producer_consumer);         \
0023     ACPI_COPY_FIELD(out, in, decode);                    \
0024     ACPI_COPY_FIELD(out, in, min_address_fixed);         \
0025     ACPI_COPY_FIELD(out, in, max_address_fixed);         \
0026     ACPI_COPY_FIELD(out, in, info);                      \
0027     ACPI_COPY_FIELD(out, in, address.granularity);       \
0028     ACPI_COPY_FIELD(out, in, address.minimum);           \
0029     ACPI_COPY_FIELD(out, in, address.maximum);           \
0030     ACPI_COPY_FIELD(out, in, address.translation_offset); \
0031     ACPI_COPY_FIELD(out, in, address.address_length);    \
0032     ACPI_COPY_FIELD(out, in, resource_source);
0033 /* Local prototypes */
0034 static acpi_status
0035 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context);
0036 
0037 static acpi_status
0038 acpi_rs_validate_parameters(acpi_handle device_handle,
0039                 struct acpi_buffer *buffer,
0040                 struct acpi_namespace_node **return_node);
0041 
0042 /*******************************************************************************
0043  *
0044  * FUNCTION:    acpi_rs_validate_parameters
0045  *
0046  * PARAMETERS:  device_handle   - Handle to a device
0047  *              buffer          - Pointer to a data buffer
0048  *              return_node     - Pointer to where the device node is returned
0049  *
0050  * RETURN:      Status
0051  *
0052  * DESCRIPTION: Common parameter validation for resource interfaces
0053  *
0054  ******************************************************************************/
0055 
0056 static acpi_status
0057 acpi_rs_validate_parameters(acpi_handle device_handle,
0058                 struct acpi_buffer *buffer,
0059                 struct acpi_namespace_node **return_node)
0060 {
0061     acpi_status status;
0062     struct acpi_namespace_node *node;
0063 
0064     ACPI_FUNCTION_TRACE(rs_validate_parameters);
0065 
0066     /*
0067      * Must have a valid handle to an ACPI device
0068      */
0069     if (!device_handle) {
0070         return_ACPI_STATUS(AE_BAD_PARAMETER);
0071     }
0072 
0073     node = acpi_ns_validate_handle(device_handle);
0074     if (!node) {
0075         return_ACPI_STATUS(AE_BAD_PARAMETER);
0076     }
0077 
0078     if (node->type != ACPI_TYPE_DEVICE) {
0079         return_ACPI_STATUS(AE_TYPE);
0080     }
0081 
0082     /*
0083      * Validate the user buffer object
0084      *
0085      * if there is a non-zero buffer length we also need a valid pointer in
0086      * the buffer. If it's a zero buffer length, we'll be returning the
0087      * needed buffer size (later), so keep going.
0088      */
0089     status = acpi_ut_validate_buffer(buffer);
0090     if (ACPI_FAILURE(status)) {
0091         return_ACPI_STATUS(status);
0092     }
0093 
0094     *return_node = node;
0095     return_ACPI_STATUS(AE_OK);
0096 }
0097 
0098 /*******************************************************************************
0099  *
0100  * FUNCTION:    acpi_get_irq_routing_table
0101  *
0102  * PARAMETERS:  device_handle   - Handle to the Bus device we are querying
0103  *              ret_buffer      - Pointer to a buffer to receive the
0104  *                                current resources for the device
0105  *
0106  * RETURN:      Status
0107  *
0108  * DESCRIPTION: This function is called to get the IRQ routing table for a
0109  *              specific bus. The caller must first acquire a handle for the
0110  *              desired bus. The routine table is placed in the buffer pointed
0111  *              to by the ret_buffer variable parameter.
0112  *
0113  *              If the function fails an appropriate status will be returned
0114  *              and the value of ret_buffer is undefined.
0115  *
0116  *              This function attempts to execute the _PRT method contained in
0117  *              the object indicated by the passed device_handle.
0118  *
0119  ******************************************************************************/
0120 
0121 acpi_status
0122 acpi_get_irq_routing_table(acpi_handle device_handle,
0123                struct acpi_buffer *ret_buffer)
0124 {
0125     acpi_status status;
0126     struct acpi_namespace_node *node;
0127 
0128     ACPI_FUNCTION_TRACE(acpi_get_irq_routing_table);
0129 
0130     /* Validate parameters then dispatch to internal routine */
0131 
0132     status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
0133     if (ACPI_FAILURE(status)) {
0134         return_ACPI_STATUS(status);
0135     }
0136 
0137     status = acpi_rs_get_prt_method_data(node, ret_buffer);
0138     return_ACPI_STATUS(status);
0139 }
0140 
0141 ACPI_EXPORT_SYMBOL(acpi_get_irq_routing_table)
0142 
0143 /*******************************************************************************
0144  *
0145  * FUNCTION:    acpi_get_current_resources
0146  *
0147  * PARAMETERS:  device_handle   - Handle to the device object for the
0148  *                                device we are querying
0149  *              ret_buffer      - Pointer to a buffer to receive the
0150  *                                current resources for the device
0151  *
0152  * RETURN:      Status
0153  *
0154  * DESCRIPTION: This function is called to get the current resources for a
0155  *              specific device. The caller must first acquire a handle for
0156  *              the desired device. The resource data is placed in the buffer
0157  *              pointed to by the ret_buffer variable parameter.
0158  *
0159  *              If the function fails an appropriate status will be returned
0160  *              and the value of ret_buffer is undefined.
0161  *
0162  *              This function attempts to execute the _CRS method contained in
0163  *              the object indicated by the passed device_handle.
0164  *
0165  ******************************************************************************/
0166 acpi_status
0167 acpi_get_current_resources(acpi_handle device_handle,
0168                struct acpi_buffer *ret_buffer)
0169 {
0170     acpi_status status;
0171     struct acpi_namespace_node *node;
0172 
0173     ACPI_FUNCTION_TRACE(acpi_get_current_resources);
0174 
0175     /* Validate parameters then dispatch to internal routine */
0176 
0177     status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
0178     if (ACPI_FAILURE(status)) {
0179         return_ACPI_STATUS(status);
0180     }
0181 
0182     status = acpi_rs_get_crs_method_data(node, ret_buffer);
0183     return_ACPI_STATUS(status);
0184 }
0185 
0186 ACPI_EXPORT_SYMBOL(acpi_get_current_resources)
0187 
0188 /*******************************************************************************
0189  *
0190  * FUNCTION:    acpi_get_possible_resources
0191  *
0192  * PARAMETERS:  device_handle   - Handle to the device object for the
0193  *                                device we are querying
0194  *              ret_buffer      - Pointer to a buffer to receive the
0195  *                                resources for the device
0196  *
0197  * RETURN:      Status
0198  *
0199  * DESCRIPTION: This function is called to get a list of the possible resources
0200  *              for a specific device. The caller must first acquire a handle
0201  *              for the desired device. The resource data is placed in the
0202  *              buffer pointed to by the ret_buffer variable.
0203  *
0204  *              If the function fails an appropriate status will be returned
0205  *              and the value of ret_buffer is undefined.
0206  *
0207  ******************************************************************************/
0208 acpi_status
0209 acpi_get_possible_resources(acpi_handle device_handle,
0210                 struct acpi_buffer *ret_buffer)
0211 {
0212     acpi_status status;
0213     struct acpi_namespace_node *node;
0214 
0215     ACPI_FUNCTION_TRACE(acpi_get_possible_resources);
0216 
0217     /* Validate parameters then dispatch to internal routine */
0218 
0219     status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
0220     if (ACPI_FAILURE(status)) {
0221         return_ACPI_STATUS(status);
0222     }
0223 
0224     status = acpi_rs_get_prs_method_data(node, ret_buffer);
0225     return_ACPI_STATUS(status);
0226 }
0227 
0228 ACPI_EXPORT_SYMBOL(acpi_get_possible_resources)
0229 
0230 /*******************************************************************************
0231  *
0232  * FUNCTION:    acpi_set_current_resources
0233  *
0234  * PARAMETERS:  device_handle   - Handle to the device object for the
0235  *                                device we are setting resources
0236  *              in_buffer       - Pointer to a buffer containing the
0237  *                                resources to be set for the device
0238  *
0239  * RETURN:      Status
0240  *
0241  * DESCRIPTION: This function is called to set the current resources for a
0242  *              specific device. The caller must first acquire a handle for
0243  *              the desired device. The resource data is passed to the routine
0244  *              the buffer pointed to by the in_buffer variable.
0245  *
0246  ******************************************************************************/
0247 acpi_status
0248 acpi_set_current_resources(acpi_handle device_handle,
0249                struct acpi_buffer *in_buffer)
0250 {
0251     acpi_status status;
0252     struct acpi_namespace_node *node;
0253 
0254     ACPI_FUNCTION_TRACE(acpi_set_current_resources);
0255 
0256     /* Validate the buffer, don't allow zero length */
0257 
0258     if ((!in_buffer) || (!in_buffer->pointer) || (!in_buffer->length)) {
0259         return_ACPI_STATUS(AE_BAD_PARAMETER);
0260     }
0261 
0262     /* Validate parameters then dispatch to internal routine */
0263 
0264     status = acpi_rs_validate_parameters(device_handle, in_buffer, &node);
0265     if (ACPI_FAILURE(status)) {
0266         return_ACPI_STATUS(status);
0267     }
0268 
0269     status = acpi_rs_set_srs_method_data(node, in_buffer);
0270     return_ACPI_STATUS(status);
0271 }
0272 
0273 ACPI_EXPORT_SYMBOL(acpi_set_current_resources)
0274 
0275 /*******************************************************************************
0276  *
0277  * FUNCTION:    acpi_get_event_resources
0278  *
0279  * PARAMETERS:  device_handle   - Handle to the device object for the
0280  *                                device we are getting resources
0281  *              in_buffer       - Pointer to a buffer containing the
0282  *                                resources to be set for the device
0283  *
0284  * RETURN:      Status
0285  *
0286  * DESCRIPTION: This function is called to get the event resources for a
0287  *              specific device. The caller must first acquire a handle for
0288  *              the desired device. The resource data is passed to the routine
0289  *              the buffer pointed to by the in_buffer variable. Uses the
0290  *              _AEI method.
0291  *
0292  ******************************************************************************/
0293 acpi_status
0294 acpi_get_event_resources(acpi_handle device_handle,
0295              struct acpi_buffer *ret_buffer)
0296 {
0297     acpi_status status;
0298     struct acpi_namespace_node *node;
0299 
0300     ACPI_FUNCTION_TRACE(acpi_get_event_resources);
0301 
0302     /* Validate parameters then dispatch to internal routine */
0303 
0304     status = acpi_rs_validate_parameters(device_handle, ret_buffer, &node);
0305     if (ACPI_FAILURE(status)) {
0306         return_ACPI_STATUS(status);
0307     }
0308 
0309     status = acpi_rs_get_aei_method_data(node, ret_buffer);
0310     return_ACPI_STATUS(status);
0311 }
0312 
0313 ACPI_EXPORT_SYMBOL(acpi_get_event_resources)
0314 
0315 /******************************************************************************
0316  *
0317  * FUNCTION:    acpi_resource_to_address64
0318  *
0319  * PARAMETERS:  resource        - Pointer to a resource
0320  *              out             - Pointer to the users's return buffer
0321  *                                (a struct acpi_resource_address64)
0322  *
0323  * RETURN:      Status
0324  *
0325  * DESCRIPTION: If the resource is an address16, address32, or address64,
0326  *              copy it to the address64 return buffer. This saves the
0327  *              caller from having to duplicate code for different-sized
0328  *              addresses.
0329  *
0330  ******************************************************************************/
0331 acpi_status
0332 acpi_resource_to_address64(struct acpi_resource *resource,
0333                struct acpi_resource_address64 *out)
0334 {
0335     struct acpi_resource_address16 *address16;
0336     struct acpi_resource_address32 *address32;
0337 
0338     if (!resource || !out) {
0339         return (AE_BAD_PARAMETER);
0340     }
0341 
0342     /* Convert 16 or 32 address descriptor to 64 */
0343 
0344     switch (resource->type) {
0345     case ACPI_RESOURCE_TYPE_ADDRESS16:
0346 
0347         address16 =
0348             ACPI_CAST_PTR(struct acpi_resource_address16,
0349                   &resource->data);
0350         ACPI_COPY_ADDRESS(out, address16);
0351         break;
0352 
0353     case ACPI_RESOURCE_TYPE_ADDRESS32:
0354 
0355         address32 =
0356             ACPI_CAST_PTR(struct acpi_resource_address32,
0357                   &resource->data);
0358         ACPI_COPY_ADDRESS(out, address32);
0359         break;
0360 
0361     case ACPI_RESOURCE_TYPE_ADDRESS64:
0362 
0363         /* Simple copy for 64 bit source */
0364 
0365         memcpy(out, &resource->data,
0366                sizeof(struct acpi_resource_address64));
0367         break;
0368 
0369     default:
0370 
0371         return (AE_BAD_PARAMETER);
0372     }
0373 
0374     return (AE_OK);
0375 }
0376 
0377 ACPI_EXPORT_SYMBOL(acpi_resource_to_address64)
0378 
0379 /*******************************************************************************
0380  *
0381  * FUNCTION:    acpi_get_vendor_resource
0382  *
0383  * PARAMETERS:  device_handle   - Handle for the parent device object
0384  *              name            - Method name for the parent resource
0385  *                                (METHOD_NAME__CRS or METHOD_NAME__PRS)
0386  *              uuid            - Pointer to the UUID to be matched.
0387  *                                includes both subtype and 16-byte UUID
0388  *              ret_buffer      - Where the vendor resource is returned
0389  *
0390  * RETURN:      Status
0391  *
0392  * DESCRIPTION: Walk a resource template for the specified device to find a
0393  *              vendor-defined resource that matches the supplied UUID and
0394  *              UUID subtype. Returns a struct acpi_resource of type Vendor.
0395  *
0396  ******************************************************************************/
0397 acpi_status
0398 acpi_get_vendor_resource(acpi_handle device_handle,
0399              char *name,
0400              struct acpi_vendor_uuid *uuid,
0401              struct acpi_buffer *ret_buffer)
0402 {
0403     struct acpi_vendor_walk_info info;
0404     acpi_status status;
0405 
0406     /* Other parameters are validated by acpi_walk_resources */
0407 
0408     if (!uuid || !ret_buffer) {
0409         return (AE_BAD_PARAMETER);
0410     }
0411 
0412     info.uuid = uuid;
0413     info.buffer = ret_buffer;
0414     info.status = AE_NOT_EXIST;
0415 
0416     /* Walk the _CRS or _PRS resource list for this device */
0417 
0418     status =
0419         acpi_walk_resources(device_handle, name,
0420                 acpi_rs_match_vendor_resource, &info);
0421     if (ACPI_FAILURE(status)) {
0422         return (status);
0423     }
0424 
0425     return (info.status);
0426 }
0427 
0428 ACPI_EXPORT_SYMBOL(acpi_get_vendor_resource)
0429 
0430 /*******************************************************************************
0431  *
0432  * FUNCTION:    acpi_rs_match_vendor_resource
0433  *
0434  * PARAMETERS:  acpi_walk_resource_callback
0435  *
0436  * RETURN:      Status
0437  *
0438  * DESCRIPTION: Match a vendor resource via the ACPI 3.0 UUID
0439  *
0440  ******************************************************************************/
0441 static acpi_status
0442 acpi_rs_match_vendor_resource(struct acpi_resource *resource, void *context)
0443 {
0444     struct acpi_vendor_walk_info *info = context;
0445     struct acpi_resource_vendor_typed *vendor;
0446     struct acpi_buffer *buffer;
0447     acpi_status status;
0448 
0449     /* Ignore all descriptors except Vendor */
0450 
0451     if (resource->type != ACPI_RESOURCE_TYPE_VENDOR) {
0452         return (AE_OK);
0453     }
0454 
0455     vendor = &resource->data.vendor_typed;
0456 
0457     /*
0458      * For a valid match, these conditions must hold:
0459      *
0460      * 1) Length of descriptor data must be at least as long as a UUID struct
0461      * 2) The UUID subtypes must match
0462      * 3) The UUID data must match
0463      */
0464     if ((vendor->byte_length < (ACPI_UUID_LENGTH + 1)) ||
0465         (vendor->uuid_subtype != info->uuid->subtype) ||
0466         (memcmp(vendor->uuid, info->uuid->data, ACPI_UUID_LENGTH))) {
0467         return (AE_OK);
0468     }
0469 
0470     /* Validate/Allocate/Clear caller buffer */
0471 
0472     buffer = info->buffer;
0473     status = acpi_ut_initialize_buffer(buffer, resource->length);
0474     if (ACPI_FAILURE(status)) {
0475         return (status);
0476     }
0477 
0478     /* Found the correct resource, copy and return it */
0479 
0480     memcpy(buffer->pointer, resource, resource->length);
0481     buffer->length = resource->length;
0482 
0483     /* Found the desired descriptor, terminate resource walk */
0484 
0485     info->status = AE_OK;
0486     return (AE_CTRL_TERMINATE);
0487 }
0488 
0489 /*******************************************************************************
0490  *
0491  * FUNCTION:    acpi_walk_resource_buffer
0492  *
0493  * PARAMETERS:  buffer          - Formatted buffer returned by one of the
0494  *                                various Get*Resource functions
0495  *              user_function   - Called for each resource
0496  *              context         - Passed to user_function
0497  *
0498  * RETURN:      Status
0499  *
0500  * DESCRIPTION: Walks the input resource template. The user_function is called
0501  *              once for each resource in the list.
0502  *
0503  ******************************************************************************/
0504 
0505 acpi_status
0506 acpi_walk_resource_buffer(struct acpi_buffer *buffer,
0507               acpi_walk_resource_callback user_function,
0508               void *context)
0509 {
0510     acpi_status status = AE_OK;
0511     struct acpi_resource *resource;
0512     struct acpi_resource *resource_end;
0513 
0514     ACPI_FUNCTION_TRACE(acpi_walk_resource_buffer);
0515 
0516     /* Parameter validation */
0517 
0518     if (!buffer || !buffer->pointer || !user_function) {
0519         return_ACPI_STATUS(AE_BAD_PARAMETER);
0520     }
0521 
0522     /* Buffer contains the resource list and length */
0523 
0524     resource = ACPI_CAST_PTR(struct acpi_resource, buffer->pointer);
0525     resource_end =
0526         ACPI_ADD_PTR(struct acpi_resource, buffer->pointer, buffer->length);
0527 
0528     /* Walk the resource list until the end_tag is found (or buffer end) */
0529 
0530     while (resource < resource_end) {
0531 
0532         /* Sanity check the resource type */
0533 
0534         if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
0535             status = AE_AML_INVALID_RESOURCE_TYPE;
0536             break;
0537         }
0538 
0539         /* Sanity check the length. It must not be zero, or we loop forever */
0540 
0541         if (!resource->length) {
0542             return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
0543         }
0544 
0545         /* Invoke the user function, abort on any error returned */
0546 
0547         status = user_function(resource, context);
0548         if (ACPI_FAILURE(status)) {
0549             if (status == AE_CTRL_TERMINATE) {
0550 
0551                 /* This is an OK termination by the user function */
0552 
0553                 status = AE_OK;
0554             }
0555             break;
0556         }
0557 
0558         /* end_tag indicates end-of-list */
0559 
0560         if (resource->type == ACPI_RESOURCE_TYPE_END_TAG) {
0561             break;
0562         }
0563 
0564         /* Get the next resource descriptor */
0565 
0566         resource = ACPI_NEXT_RESOURCE(resource);
0567     }
0568 
0569     return_ACPI_STATUS(status);
0570 }
0571 
0572 ACPI_EXPORT_SYMBOL(acpi_walk_resource_buffer)
0573 
0574 /*******************************************************************************
0575  *
0576  * FUNCTION:    acpi_walk_resources
0577  *
0578  * PARAMETERS:  device_handle   - Handle to the device object for the
0579  *                                device we are querying
0580  *              name            - Method name of the resources we want.
0581  *                                (METHOD_NAME__CRS, METHOD_NAME__PRS, or
0582  *                                METHOD_NAME__AEI or METHOD_NAME__DMA)
0583  *              user_function   - Called for each resource
0584  *              context         - Passed to user_function
0585  *
0586  * RETURN:      Status
0587  *
0588  * DESCRIPTION: Retrieves the current or possible resource list for the
0589  *              specified device. The user_function is called once for
0590  *              each resource in the list.
0591  *
0592  ******************************************************************************/
0593 acpi_status
0594 acpi_walk_resources(acpi_handle device_handle,
0595             char *name,
0596             acpi_walk_resource_callback user_function, void *context)
0597 {
0598     acpi_status status;
0599     struct acpi_buffer buffer;
0600 
0601     ACPI_FUNCTION_TRACE(acpi_walk_resources);
0602 
0603     /* Parameter validation */
0604 
0605     if (!device_handle || !user_function || !name ||
0606         (!ACPI_COMPARE_NAMESEG(name, METHOD_NAME__CRS) &&
0607          !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__PRS) &&
0608          !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__AEI) &&
0609          !ACPI_COMPARE_NAMESEG(name, METHOD_NAME__DMA))) {
0610         return_ACPI_STATUS(AE_BAD_PARAMETER);
0611     }
0612 
0613     /* Get the _CRS/_PRS/_AEI/_DMA resource list */
0614 
0615     buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
0616     status = acpi_rs_get_method_data(device_handle, name, &buffer);
0617     if (ACPI_FAILURE(status)) {
0618         return_ACPI_STATUS(status);
0619     }
0620 
0621     /* Walk the resource list and cleanup */
0622 
0623     status = acpi_walk_resource_buffer(&buffer, user_function, context);
0624     ACPI_FREE(buffer.pointer);
0625     return_ACPI_STATUS(status);
0626 }
0627 
0628 ACPI_EXPORT_SYMBOL(acpi_walk_resources)