xref: /linux/drivers/acpi/acpica/rscreate.c (revision cf48958e)
195b482a8SLen Brown /*******************************************************************************
295b482a8SLen Brown  *
395b482a8SLen Brown  * Module Name: rscreate - Create resource lists/tables
495b482a8SLen Brown  *
595b482a8SLen Brown  ******************************************************************************/
695b482a8SLen Brown 
795b482a8SLen Brown /*
877848130SBob Moore  * Copyright (C) 2000 - 2012, Intel Corp.
995b482a8SLen Brown  * All rights reserved.
1095b482a8SLen Brown  *
1195b482a8SLen Brown  * Redistribution and use in source and binary forms, with or without
1295b482a8SLen Brown  * modification, are permitted provided that the following conditions
1395b482a8SLen Brown  * are met:
1495b482a8SLen Brown  * 1. Redistributions of source code must retain the above copyright
1595b482a8SLen Brown  *    notice, this list of conditions, and the following disclaimer,
1695b482a8SLen Brown  *    without modification.
1795b482a8SLen Brown  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1895b482a8SLen Brown  *    substantially similar to the "NO WARRANTY" disclaimer below
1995b482a8SLen Brown  *    ("Disclaimer") and any redistribution must be conditioned upon
2095b482a8SLen Brown  *    including a substantially similar Disclaimer requirement for further
2195b482a8SLen Brown  *    binary redistribution.
2295b482a8SLen Brown  * 3. Neither the names of the above-listed copyright holders nor the names
2395b482a8SLen Brown  *    of any contributors may be used to endorse or promote products derived
2495b482a8SLen Brown  *    from this software without specific prior written permission.
2595b482a8SLen Brown  *
2695b482a8SLen Brown  * Alternatively, this software may be distributed under the terms of the
2795b482a8SLen Brown  * GNU General Public License ("GPL") version 2 as published by the Free
2895b482a8SLen Brown  * Software Foundation.
2995b482a8SLen Brown  *
3095b482a8SLen Brown  * NO WARRANTY
3195b482a8SLen Brown  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3295b482a8SLen Brown  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3395b482a8SLen Brown  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3495b482a8SLen Brown  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3595b482a8SLen Brown  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3695b482a8SLen Brown  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3795b482a8SLen Brown  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3895b482a8SLen Brown  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3995b482a8SLen Brown  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4095b482a8SLen Brown  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4195b482a8SLen Brown  * POSSIBILITY OF SUCH DAMAGES.
4295b482a8SLen Brown  */
4395b482a8SLen Brown 
4495b482a8SLen Brown #include <acpi/acpi.h>
45e2f7a777SLen Brown #include "accommon.h"
46e2f7a777SLen Brown #include "acresrc.h"
47e2f7a777SLen Brown #include "acnamesp.h"
4895b482a8SLen Brown 
4995b482a8SLen Brown #define _COMPONENT          ACPI_RESOURCES
5095b482a8SLen Brown ACPI_MODULE_NAME("rscreate")
5195b482a8SLen Brown 
5295b482a8SLen Brown /*******************************************************************************
5395b482a8SLen Brown  *
540e243178SBob Moore  * FUNCTION:    acpi_buffer_to_resource
550e243178SBob Moore  *
560e243178SBob Moore  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
570e243178SBob Moore  *              aml_buffer_length   - Length of the aml_buffer
580e243178SBob Moore  *              resource_ptr        - Where the converted resource is returned
590e243178SBob Moore  *
600e243178SBob Moore  * RETURN:      Status
610e243178SBob Moore  *
620e243178SBob Moore  * DESCRIPTION: Convert a raw AML buffer to a resource list
630e243178SBob Moore  *
640e243178SBob Moore  ******************************************************************************/
650e243178SBob Moore acpi_status
660e243178SBob Moore acpi_buffer_to_resource(u8 *aml_buffer,
670e243178SBob Moore 			u16 aml_buffer_length,
680e243178SBob Moore 			struct acpi_resource **resource_ptr)
690e243178SBob Moore {
700e243178SBob Moore 	acpi_status status;
710e243178SBob Moore 	acpi_size list_size_needed;
720e243178SBob Moore 	void *resource;
730e243178SBob Moore 	void *current_resource_ptr;
740e243178SBob Moore 
750e243178SBob Moore 	/*
760e243178SBob Moore 	 * Note: we allow AE_AML_NO_RESOURCE_END_TAG, since an end tag
770e243178SBob Moore 	 * is not required here.
780e243178SBob Moore 	 */
790e243178SBob Moore 
800e243178SBob Moore 	/* Get the required length for the converted resource */
810e243178SBob Moore 
820e243178SBob Moore 	status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
830e243178SBob Moore 					 &list_size_needed);
840e243178SBob Moore 	if (status == AE_AML_NO_RESOURCE_END_TAG) {
850e243178SBob Moore 		status = AE_OK;
860e243178SBob Moore 	}
870e243178SBob Moore 	if (ACPI_FAILURE(status)) {
880e243178SBob Moore 		return (status);
890e243178SBob Moore 	}
900e243178SBob Moore 
910e243178SBob Moore 	/* Allocate a buffer for the converted resource */
920e243178SBob Moore 
930e243178SBob Moore 	resource = ACPI_ALLOCATE_ZEROED(list_size_needed);
940e243178SBob Moore 	current_resource_ptr = resource;
950e243178SBob Moore 	if (!resource) {
960e243178SBob Moore 		return (AE_NO_MEMORY);
970e243178SBob Moore 	}
980e243178SBob Moore 
990e243178SBob Moore 	/* Perform the AML-to-Resource conversion */
1000e243178SBob Moore 
1010e243178SBob Moore 	status = acpi_ut_walk_aml_resources(aml_buffer, aml_buffer_length,
1020e243178SBob Moore 					    acpi_rs_convert_aml_to_resources,
1030e243178SBob Moore 					    &current_resource_ptr);
1040e243178SBob Moore 	if (status == AE_AML_NO_RESOURCE_END_TAG) {
1050e243178SBob Moore 		status = AE_OK;
1060e243178SBob Moore 	}
1070e243178SBob Moore 	if (ACPI_FAILURE(status)) {
1080e243178SBob Moore 		ACPI_FREE(resource);
1090e243178SBob Moore 	} else {
1100e243178SBob Moore 		*resource_ptr = resource;
1110e243178SBob Moore 	}
1120e243178SBob Moore 
1130e243178SBob Moore 	return (status);
1140e243178SBob Moore }
1150e243178SBob Moore 
1160e243178SBob Moore /*******************************************************************************
1170e243178SBob Moore  *
11895b482a8SLen Brown  * FUNCTION:    acpi_rs_create_resource_list
11995b482a8SLen Brown  *
12095b482a8SLen Brown  * PARAMETERS:  aml_buffer          - Pointer to the resource byte stream
12195b482a8SLen Brown  *              output_buffer       - Pointer to the user's buffer
12295b482a8SLen Brown  *
12395b482a8SLen Brown  * RETURN:      Status: AE_OK if okay, else a valid acpi_status code
12495b482a8SLen Brown  *              If output_buffer is not large enough, output_buffer_length
12595b482a8SLen Brown  *              indicates how large output_buffer should be, else it
12695b482a8SLen Brown  *              indicates how may u8 elements of output_buffer are valid.
12795b482a8SLen Brown  *
12895b482a8SLen Brown  * DESCRIPTION: Takes the byte stream returned from a _CRS, _PRS control method
12995b482a8SLen Brown  *              execution and parses the stream to create a linked list
13095b482a8SLen Brown  *              of device resources.
13195b482a8SLen Brown  *
13295b482a8SLen Brown  ******************************************************************************/
133e0fe0a8dSLin Ming 
13495b482a8SLen Brown acpi_status
13595b482a8SLen Brown acpi_rs_create_resource_list(union acpi_operand_object *aml_buffer,
13695b482a8SLen Brown 			     struct acpi_buffer * output_buffer)
13795b482a8SLen Brown {
13895b482a8SLen Brown 
13995b482a8SLen Brown 	acpi_status status;
14095b482a8SLen Brown 	u8 *aml_start;
14195b482a8SLen Brown 	acpi_size list_size_needed = 0;
14295b482a8SLen Brown 	u32 aml_buffer_length;
14395b482a8SLen Brown 	void *resource;
14495b482a8SLen Brown 
14595b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_create_resource_list);
14695b482a8SLen Brown 
14795b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlBuffer = %p\n", aml_buffer));
14895b482a8SLen Brown 
14995b482a8SLen Brown 	/* Params already validated, so we don't re-validate here */
15095b482a8SLen Brown 
15195b482a8SLen Brown 	aml_buffer_length = aml_buffer->buffer.length;
15295b482a8SLen Brown 	aml_start = aml_buffer->buffer.pointer;
15395b482a8SLen Brown 
15495b482a8SLen Brown 	/*
15595b482a8SLen Brown 	 * Pass the aml_buffer into a module that can calculate
15695b482a8SLen Brown 	 * the buffer size needed for the linked list
15795b482a8SLen Brown 	 */
15895b482a8SLen Brown 	status = acpi_rs_get_list_length(aml_start, aml_buffer_length,
15995b482a8SLen Brown 					 &list_size_needed);
16095b482a8SLen Brown 
16195b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Status=%X ListSizeNeeded=%X\n",
16295b482a8SLen Brown 			  status, (u32) list_size_needed));
16395b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
16495b482a8SLen Brown 		return_ACPI_STATUS(status);
16595b482a8SLen Brown 	}
16695b482a8SLen Brown 
16795b482a8SLen Brown 	/* Validate/Allocate/Clear caller buffer */
16895b482a8SLen Brown 
16995b482a8SLen Brown 	status = acpi_ut_initialize_buffer(output_buffer, list_size_needed);
17095b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
17195b482a8SLen Brown 		return_ACPI_STATUS(status);
17295b482a8SLen Brown 	}
17395b482a8SLen Brown 
17495b482a8SLen Brown 	/* Do the conversion */
17595b482a8SLen Brown 
17695b482a8SLen Brown 	resource = output_buffer->pointer;
17795b482a8SLen Brown 	status = acpi_ut_walk_aml_resources(aml_start, aml_buffer_length,
17895b482a8SLen Brown 					    acpi_rs_convert_aml_to_resources,
17995b482a8SLen Brown 					    &resource);
18095b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
18195b482a8SLen Brown 		return_ACPI_STATUS(status);
18295b482a8SLen Brown 	}
18395b482a8SLen Brown 
18495b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
18595b482a8SLen Brown 			  output_buffer->pointer, (u32) output_buffer->length));
18695b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
18795b482a8SLen Brown }
18895b482a8SLen Brown 
18995b482a8SLen Brown /*******************************************************************************
19095b482a8SLen Brown  *
19195b482a8SLen Brown  * FUNCTION:    acpi_rs_create_pci_routing_table
19295b482a8SLen Brown  *
193*cf48958eSBob Moore  * PARAMETERS:  package_object          - Pointer to a package containing one
194*cf48958eSBob Moore  *                                        of more ACPI_OPERAND_OBJECTs
19595b482a8SLen Brown  *              output_buffer           - Pointer to the user's buffer
19695b482a8SLen Brown  *
19795b482a8SLen Brown  * RETURN:      Status  AE_OK if okay, else a valid acpi_status code.
19895b482a8SLen Brown  *              If the output_buffer is too small, the error will be
19995b482a8SLen Brown  *              AE_BUFFER_OVERFLOW and output_buffer->Length will point
20095b482a8SLen Brown  *              to the size buffer needed.
20195b482a8SLen Brown  *
20295b482a8SLen Brown  * DESCRIPTION: Takes the union acpi_operand_object package and creates a
20395b482a8SLen Brown  *              linked list of PCI interrupt descriptions
20495b482a8SLen Brown  *
20595b482a8SLen Brown  * NOTE: It is the caller's responsibility to ensure that the start of the
20695b482a8SLen Brown  * output buffer is aligned properly (if necessary).
20795b482a8SLen Brown  *
20895b482a8SLen Brown  ******************************************************************************/
20995b482a8SLen Brown 
21095b482a8SLen Brown acpi_status
21195b482a8SLen Brown acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
21295b482a8SLen Brown 				 struct acpi_buffer *output_buffer)
21395b482a8SLen Brown {
21495b482a8SLen Brown 	u8 *buffer;
21595b482a8SLen Brown 	union acpi_operand_object **top_object_list;
21695b482a8SLen Brown 	union acpi_operand_object **sub_object_list;
21795b482a8SLen Brown 	union acpi_operand_object *obj_desc;
21895b482a8SLen Brown 	acpi_size buffer_size_needed = 0;
21995b482a8SLen Brown 	u32 number_of_elements;
22095b482a8SLen Brown 	u32 index;
22195b482a8SLen Brown 	struct acpi_pci_routing_table *user_prt;
22295b482a8SLen Brown 	struct acpi_namespace_node *node;
22395b482a8SLen Brown 	acpi_status status;
22495b482a8SLen Brown 	struct acpi_buffer path_buffer;
22595b482a8SLen Brown 
22695b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);
22795b482a8SLen Brown 
22895b482a8SLen Brown 	/* Params already validated, so we don't re-validate here */
22995b482a8SLen Brown 
23095b482a8SLen Brown 	/* Get the required buffer length */
23195b482a8SLen Brown 
23295b482a8SLen Brown 	status = acpi_rs_get_pci_routing_table_length(package_object,
23395b482a8SLen Brown 						      &buffer_size_needed);
23495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
23595b482a8SLen Brown 		return_ACPI_STATUS(status);
23695b482a8SLen Brown 	}
23795b482a8SLen Brown 
23895b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
23995b482a8SLen Brown 			  (u32) buffer_size_needed));
24095b482a8SLen Brown 
24195b482a8SLen Brown 	/* Validate/Allocate/Clear caller buffer */
24295b482a8SLen Brown 
24395b482a8SLen Brown 	status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
24495b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
24595b482a8SLen Brown 		return_ACPI_STATUS(status);
24695b482a8SLen Brown 	}
24795b482a8SLen Brown 
24895b482a8SLen Brown 	/*
24995b482a8SLen Brown 	 * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
2505df7e6cbSBob Moore 	 * package that in turn contains an u64 Address, a u8 Pin,
25195b482a8SLen Brown 	 * a Name, and a u8 source_index.
25295b482a8SLen Brown 	 */
25395b482a8SLen Brown 	top_object_list = package_object->package.elements;
25495b482a8SLen Brown 	number_of_elements = package_object->package.count;
25595b482a8SLen Brown 	buffer = output_buffer->pointer;
25695b482a8SLen Brown 	user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
25795b482a8SLen Brown 
25895b482a8SLen Brown 	for (index = 0; index < number_of_elements; index++) {
25995b482a8SLen Brown 
26095b482a8SLen Brown 		/*
26195b482a8SLen Brown 		 * Point user_prt past this current structure
26295b482a8SLen Brown 		 *
26395b482a8SLen Brown 		 * NOTE: On the first iteration, user_prt->Length will
26495b482a8SLen Brown 		 * be zero because we cleared the return buffer earlier
26595b482a8SLen Brown 		 */
26695b482a8SLen Brown 		buffer += user_prt->length;
26795b482a8SLen Brown 		user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
26895b482a8SLen Brown 
26995b482a8SLen Brown 		/*
27095b482a8SLen Brown 		 * Fill in the Length field with the information we have at this point.
27195b482a8SLen Brown 		 * The minus four is to subtract the size of the u8 Source[4] member
27295b482a8SLen Brown 		 * because it is added below.
27395b482a8SLen Brown 		 */
27495b482a8SLen Brown 		user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
27595b482a8SLen Brown 
27695b482a8SLen Brown 		/* Each element of the top-level package must also be a package */
27795b482a8SLen Brown 
2783371c19cSBob Moore 		if ((*top_object_list)->common.type != ACPI_TYPE_PACKAGE) {
27995b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
280f6a22b0bSBob Moore 				    "(PRT[%u]) Need sub-package, found %s",
28195b482a8SLen Brown 				    index,
28295b482a8SLen Brown 				    acpi_ut_get_object_type_name
28395b482a8SLen Brown 				    (*top_object_list)));
28495b482a8SLen Brown 			return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
28595b482a8SLen Brown 		}
28695b482a8SLen Brown 
28795b482a8SLen Brown 		/* Each sub-package must be of length 4 */
28895b482a8SLen Brown 
28995b482a8SLen Brown 		if ((*top_object_list)->package.count != 4) {
29095b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
291f6a22b0bSBob Moore 				    "(PRT[%u]) Need package of length 4, found length %u",
29295b482a8SLen Brown 				    index, (*top_object_list)->package.count));
29395b482a8SLen Brown 			return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
29495b482a8SLen Brown 		}
29595b482a8SLen Brown 
29695b482a8SLen Brown 		/*
29795b482a8SLen Brown 		 * Dereference the sub-package.
29895b482a8SLen Brown 		 * The sub_object_list will now point to an array of the four IRQ
29995b482a8SLen Brown 		 * elements: [Address, Pin, Source, source_index]
30095b482a8SLen Brown 		 */
30195b482a8SLen Brown 		sub_object_list = (*top_object_list)->package.elements;
30295b482a8SLen Brown 
30395b482a8SLen Brown 		/* 1) First subobject: Dereference the PRT.Address */
30495b482a8SLen Brown 
30595b482a8SLen Brown 		obj_desc = sub_object_list[0];
3063371c19cSBob Moore 		if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
30795b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
308f6a22b0bSBob Moore 				    "(PRT[%u].Address) Need Integer, found %s",
30995b482a8SLen Brown 				    index,
31095b482a8SLen Brown 				    acpi_ut_get_object_type_name(obj_desc)));
31195b482a8SLen Brown 			return_ACPI_STATUS(AE_BAD_DATA);
31295b482a8SLen Brown 		}
31395b482a8SLen Brown 
31495b482a8SLen Brown 		user_prt->address = obj_desc->integer.value;
31595b482a8SLen Brown 
31695b482a8SLen Brown 		/* 2) Second subobject: Dereference the PRT.Pin */
31795b482a8SLen Brown 
31895b482a8SLen Brown 		obj_desc = sub_object_list[1];
3193371c19cSBob Moore 		if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
32095b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
321f6a22b0bSBob Moore 				    "(PRT[%u].Pin) Need Integer, found %s",
32295b482a8SLen Brown 				    index,
32395b482a8SLen Brown 				    acpi_ut_get_object_type_name(obj_desc)));
32495b482a8SLen Brown 			return_ACPI_STATUS(AE_BAD_DATA);
32595b482a8SLen Brown 		}
32695b482a8SLen Brown 
32795b482a8SLen Brown 		user_prt->pin = (u32) obj_desc->integer.value;
32895b482a8SLen Brown 
32995b482a8SLen Brown 		/*
33095b482a8SLen Brown 		 * If the BIOS has erroneously reversed the _PRT source_name (index 2)
33195b482a8SLen Brown 		 * and the source_index (index 3), fix it. _PRT is important enough to
33295b482a8SLen Brown 		 * workaround this BIOS error. This also provides compatibility with
33395b482a8SLen Brown 		 * other ACPI implementations.
33495b482a8SLen Brown 		 */
33595b482a8SLen Brown 		obj_desc = sub_object_list[3];
3363371c19cSBob Moore 		if (!obj_desc || (obj_desc->common.type != ACPI_TYPE_INTEGER)) {
33795b482a8SLen Brown 			sub_object_list[3] = sub_object_list[2];
33895b482a8SLen Brown 			sub_object_list[2] = obj_desc;
33995b482a8SLen Brown 
34095b482a8SLen Brown 			ACPI_WARNING((AE_INFO,
34195b482a8SLen Brown 				      "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed",
34295b482a8SLen Brown 				      index));
34395b482a8SLen Brown 		}
34495b482a8SLen Brown 
34595b482a8SLen Brown 		/*
34695b482a8SLen Brown 		 * 3) Third subobject: Dereference the PRT.source_name
34795b482a8SLen Brown 		 * The name may be unresolved (slack mode), so allow a null object
34895b482a8SLen Brown 		 */
34982babbb3SZhang Rui 		obj_desc = sub_object_list[2];
35095b482a8SLen Brown 		if (obj_desc) {
3513371c19cSBob Moore 			switch (obj_desc->common.type) {
35295b482a8SLen Brown 			case ACPI_TYPE_LOCAL_REFERENCE:
35395b482a8SLen Brown 
35495b482a8SLen Brown 				if (obj_desc->reference.class !=
35595b482a8SLen Brown 				    ACPI_REFCLASS_NAME) {
35695b482a8SLen Brown 					ACPI_ERROR((AE_INFO,
357f6a22b0bSBob Moore 						    "(PRT[%u].Source) Need name, found Reference Class 0x%X",
35895b482a8SLen Brown 						    index,
35995b482a8SLen Brown 						    obj_desc->reference.class));
36095b482a8SLen Brown 					return_ACPI_STATUS(AE_BAD_DATA);
36195b482a8SLen Brown 				}
36295b482a8SLen Brown 
36395b482a8SLen Brown 				node = obj_desc->reference.node;
36495b482a8SLen Brown 
36595b482a8SLen Brown 				/* Use *remaining* length of the buffer as max for pathname */
36695b482a8SLen Brown 
36795b482a8SLen Brown 				path_buffer.length = output_buffer->length -
36895b482a8SLen Brown 				    (u32) ((u8 *) user_prt->source -
36995b482a8SLen Brown 					   (u8 *) output_buffer->pointer);
37095b482a8SLen Brown 				path_buffer.pointer = user_prt->source;
37195b482a8SLen Brown 
37295b482a8SLen Brown 				status =
37395b482a8SLen Brown 				    acpi_ns_handle_to_pathname((acpi_handle)
37495b482a8SLen Brown 							       node,
37595b482a8SLen Brown 							       &path_buffer);
37695b482a8SLen Brown 
37795b482a8SLen Brown 				/* +1 to include null terminator */
37895b482a8SLen Brown 
37995b482a8SLen Brown 				user_prt->length +=
38095b482a8SLen Brown 				    (u32) ACPI_STRLEN(user_prt->source) + 1;
38195b482a8SLen Brown 				break;
38295b482a8SLen Brown 
38395b482a8SLen Brown 			case ACPI_TYPE_STRING:
38495b482a8SLen Brown 
38595b482a8SLen Brown 				ACPI_STRCPY(user_prt->source,
38695b482a8SLen Brown 					    obj_desc->string.pointer);
38795b482a8SLen Brown 
38895b482a8SLen Brown 				/*
38995b482a8SLen Brown 				 * Add to the Length field the length of the string
39095b482a8SLen Brown 				 * (add 1 for terminator)
39195b482a8SLen Brown 				 */
39295b482a8SLen Brown 				user_prt->length += obj_desc->string.length + 1;
39395b482a8SLen Brown 				break;
39495b482a8SLen Brown 
39595b482a8SLen Brown 			case ACPI_TYPE_INTEGER:
39695b482a8SLen Brown 				/*
39795b482a8SLen Brown 				 * If this is a number, then the Source Name is NULL, since the
39895b482a8SLen Brown 				 * entire buffer was zeroed out, we can leave this alone.
39995b482a8SLen Brown 				 *
40095b482a8SLen Brown 				 * Add to the Length field the length of the u32 NULL
40195b482a8SLen Brown 				 */
40295b482a8SLen Brown 				user_prt->length += sizeof(u32);
40395b482a8SLen Brown 				break;
40495b482a8SLen Brown 
40595b482a8SLen Brown 			default:
40695b482a8SLen Brown 
40795b482a8SLen Brown 				ACPI_ERROR((AE_INFO,
408f6a22b0bSBob Moore 					    "(PRT[%u].Source) Need Ref/String/Integer, found %s",
40995b482a8SLen Brown 					    index,
41095b482a8SLen Brown 					    acpi_ut_get_object_type_name
41195b482a8SLen Brown 					    (obj_desc)));
41295b482a8SLen Brown 				return_ACPI_STATUS(AE_BAD_DATA);
41395b482a8SLen Brown 			}
41495b482a8SLen Brown 		}
41595b482a8SLen Brown 
41695b482a8SLen Brown 		/* Now align the current length */
41795b482a8SLen Brown 
41895b482a8SLen Brown 		user_prt->length =
41995b482a8SLen Brown 		    (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);
42095b482a8SLen Brown 
42195b482a8SLen Brown 		/* 4) Fourth subobject: Dereference the PRT.source_index */
42295b482a8SLen Brown 
42382babbb3SZhang Rui 		obj_desc = sub_object_list[3];
4243371c19cSBob Moore 		if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
42595b482a8SLen Brown 			ACPI_ERROR((AE_INFO,
426f6a22b0bSBob Moore 				    "(PRT[%u].SourceIndex) Need Integer, found %s",
42795b482a8SLen Brown 				    index,
42895b482a8SLen Brown 				    acpi_ut_get_object_type_name(obj_desc)));
42995b482a8SLen Brown 			return_ACPI_STATUS(AE_BAD_DATA);
43095b482a8SLen Brown 		}
43195b482a8SLen Brown 
43295b482a8SLen Brown 		user_prt->source_index = (u32) obj_desc->integer.value;
43395b482a8SLen Brown 
43495b482a8SLen Brown 		/* Point to the next union acpi_operand_object in the top level package */
43595b482a8SLen Brown 
43695b482a8SLen Brown 		top_object_list++;
43795b482a8SLen Brown 	}
43895b482a8SLen Brown 
43995b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
44095b482a8SLen Brown 			  output_buffer->pointer, (u32) output_buffer->length));
44195b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
44295b482a8SLen Brown }
44395b482a8SLen Brown 
44495b482a8SLen Brown /*******************************************************************************
44595b482a8SLen Brown  *
44695b482a8SLen Brown  * FUNCTION:    acpi_rs_create_aml_resources
44795b482a8SLen Brown  *
44895b482a8SLen Brown  * PARAMETERS:  linked_list_buffer      - Pointer to the resource linked list
44995b482a8SLen Brown  *              output_buffer           - Pointer to the user's buffer
45095b482a8SLen Brown  *
45195b482a8SLen Brown  * RETURN:      Status  AE_OK if okay, else a valid acpi_status code.
45295b482a8SLen Brown  *              If the output_buffer is too small, the error will be
45395b482a8SLen Brown  *              AE_BUFFER_OVERFLOW and output_buffer->Length will point
45495b482a8SLen Brown  *              to the size buffer needed.
45595b482a8SLen Brown  *
45695b482a8SLen Brown  * DESCRIPTION: Takes the linked list of device resources and
45795b482a8SLen Brown  *              creates a bytestream to be used as input for the
45895b482a8SLen Brown  *              _SRS control method.
45995b482a8SLen Brown  *
46095b482a8SLen Brown  ******************************************************************************/
46195b482a8SLen Brown 
46295b482a8SLen Brown acpi_status
46395b482a8SLen Brown acpi_rs_create_aml_resources(struct acpi_resource *linked_list_buffer,
46495b482a8SLen Brown 			     struct acpi_buffer *output_buffer)
46595b482a8SLen Brown {
46695b482a8SLen Brown 	acpi_status status;
46795b482a8SLen Brown 	acpi_size aml_size_needed = 0;
46895b482a8SLen Brown 
46995b482a8SLen Brown 	ACPI_FUNCTION_TRACE(rs_create_aml_resources);
47095b482a8SLen Brown 
47195b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "LinkedListBuffer = %p\n",
47295b482a8SLen Brown 			  linked_list_buffer));
47395b482a8SLen Brown 
47495b482a8SLen Brown 	/*
47595b482a8SLen Brown 	 * Params already validated, so we don't re-validate here
47695b482a8SLen Brown 	 *
47795b482a8SLen Brown 	 * Pass the linked_list_buffer into a module that calculates
47895b482a8SLen Brown 	 * the buffer size needed for the byte stream.
47995b482a8SLen Brown 	 */
48095b482a8SLen Brown 	status = acpi_rs_get_aml_length(linked_list_buffer, &aml_size_needed);
48195b482a8SLen Brown 
48295b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
48395b482a8SLen Brown 			  (u32) aml_size_needed,
48495b482a8SLen Brown 			  acpi_format_exception(status)));
48595b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
48695b482a8SLen Brown 		return_ACPI_STATUS(status);
48795b482a8SLen Brown 	}
48895b482a8SLen Brown 
48995b482a8SLen Brown 	/* Validate/Allocate/Clear caller buffer */
49095b482a8SLen Brown 
49195b482a8SLen Brown 	status = acpi_ut_initialize_buffer(output_buffer, aml_size_needed);
49295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
49395b482a8SLen Brown 		return_ACPI_STATUS(status);
49495b482a8SLen Brown 	}
49595b482a8SLen Brown 
49695b482a8SLen Brown 	/* Do the conversion */
49795b482a8SLen Brown 
49895b482a8SLen Brown 	status =
49995b482a8SLen Brown 	    acpi_rs_convert_resources_to_aml(linked_list_buffer,
50095b482a8SLen Brown 					     aml_size_needed,
50195b482a8SLen Brown 					     output_buffer->pointer);
50295b482a8SLen Brown 	if (ACPI_FAILURE(status)) {
50395b482a8SLen Brown 		return_ACPI_STATUS(status);
50495b482a8SLen Brown 	}
50595b482a8SLen Brown 
50695b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
50795b482a8SLen Brown 			  output_buffer->pointer, (u32) output_buffer->length));
50895b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
50995b482a8SLen Brown }
510