1 /*******************************************************************************
3 * Module Name: rsutils - Utilities for the resource manager
5 ******************************************************************************/
8 * Copyright (C) 2000 - 2005, R. Byron Moore
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
44 #include <acpi/acpi.h>
45 #include <acpi/acnamesp.h>
46 #include <acpi/acresrc.h>
48 #define _COMPONENT ACPI_RESOURCES
49 ACPI_MODULE_NAME("rsutils")
51 /*******************************************************************************
53 * FUNCTION: acpi_rs_decode_bitmask
55 * PARAMETERS: Mask - Bitmask to decode
56 * List - Where the converted list is returned
58 * RETURN: Count of bits set (length of list)
60 * DESCRIPTION: Convert a bit mask into a list of values
62 ******************************************************************************/
63 u8
acpi_rs_decode_bitmask(u16 mask
, u8
* list
)
68 /* Decode the mask bits */
70 for (i
= 0, bit_count
= 0; mask
; i
++) {
72 list
[bit_count
] = (u8
) i
;
82 /*******************************************************************************
84 * FUNCTION: acpi_rs_encode_bitmask
86 * PARAMETERS: List - List of values to encode
87 * Count - Length of list
89 * RETURN: Encoded bitmask
91 * DESCRIPTION: Convert a list of values to an encoded bitmask
93 ******************************************************************************/
95 u16
acpi_rs_encode_bitmask(u8
* list
, u8 count
)
100 /* Encode the list into a single bitmask */
102 for (i
= 0, mask
= 0; i
< count
; i
++) {
103 mask
|= (0x0001 << list
[i
]);
109 /*******************************************************************************
111 * FUNCTION: acpi_rs_move_data
113 * PARAMETERS: Destination - Pointer to the destination descriptor
114 * Source - Pointer to the source descriptor
115 * item_count - How many items to move
116 * move_type - Byte width
120 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
121 * alignment issues and endian issues if necessary, as configured
122 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
124 ******************************************************************************/
127 acpi_rs_move_data(void *destination
, void *source
, u16 item_count
, u8 move_type
)
131 /* One move per item */
133 for (i
= 0; i
< item_count
; i
++) {
136 * For the 8-bit case, we can perform the move all at once
137 * since there are no alignment or endian issues
140 ACPI_MEMCPY(destination
, source
, item_count
);
144 * 16-, 32-, and 64-bit cases must use the move macros that perform
145 * endian conversion and/or accomodate hardware that cannot perform
146 * misaligned memory transfers
148 case ACPI_RSC_MOVE16
:
149 ACPI_MOVE_16_TO_16(&((u16
*) destination
)[i
],
150 &((u16
*) source
)[i
]);
153 case ACPI_RSC_MOVE32
:
154 ACPI_MOVE_32_TO_32(&((u32
*) destination
)[i
],
155 &((u32
*) source
)[i
]);
158 case ACPI_RSC_MOVE64
:
159 ACPI_MOVE_64_TO_64(&((u64
*) destination
)[i
],
160 &((u64
*) source
)[i
]);
169 /*******************************************************************************
171 * FUNCTION: acpi_rs_get_resource_info
173 * PARAMETERS: resource_type - Byte 0 of a resource descriptor
175 * RETURN: Pointer to the resource conversion handler
177 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
178 * a resource descriptor.
180 ******************************************************************************/
182 struct acpi_resource_info
*acpi_rs_get_resource_info(u8 resource_type
)
184 struct acpi_resource_info
*size_info
;
186 ACPI_FUNCTION_ENTRY();
188 /* Determine if this is a small or large resource */
190 if (resource_type
& ACPI_RESOURCE_NAME_LARGE
) {
191 /* Large Resource Type -- bits 6:0 contain the name */
193 if (resource_type
> ACPI_RESOURCE_NAME_LARGE_MAX
) {
197 size_info
= &acpi_gbl_lg_resource_info
[(resource_type
&
198 ACPI_RESOURCE_NAME_LARGE_MASK
)];
200 /* Small Resource Type -- bits 6:3 contain the name */
202 size_info
= &acpi_gbl_sm_resource_info
[((resource_type
&
203 ACPI_RESOURCE_NAME_SMALL_MASK
)
207 /* Zero entry indicates an invalid resource type */
209 if (!size_info
->minimum_internal_struct_length
) {
216 /*******************************************************************************
218 * FUNCTION: acpi_rs_set_resource_length
220 * PARAMETERS: total_length - Length of the AML descriptor, including
221 * the header and length fields.
222 * Aml - Pointer to the raw AML descriptor
226 * DESCRIPTION: Set the resource_length field of an AML
227 * resource descriptor, both Large and Small descriptors are
228 * supported automatically. Note: Descriptor Type field must
231 ******************************************************************************/
234 acpi_rs_set_resource_length(acpi_rsdesc_size total_length
,
235 union aml_resource
*aml
)
237 acpi_rs_length resource_length
;
239 ACPI_FUNCTION_ENTRY();
241 /* Determine if this is a small or large resource */
243 if (aml
->small_header
.descriptor_type
& ACPI_RESOURCE_NAME_LARGE
) {
244 /* Large Resource type -- bytes 1-2 contain the 16-bit length */
246 resource_length
= (acpi_rs_length
)
247 (total_length
- sizeof(struct aml_resource_large_header
));
249 /* Insert length into the Large descriptor length field */
251 ACPI_MOVE_16_TO_16(&aml
->large_header
.resource_length
,
254 /* Small Resource type -- bits 2:0 of byte 0 contain the length */
256 resource_length
= (acpi_rs_length
)
257 (total_length
- sizeof(struct aml_resource_small_header
));
259 /* Insert length into the descriptor type byte */
261 aml
->small_header
.descriptor_type
= (u8
)
263 /* Clear any existing length, preserving descriptor type bits */
265 descriptor_type
& ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK
)
271 /*******************************************************************************
273 * FUNCTION: acpi_rs_set_resource_header
275 * PARAMETERS: descriptor_type - Byte to be inserted as the type
276 * total_length - Length of the AML descriptor, including
277 * the header and length fields.
278 * Aml - Pointer to the raw AML descriptor
282 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
283 * resource descriptor, both Large and Small descriptors are
284 * supported automatically
286 ******************************************************************************/
289 acpi_rs_set_resource_header(u8 descriptor_type
,
290 acpi_rsdesc_size total_length
,
291 union aml_resource
*aml
)
293 ACPI_FUNCTION_ENTRY();
295 /* Set the Descriptor Type */
297 aml
->small_header
.descriptor_type
= descriptor_type
;
299 /* Set the Resource Length */
301 acpi_rs_set_resource_length(total_length
, aml
);
304 /*******************************************************************************
306 * FUNCTION: acpi_rs_strcpy
308 * PARAMETERS: Destination - Pointer to the destination string
309 * Source - Pointer to the source string
311 * RETURN: String length, including NULL terminator
313 * DESCRIPTION: Local string copy that returns the string length, saving a
314 * strcpy followed by a strlen.
316 ******************************************************************************/
318 static u16
acpi_rs_strcpy(char *destination
, char *source
)
322 ACPI_FUNCTION_ENTRY();
324 for (i
= 0; source
[i
]; i
++) {
325 destination
[i
] = source
[i
];
330 /* Return string length including the NULL terminator */
332 return ((u16
) (i
+ 1));
335 /*******************************************************************************
337 * FUNCTION: acpi_rs_get_resource_source
339 * PARAMETERS: resource_length - Length field of the descriptor
340 * minimum_length - Minimum length of the descriptor (minus
341 * any optional fields)
342 * resource_source - Where the resource_source is returned
343 * Aml - Pointer to the raw AML descriptor
344 * string_ptr - (optional) where to store the actual
345 * resource_source string
347 * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
349 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
350 * to an internal resource descriptor
352 ******************************************************************************/
355 acpi_rs_get_resource_source(acpi_rs_length resource_length
,
356 acpi_rs_length minimum_length
,
357 struct acpi_resource_source
* resource_source
,
358 union aml_resource
* aml
, char *string_ptr
)
360 acpi_rsdesc_size total_length
;
361 u8
*aml_resource_source
;
363 ACPI_FUNCTION_ENTRY();
366 resource_length
+ sizeof(struct aml_resource_large_header
);
367 aml_resource_source
= ((u8
*) aml
) + minimum_length
;
370 * resource_source is present if the length of the descriptor is longer than
371 * the minimum length.
373 * Note: Some resource descriptors will have an additional null, so
374 * we add 1 to the minimum length.
376 if (total_length
> (acpi_rsdesc_size
) (minimum_length
+ 1)) {
377 /* Get the resource_source_index */
379 resource_source
->index
= aml_resource_source
[0];
381 resource_source
->string_ptr
= string_ptr
;
384 * String destination pointer is not specified; Set the String
385 * pointer to the end of the current resource_source structure.
387 resource_source
->string_ptr
= (char *)
388 ((u8
*) resource_source
) +
389 sizeof(struct acpi_resource_source
);
393 * In order for the struct_size to fall on a 32-bit boundary, calculate
394 * the length of the string (+1 for the NULL terminator) and expand the
395 * struct_size to the next 32-bit boundary.
397 * Zero the entire area of the buffer.
400 ACPI_ROUND_UP_to_32_bITS(ACPI_STRLEN
401 ((char *)&aml_resource_source
[1]) +
403 ACPI_MEMSET(resource_source
->string_ptr
, 0, total_length
);
405 /* Copy the resource_source string to the destination */
407 resource_source
->string_length
=
408 acpi_rs_strcpy(resource_source
->string_ptr
,
409 (char *)&aml_resource_source
[1]);
411 return ((acpi_rs_length
) total_length
);
413 /* resource_source is not present */
415 resource_source
->index
= 0;
416 resource_source
->string_length
= 0;
417 resource_source
->string_ptr
= NULL
;
422 /*******************************************************************************
424 * FUNCTION: acpi_rs_set_resource_source
426 * PARAMETERS: Aml - Pointer to the raw AML descriptor
427 * minimum_length - Minimum length of the descriptor (minus
428 * any optional fields)
429 * resource_source - Internal resource_source
432 * RETURN: Total length of the AML descriptor
434 * DESCRIPTION: Convert an optional resource_source from internal format to a
435 * raw AML resource descriptor
437 ******************************************************************************/
440 acpi_rs_set_resource_source(union aml_resource
* aml
,
441 acpi_rs_length minimum_length
,
442 struct acpi_resource_source
* resource_source
)
444 u8
*aml_resource_source
;
445 acpi_rsdesc_size descriptor_length
;
447 ACPI_FUNCTION_ENTRY();
449 descriptor_length
= minimum_length
;
451 /* Non-zero string length indicates presence of a resource_source */
453 if (resource_source
->string_length
) {
454 /* Point to the end of the AML descriptor */
456 aml_resource_source
= ((u8
*) aml
) + minimum_length
;
458 /* Copy the resource_source_index */
460 aml_resource_source
[0] = (u8
) resource_source
->index
;
462 /* Copy the resource_source string */
464 ACPI_STRCPY((char *)&aml_resource_source
[1],
465 resource_source
->string_ptr
);
468 * Add the length of the string (+ 1 for null terminator) to the
469 * final descriptor length
472 ((acpi_rsdesc_size
) resource_source
->string_length
+ 1);
475 /* Return the new total length of the AML descriptor */
477 return (descriptor_length
);
480 /*******************************************************************************
482 * FUNCTION: acpi_rs_get_prt_method_data
484 * PARAMETERS: Handle - a handle to the containing object
485 * ret_buffer - a pointer to a buffer structure for the
490 * DESCRIPTION: This function is called to get the _PRT value of an object
491 * contained in an object specified by the handle passed in
493 * If the function fails an appropriate status will be returned
494 * and the contents of the callers buffer is undefined.
496 ******************************************************************************/
499 acpi_rs_get_prt_method_data(acpi_handle handle
, struct acpi_buffer
* ret_buffer
)
501 union acpi_operand_object
*obj_desc
;
504 ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
506 /* Parameters guaranteed valid by caller */
508 /* Execute the method, no parameters */
510 status
= acpi_ut_evaluate_object(handle
, METHOD_NAME__PRT
,
511 ACPI_BTYPE_PACKAGE
, &obj_desc
);
512 if (ACPI_FAILURE(status
)) {
513 return_ACPI_STATUS(status
);
517 * Create a resource linked list from the byte stream buffer that comes
518 * back from the _CRS method execution.
520 status
= acpi_rs_create_pci_routing_table(obj_desc
, ret_buffer
);
522 /* On exit, we must delete the object returned by evaluate_object */
524 acpi_ut_remove_reference(obj_desc
);
525 return_ACPI_STATUS(status
);
528 /*******************************************************************************
530 * FUNCTION: acpi_rs_get_crs_method_data
532 * PARAMETERS: Handle - a handle to the containing object
533 * ret_buffer - a pointer to a buffer structure for the
538 * DESCRIPTION: This function is called to get the _CRS value of an object
539 * contained in an object specified by the handle passed in
541 * If the function fails an appropriate status will be returned
542 * and the contents of the callers buffer is undefined.
544 ******************************************************************************/
547 acpi_rs_get_crs_method_data(acpi_handle handle
, struct acpi_buffer
*ret_buffer
)
549 union acpi_operand_object
*obj_desc
;
552 ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
554 /* Parameters guaranteed valid by caller */
556 /* Execute the method, no parameters */
558 status
= acpi_ut_evaluate_object(handle
, METHOD_NAME__CRS
,
559 ACPI_BTYPE_BUFFER
, &obj_desc
);
560 if (ACPI_FAILURE(status
)) {
561 return_ACPI_STATUS(status
);
565 * Make the call to create a resource linked list from the
566 * byte stream buffer that comes back from the _CRS method
569 status
= acpi_rs_create_resource_list(obj_desc
, ret_buffer
);
571 /* on exit, we must delete the object returned by evaluate_object */
573 acpi_ut_remove_reference(obj_desc
);
574 return_ACPI_STATUS(status
);
577 /*******************************************************************************
579 * FUNCTION: acpi_rs_get_prs_method_data
581 * PARAMETERS: Handle - a handle to the containing object
582 * ret_buffer - a pointer to a buffer structure for the
587 * DESCRIPTION: This function is called to get the _PRS value of an object
588 * contained in an object specified by the handle passed in
590 * If the function fails an appropriate status will be returned
591 * and the contents of the callers buffer is undefined.
593 ******************************************************************************/
595 #ifdef ACPI_FUTURE_USAGE
597 acpi_rs_get_prs_method_data(acpi_handle handle
, struct acpi_buffer
*ret_buffer
)
599 union acpi_operand_object
*obj_desc
;
602 ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
604 /* Parameters guaranteed valid by caller */
606 /* Execute the method, no parameters */
608 status
= acpi_ut_evaluate_object(handle
, METHOD_NAME__PRS
,
609 ACPI_BTYPE_BUFFER
, &obj_desc
);
610 if (ACPI_FAILURE(status
)) {
611 return_ACPI_STATUS(status
);
615 * Make the call to create a resource linked list from the
616 * byte stream buffer that comes back from the _CRS method
619 status
= acpi_rs_create_resource_list(obj_desc
, ret_buffer
);
621 /* on exit, we must delete the object returned by evaluate_object */
623 acpi_ut_remove_reference(obj_desc
);
624 return_ACPI_STATUS(status
);
626 #endif /* ACPI_FUTURE_USAGE */
628 /*******************************************************************************
630 * FUNCTION: acpi_rs_get_method_data
632 * PARAMETERS: Handle - a handle to the containing object
633 * Path - Path to method, relative to Handle
634 * ret_buffer - a pointer to a buffer structure for the
639 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
640 * object contained in an object specified by the handle passed in
642 * If the function fails an appropriate status will be returned
643 * and the contents of the callers buffer is undefined.
645 ******************************************************************************/
648 acpi_rs_get_method_data(acpi_handle handle
,
649 char *path
, struct acpi_buffer
*ret_buffer
)
651 union acpi_operand_object
*obj_desc
;
654 ACPI_FUNCTION_TRACE("rs_get_method_data");
656 /* Parameters guaranteed valid by caller */
658 /* Execute the method, no parameters */
661 acpi_ut_evaluate_object(handle
, path
, ACPI_BTYPE_BUFFER
, &obj_desc
);
662 if (ACPI_FAILURE(status
)) {
663 return_ACPI_STATUS(status
);
667 * Make the call to create a resource linked list from the
668 * byte stream buffer that comes back from the method
671 status
= acpi_rs_create_resource_list(obj_desc
, ret_buffer
);
673 /* On exit, we must delete the object returned by evaluate_object */
675 acpi_ut_remove_reference(obj_desc
);
676 return_ACPI_STATUS(status
);
679 /*******************************************************************************
681 * FUNCTION: acpi_rs_set_srs_method_data
683 * PARAMETERS: Handle - a handle to the containing object
684 * in_buffer - a pointer to a buffer structure of the
689 * DESCRIPTION: This function is called to set the _SRS of an object contained
690 * in an object specified by the handle passed in
692 * If the function fails an appropriate status will be returned
693 * and the contents of the callers buffer is undefined.
695 ******************************************************************************/
698 acpi_rs_set_srs_method_data(acpi_handle handle
, struct acpi_buffer
*in_buffer
)
700 struct acpi_parameter_info info
;
701 union acpi_operand_object
*params
[2];
703 struct acpi_buffer buffer
;
705 ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
707 /* Parameters guaranteed valid by caller */
710 * The in_buffer parameter will point to a linked list of
711 * resource parameters. It needs to be formatted into a
712 * byte stream to be sent in as an input parameter to _SRS
714 * Convert the linked list into a byte stream
716 buffer
.length
= ACPI_ALLOCATE_LOCAL_BUFFER
;
717 status
= acpi_rs_create_aml_resources(in_buffer
->pointer
, &buffer
);
718 if (ACPI_FAILURE(status
)) {
719 return_ACPI_STATUS(status
);
722 /* Init the param object */
724 params
[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER
);
726 acpi_os_free(buffer
.pointer
);
727 return_ACPI_STATUS(AE_NO_MEMORY
);
730 /* Set up the parameter object */
732 params
[0]->buffer
.length
= (u32
) buffer
.length
;
733 params
[0]->buffer
.pointer
= buffer
.pointer
;
734 params
[0]->common
.flags
= AOPOBJ_DATA_VALID
;
738 info
.parameters
= params
;
739 info
.parameter_type
= ACPI_PARAM_ARGS
;
741 /* Execute the method, no return value */
743 status
= acpi_ns_evaluate_relative(METHOD_NAME__SRS
, &info
);
744 if (ACPI_SUCCESS(status
)) {
745 /* Delete any return object (especially if implicit_return is enabled) */
747 if (info
.return_object
) {
748 acpi_ut_remove_reference(info
.return_object
);
752 /* Clean up and return the status from acpi_ns_evaluate_relative */
754 acpi_ut_remove_reference(params
[0]);
755 return_ACPI_STATUS(status
);