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_move_data
55 * PARAMETERS: Destination - Pointer to the destination descriptor
56 * Source - Pointer to the source descriptor
57 * item_count - How many items to move
58 * move_type - Byte width
62 * DESCRIPTION: Move multiple data items from one descriptor to another. Handles
63 * alignment issues and endian issues if necessary, as configured
64 * via the ACPI_MOVE_* macros. (This is why a memcpy is not used)
66 ******************************************************************************/
68 acpi_rs_move_data(void *destination, void *source, u16 item_count, u8 move_type)
72 /* One move per item */
74 for (i = 0; i < item_count; i++) {
76 case ACPI_MOVE_TYPE_16_TO_32:
77 ACPI_MOVE_16_TO_32(&((u32 *) destination)[i],
78 &((u16 *) source)[i]);
81 case ACPI_MOVE_TYPE_32_TO_16:
82 ACPI_MOVE_32_TO_16(&((u16 *) destination)[i],
83 &((u32 *) source)[i]);
86 case ACPI_MOVE_TYPE_32_TO_32:
87 ACPI_MOVE_32_TO_32(&((u32 *) destination)[i],
88 &((u32 *) source)[i]);
91 case ACPI_MOVE_TYPE_64_TO_64:
92 ACPI_MOVE_64_TO_64(&((u64 *) destination)[i],
93 &((u64 *) source)[i]);
102 /*******************************************************************************
104 * FUNCTION: acpi_rs_get_resource_info
106 * PARAMETERS: resource_type - Byte 0 of a resource descriptor
108 * RETURN: Pointer to the resource conversion handler
110 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
111 * a resource descriptor.
113 ******************************************************************************/
115 struct acpi_resource_info *acpi_rs_get_resource_info(u8 resource_type)
117 struct acpi_resource_info *size_info;
119 ACPI_FUNCTION_ENTRY();
121 /* Determine if this is a small or large resource */
123 if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
124 /* Large Resource Type -- bits 6:0 contain the name */
126 if (resource_type > ACPI_RESOURCE_NAME_LARGE_MAX) {
130 size_info = &acpi_gbl_lg_resource_info[(resource_type &
131 ACPI_RESOURCE_NAME_LARGE_MASK)];
133 /* Small Resource Type -- bits 6:3 contain the name */
135 size_info = &acpi_gbl_sm_resource_info[((resource_type &
136 ACPI_RESOURCE_NAME_SMALL_MASK)
140 /* Zero entry indicates an invalid resource type */
142 if (!size_info->minimum_internal_struct_length) {
149 /*******************************************************************************
151 * FUNCTION: acpi_rs_get_resource_length
153 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
155 * RETURN: Byte Length
157 * DESCRIPTION: Get the "Resource Length" of a raw AML descriptor. By
158 * definition, this does not include the size of the descriptor
159 * header or the length field itself.
161 ******************************************************************************/
163 u16 acpi_rs_get_resource_length(union aml_resource * aml)
167 ACPI_FUNCTION_ENTRY();
169 /* Determine if this is a small or large resource */
171 if (aml->large_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
172 /* Large Resource type -- bytes 1-2 contain the 16-bit length */
174 ACPI_MOVE_16_TO_16(&resource_length,
175 &aml->large_header.resource_length);
178 /* Small Resource type -- bits 2:0 of byte 0 contain the length */
180 resource_length = (u16) (aml->small_header.descriptor_type &
181 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
184 return (resource_length);
187 /*******************************************************************************
189 * FUNCTION: acpi_rs_get_descriptor_length
191 * PARAMETERS: Aml - Pointer to the raw AML resource descriptor
193 * RETURN: Byte length
195 * DESCRIPTION: Get the total byte length of a raw AML descriptor, including the
196 * length of the descriptor header and the length field itself.
197 * Used to walk descriptor lists.
199 ******************************************************************************/
201 u32 acpi_rs_get_descriptor_length(union aml_resource * aml)
203 u32 descriptor_length;
205 ACPI_FUNCTION_ENTRY();
207 /* Determine if this is a small or large resource */
209 if (aml->large_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
210 /* Large Resource type -- bytes 1-2 contain the 16-bit length */
212 ACPI_MOVE_16_TO_32(&descriptor_length,
213 &aml->large_header.resource_length);
214 descriptor_length += sizeof(struct aml_resource_large_header);
217 /* Small Resource type -- bits 2:0 of byte 0 contain the length */
219 descriptor_length = (u32) (aml->small_header.descriptor_type &
220 ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK);
221 descriptor_length += sizeof(struct aml_resource_small_header);
224 return (descriptor_length);
227 /*******************************************************************************
229 * FUNCTION: acpi_rs_set_resource_header
231 * PARAMETERS: descriptor_type - Byte to be inserted as the type
232 * total_length - Length of the AML descriptor, including
233 * the header and length fields.
234 * Aml - Pointer to the raw AML descriptor
238 * DESCRIPTION: Set the descriptor_type and resource_length fields of an AML
239 * resource descriptor, both Large and Small descriptors are
240 * supported automatically
242 ******************************************************************************/
245 acpi_rs_set_resource_header(u8 descriptor_type,
246 acpi_size total_length, union aml_resource *aml)
250 ACPI_FUNCTION_ENTRY();
252 /* Set the descriptor type */
254 aml->small_header.descriptor_type = descriptor_type;
256 /* Determine if this is a small or large resource */
258 if (aml->small_header.descriptor_type & ACPI_RESOURCE_NAME_LARGE) {
259 /* Large Resource type -- bytes 1-2 contain the 16-bit length */
262 (u16) (total_length -
263 sizeof(struct aml_resource_large_header));
265 /* Insert length into the Large descriptor length field */
267 ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
270 /* Small Resource type -- bits 2:0 of byte 0 contain the length */
273 (u16) (total_length -
274 sizeof(struct aml_resource_small_header));
276 /* Insert length into the descriptor type byte */
278 aml->small_header.descriptor_type |= (u8) resource_length;
282 /*******************************************************************************
284 * FUNCTION: acpi_rs_get_resource_type
286 * PARAMETERS: resource_type - Byte 0 of a resource descriptor
288 * RETURN: The Resource Type with no extraneous bits (except the
289 * Large/Small descriptor bit -- this is left alone)
291 * DESCRIPTION: Extract the Resource Type/Name from the first byte of
292 * a resource descriptor.
294 ******************************************************************************/
296 u8 acpi_rs_get_resource_type(u8 resource_type)
298 ACPI_FUNCTION_ENTRY();
300 /* Determine if this is a small or large resource */
302 if (resource_type & ACPI_RESOURCE_NAME_LARGE) {
303 /* Large Resource Type -- bits 6:0 contain the name */
305 return (resource_type);
307 /* Small Resource Type -- bits 6:3 contain the name */
309 return ((u8) (resource_type & ACPI_RESOURCE_NAME_SMALL_MASK));
313 /*******************************************************************************
315 * FUNCTION: acpi_rs_strcpy
317 * PARAMETERS: Destination - Pointer to the destination string
318 * Source - Pointer to the source string
320 * RETURN: String length, including NULL terminator
322 * DESCRIPTION: Local string copy that returns the string length, saving a
323 * strcpy followed by a strlen.
325 ******************************************************************************/
327 static u16 acpi_rs_strcpy(char *destination, char *source)
331 ACPI_FUNCTION_ENTRY();
333 for (i = 0; source[i]; i++) {
334 destination[i] = source[i];
339 /* Return string length including the NULL terminator */
341 return ((u16) (i + 1));
344 /*******************************************************************************
346 * FUNCTION: acpi_rs_get_resource_source
348 * PARAMETERS: resource_length - Length field of the descriptor
349 * minimum_length - Minimum length of the descriptor (minus
350 * any optional fields)
351 * resource_source - Where the resource_source is returned
352 * Aml - Pointer to the raw AML descriptor
353 * string_ptr - (optional) where to store the actual
354 * resource_source string
356 * RETURN: Length of the string plus NULL terminator, rounded up to 32 bit
358 * DESCRIPTION: Copy the optional resource_source data from a raw AML descriptor
359 * to an internal resource descriptor
361 ******************************************************************************/
364 acpi_rs_get_resource_source(u16 resource_length,
365 acpi_size minimum_length,
366 struct acpi_resource_source * resource_source,
367 union aml_resource * aml, char *string_ptr)
369 acpi_size total_length;
370 u8 *aml_resource_source;
372 ACPI_FUNCTION_ENTRY();
375 resource_length + sizeof(struct aml_resource_large_header);
376 aml_resource_source = ((u8 *) aml) + minimum_length;
379 * resource_source is present if the length of the descriptor is longer than
380 * the minimum length.
382 * Note: Some resource descriptors will have an additional null, so
383 * we add 1 to the minimum length.
385 if (total_length > (minimum_length + 1)) {
386 /* Get the resource_source_index */
388 resource_source->index = aml_resource_source[0];
390 resource_source->string_ptr = string_ptr;
393 * String destination pointer is not specified; Set the String
394 * pointer to the end of the current resource_source structure.
396 resource_source->string_ptr = (char *)
397 ((u8 *) resource_source) +
398 sizeof(struct acpi_resource_source);
401 /* Copy the resource_source string to the destination */
403 resource_source->string_length =
404 acpi_rs_strcpy(resource_source->string_ptr,
405 (char *)&aml_resource_source[1]);
408 * In order for the struct_size to fall on a 32-bit boundary,
409 * calculate the length of the string and expand the
410 * struct_size to the next 32-bit boundary.
413 ACPI_ROUND_UP_to_32_bITS(resource_source->
416 /* resource_source is not present */
418 resource_source->index = 0;
419 resource_source->string_length = 0;
420 resource_source->string_ptr = NULL;
425 /*******************************************************************************
427 * FUNCTION: acpi_rs_set_resource_source
429 * PARAMETERS: Aml - Pointer to the raw AML descriptor
430 * minimum_length - Minimum length of the descriptor (minus
431 * any optional fields)
432 * resource_source - Internal resource_source
435 * RETURN: Total length of the AML descriptor
437 * DESCRIPTION: Convert an optoinal resource_source from internal format to a
438 * raw AML resource descriptor
440 ******************************************************************************/
443 acpi_rs_set_resource_source(union aml_resource * aml,
444 acpi_size minimum_length,
445 struct acpi_resource_source * resource_source)
447 u8 *aml_resource_source;
448 acpi_size descriptor_length;
450 ACPI_FUNCTION_ENTRY();
452 descriptor_length = minimum_length;
454 /* Non-zero string length indicates presence of a resource_source */
456 if (resource_source->string_length) {
457 /* Point to the end of the AML descriptor */
459 aml_resource_source = ((u8 *) aml) + minimum_length;
461 /* Copy the resource_source_index */
463 aml_resource_source[0] = (u8) resource_source->index;
465 /* Copy the resource_source string */
467 ACPI_STRCPY((char *)&aml_resource_source[1],
468 resource_source->string_ptr);
471 * Add the length of the string (+ 1 for null terminator) to the
472 * final descriptor length
475 ((acpi_size) resource_source->string_length + 1);
478 /* Return the new total length of the AML descriptor */
480 return (descriptor_length);
483 /*******************************************************************************
485 * FUNCTION: acpi_rs_get_prt_method_data
487 * PARAMETERS: Handle - a handle to the containing object
488 * ret_buffer - a pointer to a buffer structure for the
493 * DESCRIPTION: This function is called to get the _PRT value of an object
494 * contained in an object specified by the handle passed in
496 * If the function fails an appropriate status will be returned
497 * and the contents of the callers buffer is undefined.
499 ******************************************************************************/
502 acpi_rs_get_prt_method_data(acpi_handle handle, struct acpi_buffer * ret_buffer)
504 union acpi_operand_object *obj_desc;
507 ACPI_FUNCTION_TRACE("rs_get_prt_method_data");
509 /* Parameters guaranteed valid by caller */
511 /* Execute the method, no parameters */
513 status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRT,
514 ACPI_BTYPE_PACKAGE, &obj_desc);
515 if (ACPI_FAILURE(status)) {
516 return_ACPI_STATUS(status);
520 * Create a resource linked list from the byte stream buffer that comes
521 * back from the _CRS method execution.
523 status = acpi_rs_create_pci_routing_table(obj_desc, ret_buffer);
525 /* On exit, we must delete the object returned by evaluate_object */
527 acpi_ut_remove_reference(obj_desc);
528 return_ACPI_STATUS(status);
531 /*******************************************************************************
533 * FUNCTION: acpi_rs_get_crs_method_data
535 * PARAMETERS: Handle - a handle to the containing object
536 * ret_buffer - a pointer to a buffer structure for the
541 * DESCRIPTION: This function is called to get the _CRS value of an object
542 * contained in an object specified by the handle passed in
544 * If the function fails an appropriate status will be returned
545 * and the contents of the callers buffer is undefined.
547 ******************************************************************************/
550 acpi_rs_get_crs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
552 union acpi_operand_object *obj_desc;
555 ACPI_FUNCTION_TRACE("rs_get_crs_method_data");
557 /* Parameters guaranteed valid by caller */
559 /* Execute the method, no parameters */
561 status = acpi_ut_evaluate_object(handle, METHOD_NAME__CRS,
562 ACPI_BTYPE_BUFFER, &obj_desc);
563 if (ACPI_FAILURE(status)) {
564 return_ACPI_STATUS(status);
568 * Make the call to create a resource linked list from the
569 * byte stream buffer that comes back from the _CRS method
572 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
574 /* on exit, we must delete the object returned by evaluate_object */
576 acpi_ut_remove_reference(obj_desc);
577 return_ACPI_STATUS(status);
580 /*******************************************************************************
582 * FUNCTION: acpi_rs_get_prs_method_data
584 * PARAMETERS: Handle - a handle to the containing object
585 * ret_buffer - a pointer to a buffer structure for the
590 * DESCRIPTION: This function is called to get the _PRS value of an object
591 * contained in an object specified by the handle passed in
593 * If the function fails an appropriate status will be returned
594 * and the contents of the callers buffer is undefined.
596 ******************************************************************************/
598 #ifdef ACPI_FUTURE_USAGE
600 acpi_rs_get_prs_method_data(acpi_handle handle, struct acpi_buffer *ret_buffer)
602 union acpi_operand_object *obj_desc;
605 ACPI_FUNCTION_TRACE("rs_get_prs_method_data");
607 /* Parameters guaranteed valid by caller */
609 /* Execute the method, no parameters */
611 status = acpi_ut_evaluate_object(handle, METHOD_NAME__PRS,
612 ACPI_BTYPE_BUFFER, &obj_desc);
613 if (ACPI_FAILURE(status)) {
614 return_ACPI_STATUS(status);
618 * Make the call to create a resource linked list from the
619 * byte stream buffer that comes back from the _CRS method
622 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
624 /* on exit, we must delete the object returned by evaluate_object */
626 acpi_ut_remove_reference(obj_desc);
627 return_ACPI_STATUS(status);
629 #endif /* ACPI_FUTURE_USAGE */
631 /*******************************************************************************
633 * FUNCTION: acpi_rs_get_method_data
635 * PARAMETERS: Handle - a handle to the containing object
636 * Path - Path to method, relative to Handle
637 * ret_buffer - a pointer to a buffer structure for the
642 * DESCRIPTION: This function is called to get the _CRS or _PRS value of an
643 * object contained in an object specified by the handle passed in
645 * If the function fails an appropriate status will be returned
646 * and the contents of the callers buffer is undefined.
648 ******************************************************************************/
651 acpi_rs_get_method_data(acpi_handle handle,
652 char *path, struct acpi_buffer *ret_buffer)
654 union acpi_operand_object *obj_desc;
657 ACPI_FUNCTION_TRACE("rs_get_method_data");
659 /* Parameters guaranteed valid by caller */
661 /* Execute the method, no parameters */
664 acpi_ut_evaluate_object(handle, path, ACPI_BTYPE_BUFFER, &obj_desc);
665 if (ACPI_FAILURE(status)) {
666 return_ACPI_STATUS(status);
670 * Make the call to create a resource linked list from the
671 * byte stream buffer that comes back from the method
674 status = acpi_rs_create_resource_list(obj_desc, ret_buffer);
676 /* On exit, we must delete the object returned by evaluate_object */
678 acpi_ut_remove_reference(obj_desc);
679 return_ACPI_STATUS(status);
682 /*******************************************************************************
684 * FUNCTION: acpi_rs_set_srs_method_data
686 * PARAMETERS: Handle - a handle to the containing object
687 * in_buffer - a pointer to a buffer structure of the
692 * DESCRIPTION: This function is called to set the _SRS of an object contained
693 * in an object specified by the handle passed in
695 * If the function fails an appropriate status will be returned
696 * and the contents of the callers buffer is undefined.
698 ******************************************************************************/
701 acpi_rs_set_srs_method_data(acpi_handle handle, struct acpi_buffer *in_buffer)
703 struct acpi_parameter_info info;
704 union acpi_operand_object *params[2];
706 struct acpi_buffer buffer;
708 ACPI_FUNCTION_TRACE("rs_set_srs_method_data");
710 /* Parameters guaranteed valid by caller */
713 * The in_buffer parameter will point to a linked list of
714 * resource parameters. It needs to be formatted into a
715 * byte stream to be sent in as an input parameter to _SRS
717 * Convert the linked list into a byte stream
719 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
720 status = acpi_rs_create_aml_resources(in_buffer->pointer, &buffer);
721 if (ACPI_FAILURE(status)) {
722 return_ACPI_STATUS(status);
725 /* Init the param object */
727 params[0] = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
729 acpi_os_free(buffer.pointer);
730 return_ACPI_STATUS(AE_NO_MEMORY);
733 /* Set up the parameter object */
735 params[0]->buffer.length = (u32) buffer.length;
736 params[0]->buffer.pointer = buffer.pointer;
737 params[0]->common.flags = AOPOBJ_DATA_VALID;
741 info.parameters = params;
742 info.parameter_type = ACPI_PARAM_ARGS;
744 /* Execute the method, no return value */
746 status = acpi_ns_evaluate_relative(METHOD_NAME__SRS, &info);
747 if (ACPI_SUCCESS(status)) {
748 /* Delete any return object (especially if implicit_return is enabled) */
750 if (info.return_object) {
751 acpi_ut_remove_reference(info.return_object);
755 /* Clean up and return the status from acpi_ns_evaluate_relative */
757 acpi_ut_remove_reference(params[0]);
758 return_ACPI_STATUS(status);