1 /******************************************************************************
2  *
3  * Module Name: tbxface - Public interfaces to the ACPI subsystem
4  *                         ACPI table oriented interfaces
5  *
6  *****************************************************************************/
7 
8 /*
9  * Copyright (C) 2000 - 2008, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44 
45 #include <xen/init.h>
46 #include <acpi/acpi.h>
47 #include <acpi/actables.h>
48 
49 #define _COMPONENT          ACPI_TABLES
50 ACPI_MODULE_NAME("tbxface")
51 
52 /*******************************************************************************
53  *
54  * FUNCTION:    acpi_allocate_root_table
55  *
56  * PARAMETERS:  initial_table_count - Size of initial_table_array, in number of
57  *                                    struct acpi_table_desc structures
58  *
59  * RETURN:      Status
60  *
61  * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and
62  *              acpi_initialize_tables.
63  *
64  ******************************************************************************/
65 
acpi_allocate_root_table(u32 initial_table_count)66 acpi_status __init acpi_allocate_root_table(u32 initial_table_count)
67 {
68 
69 	acpi_gbl_root_table_list.size = initial_table_count -
70 					ACPI_ROOT_TABLE_SIZE_INCREMENT;
71 	acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
72 
73 	return (acpi_tb_resize_root_table_list());
74 }
75 
76 /*******************************************************************************
77  *
78  * FUNCTION:    acpi_initialize_tables
79  *
80  * PARAMETERS:  initial_table_array - Pointer to an array of pre-allocated
81  *                                    struct acpi_table_desc structures. If NULL, the
82  *                                    array is dynamically allocated.
83  *              initial_table_count - Size of initial_table_array, in number of
84  *                                    struct acpi_table_desc structures
85  *              allow_realloc       - Flag to tell Table Manager if resize of
86  *                                    pre-allocated array is allowed. Ignored
87  *                                    if initial_table_array is NULL.
88  *
89  * RETURN:      Status
90  *
91  * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
92  *
93  * NOTE:        Allows static allocation of the initial table array in order
94  *              to avoid the use of dynamic memory in confined environments
95  *              such as the kernel boot sequence where it may not be available.
96  *
97  *              If the host OS memory managers are initialized, use NULL for
98  *              initial_table_array, and the table will be dynamically allocated.
99  *
100  ******************************************************************************/
101 
102 acpi_status __init
acpi_initialize_tables(struct acpi_table_desc * initial_table_array,u32 initial_table_count,u8 allow_resize)103 acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
104 		       u32 initial_table_count, u8 allow_resize)
105 {
106 	acpi_physical_address rsdp_address;
107 	acpi_status status;
108 
109 	ACPI_FUNCTION_TRACE(acpi_initialize_tables);
110 
111 	/*
112 	 * Set up the Root Table Array
113 	 * Allocate the table array if requested
114 	 */
115 	if (!initial_table_array) {
116 		status = acpi_allocate_root_table(initial_table_count);
117 		if (ACPI_FAILURE(status)) {
118 			return_ACPI_STATUS(status);
119 		}
120 	} else {
121 		/* Root Table Array has been statically allocated by the host */
122 
123 		ACPI_MEMSET(initial_table_array, 0,
124 			    initial_table_count *
125 			    sizeof(struct acpi_table_desc));
126 
127 		acpi_gbl_root_table_list.tables = initial_table_array;
128 		acpi_gbl_root_table_list.size = initial_table_count;
129 		acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
130 		if (allow_resize) {
131 			acpi_gbl_root_table_list.flags |=
132 			    ACPI_ROOT_ALLOW_RESIZE;
133 		}
134 	}
135 
136 	/* Get the address of the RSDP */
137 
138 	rsdp_address = acpi_os_get_root_pointer();
139 	if (!rsdp_address) {
140 		return_ACPI_STATUS(AE_NOT_FOUND);
141 	}
142 
143 	/*
144 	 * Get the root table (RSDT or XSDT) and extract all entries to the local
145 	 * Root Table Array. This array contains the information of the RSDT/XSDT
146 	 * in a common, more useable format.
147 	 */
148 	status =
149 	    acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
150 	return_ACPI_STATUS(status);
151 }
152 
153 /*******************************************************************************
154  *
155  * FUNCTION:    acpi_get_table
156  *
157  * PARAMETERS:  Signature           - ACPI signature of needed table
158  *              Instance            - Which instance (for SSDTs)
159  *              out_table           - Where the pointer to the table is returned
160  *
161  * RETURN:      Status and pointer to table
162  *
163  * DESCRIPTION: Finds and verifies an ACPI table.
164  *
165  *****************************************************************************/
166 acpi_status __init
acpi_get_table(char * signature,acpi_native_uint instance,struct acpi_table_header ** out_table)167 acpi_get_table(char *signature,
168 	       acpi_native_uint instance, struct acpi_table_header **out_table)
169 {
170 	acpi_native_uint i;
171 	acpi_native_uint j;
172 	acpi_status status;
173 
174 	/* Parameter validation */
175 
176 	if (!signature || !out_table) {
177 		return (AE_BAD_PARAMETER);
178 	}
179 
180 	/*
181 	 * Walk the root table list
182 	 */
183 	for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
184 		if (!ACPI_COMPARE_NAME
185 		    (&(acpi_gbl_root_table_list.tables[i].signature),
186 		     signature)) {
187 			continue;
188 		}
189 
190 		if (++j < instance) {
191 			continue;
192 		}
193 
194 		status =
195 		    acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
196 		if (ACPI_SUCCESS(status)) {
197 			*out_table = acpi_gbl_root_table_list.tables[i].pointer;
198 		}
199 
200 		acpi_gbl_root_table_list.tables[i].pointer = NULL;
201 
202 		return (status);
203 	}
204 
205 	return (AE_NOT_FOUND);
206 }
207 
208 /******************************************************************************
209  *
210  * FUNCTION:    acpi_get_table_phys
211  *
212  * PARAMETERS:  signature      - ACPI signature of needed table
213  *              instance       - Which instance (for SSDTs)
214  *              addr           - Where the table's physical address is returned
215  *              len            - Where the length of table is returned
216  *
217  * RETURN:      Status, pointer and length of table
218  *
219  * DESCRIPTION: Finds physical address and length of ACPI table
220  *
221  *****************************************************************************/
222 acpi_status __init
acpi_get_table_phys(acpi_string signature,acpi_native_uint instance,acpi_physical_address * addr,acpi_native_uint * len)223 acpi_get_table_phys(acpi_string signature, acpi_native_uint instance,
224 		     acpi_physical_address *addr, acpi_native_uint *len)
225 {
226 	acpi_native_uint i, j;
227 	acpi_status status;
228 
229 	if (!signature || !addr || !len)
230 		return AE_BAD_PARAMETER;
231 
232 	for (i = j = 0; i < acpi_gbl_root_table_list.count; i++) {
233 		if (!ACPI_COMPARE_NAME(
234 				&acpi_gbl_root_table_list.tables[i].signature,
235 				signature))
236 			continue;
237 
238 		if (++j < instance)
239 			continue;
240 
241 		status =
242 		    acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
243 		if (ACPI_SUCCESS(status)) {
244 			*addr = acpi_gbl_root_table_list.tables[i].address;
245 			*len = acpi_gbl_root_table_list.tables[i].length;
246 		}
247 
248 		acpi_gbl_root_table_list.tables[i].pointer = NULL;
249 
250 		return status;
251 	}
252 
253 	return AE_NOT_FOUND;
254 }
255