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 ¤t_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