diff options
Diffstat (limited to 'drivers/acpi/tables/tbxface.c')
-rw-r--r-- | drivers/acpi/tables/tbxface.c | 620 |
1 files changed, 351 insertions, 269 deletions
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c index 5ba9303293ad..77439fc36c32 100644 --- a/drivers/acpi/tables/tbxface.c +++ b/drivers/acpi/tables/tbxface.c | |||
@@ -49,80 +49,146 @@ | |||
49 | #define _COMPONENT ACPI_TABLES | 49 | #define _COMPONENT ACPI_TABLES |
50 | ACPI_MODULE_NAME("tbxface") | 50 | ACPI_MODULE_NAME("tbxface") |
51 | 51 | ||
52 | /* Local prototypes */ | ||
53 | static acpi_status acpi_tb_load_namespace(void); | ||
54 | |||
52 | /******************************************************************************* | 55 | /******************************************************************************* |
53 | * | 56 | * |
54 | * FUNCTION: acpi_load_tables | 57 | * FUNCTION: acpi_initialize_tables |
55 | * | 58 | * |
56 | * PARAMETERS: None | 59 | * PARAMETERS: initial_table_array - Pointer to an array of pre-allocated |
60 | * struct acpi_table_desc structures. If NULL, the | ||
61 | * array is dynamically allocated. | ||
62 | * initial_table_count - Size of initial_table_array, in number of | ||
63 | * struct acpi_table_desc structures | ||
64 | * allow_realloc - Flag to tell Table Manager if resize of | ||
65 | * pre-allocated array is allowed. Ignored | ||
66 | * if initial_table_array is NULL. | ||
57 | * | 67 | * |
58 | * RETURN: Status | 68 | * RETURN: Status |
59 | * | 69 | * |
60 | * DESCRIPTION: This function is called to load the ACPI tables from the | 70 | * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT. |
61 | * provided RSDT | 71 | * |
72 | * NOTE: Allows static allocation of the initial table array in order | ||
73 | * to avoid the use of dynamic memory in confined environments | ||
74 | * such as the kernel boot sequence where it may not be available. | ||
75 | * | ||
76 | * If the host OS memory managers are initialized, use NULL for | ||
77 | * initial_table_array, and the table will be dynamically allocated. | ||
62 | * | 78 | * |
63 | ******************************************************************************/ | 79 | ******************************************************************************/ |
64 | acpi_status acpi_load_tables(void) | 80 | |
81 | acpi_status | ||
82 | acpi_initialize_tables(struct acpi_table_desc *initial_table_array, | ||
83 | u32 initial_table_count, u8 allow_resize) | ||
65 | { | 84 | { |
66 | struct acpi_pointer rsdp_address; | 85 | acpi_physical_address address; |
67 | acpi_status status; | 86 | acpi_status status; |
87 | struct acpi_table_rsdp *rsdp; | ||
68 | 88 | ||
69 | ACPI_FUNCTION_TRACE(acpi_load_tables); | 89 | ACPI_FUNCTION_TRACE(acpi_initialize_tables); |
70 | 90 | ||
71 | /* Get the RSDP */ | 91 | /* |
92 | * Set up the Root Table Array | ||
93 | * Allocate the table array if requested | ||
94 | */ | ||
95 | if (!initial_table_array) { | ||
96 | acpi_gbl_root_table_list.size = initial_table_count; | ||
97 | acpi_gbl_root_table_list.flags = ACPI_TABLE_FLAGS_ALLOW_RESIZE; | ||
72 | 98 | ||
73 | status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING, | 99 | status = acpi_tb_resize_root_table_list(); |
74 | &rsdp_address); | 100 | if (ACPI_FAILURE(status)) { |
75 | if (ACPI_FAILURE(status)) { | 101 | return_ACPI_STATUS(status); |
76 | ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP")); | 102 | } |
77 | goto error_exit; | 103 | } else { |
104 | /* Root Table Array has been statically allocated by the host */ | ||
105 | |||
106 | acpi_gbl_root_table_list.tables = initial_table_array; | ||
107 | acpi_gbl_root_table_list.size = initial_table_count; | ||
108 | acpi_gbl_root_table_list.flags = ACPI_TABLE_ORIGIN_UNKNOWN; | ||
109 | if (allow_resize) { | ||
110 | acpi_gbl_root_table_list.flags = | ||
111 | ACPI_TABLE_FLAGS_ALLOW_RESIZE; | ||
112 | } | ||
78 | } | 113 | } |
79 | 114 | ||
80 | /* Map and validate the RSDP */ | 115 | /* Get the RSDP and map it */ |
81 | 116 | ||
82 | acpi_gbl_table_flags = rsdp_address.pointer_type; | 117 | address = acpi_os_get_root_pointer(); |
118 | if (!address) { | ||
119 | return_ACPI_STATUS(AE_NOT_FOUND); | ||
120 | } | ||
83 | 121 | ||
84 | status = acpi_tb_verify_rsdp(&rsdp_address); | 122 | rsdp = acpi_os_map_memory(address, sizeof(struct acpi_table_rsdp)); |
85 | if (ACPI_FAILURE(status)) { | 123 | if (!rsdp) { |
86 | ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation")); | 124 | return_ACPI_STATUS(AE_NO_MEMORY); |
87 | goto error_exit; | ||
88 | } | 125 | } |
89 | 126 | ||
90 | /* Get the RSDT via the RSDP */ | 127 | ACPI_INFO((AE_INFO, "%.8s @ 0x%p", |
128 | rsdp->signature, ACPI_CAST_PTR(void, address))); | ||
91 | 129 | ||
92 | status = acpi_tb_get_table_rsdt(); | 130 | /* |
93 | if (ACPI_FAILURE(status)) { | 131 | * Get the root table (RSDT or XSDT) and extract all entries to the local |
94 | ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT")); | 132 | * Root Table Array. This array contains the information of the RSDT/XSDT |
95 | goto error_exit; | 133 | * in a common, more useable format. |
96 | } | 134 | */ |
135 | status = acpi_tb_parse_root_table(rsdp, ACPI_TABLE_ORIGIN_MAPPED); | ||
136 | acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); | ||
137 | return_ACPI_STATUS(status); | ||
138 | } | ||
97 | 139 | ||
98 | /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */ | 140 | ACPI_EXPORT_SYMBOL(acpi_initialize_tables) |
99 | 141 | ||
100 | status = acpi_tb_get_required_tables(); | 142 | /******************************************************************************* |
101 | if (ACPI_FAILURE(status)) { | 143 | * |
102 | ACPI_EXCEPTION((AE_INFO, status, | 144 | * FUNCTION: acpi_reallocate_root_table |
103 | "Could not get all required tables (DSDT/FADT/FACS)")); | 145 | * |
104 | goto error_exit; | 146 | * PARAMETERS: None |
147 | * | ||
148 | * RETURN: Status | ||
149 | * | ||
150 | * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the | ||
151 | * root list from the previously provided scratch area. Should | ||
152 | * be called once dynamic memory allocation is available in the | ||
153 | * kernel | ||
154 | * | ||
155 | ******************************************************************************/ | ||
156 | acpi_status acpi_reallocate_root_table(void) | ||
157 | { | ||
158 | struct acpi_table_desc *tables; | ||
159 | acpi_size new_size; | ||
160 | |||
161 | ACPI_FUNCTION_TRACE(acpi_reallocate_root_table); | ||
162 | |||
163 | /* | ||
164 | * Only reallocate the root table if the host provided a static buffer | ||
165 | * for the table array in the call to acpi_initialize_tables. | ||
166 | */ | ||
167 | if ((acpi_gbl_root_table_list.flags & ACPI_TABLE_ORIGIN_MASK) != | ||
168 | ACPI_TABLE_ORIGIN_UNKNOWN) { | ||
169 | return_ACPI_STATUS(AE_SUPPORT); | ||
105 | } | 170 | } |
106 | 171 | ||
107 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); | 172 | new_size = |
173 | (acpi_gbl_root_table_list.count + | ||
174 | ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc); | ||
108 | 175 | ||
109 | /* Load the namespace from the tables */ | 176 | /* Create new array and copy the old array */ |
110 | 177 | ||
111 | status = acpi_ns_load_namespace(); | 178 | tables = ACPI_ALLOCATE_ZEROED(new_size); |
112 | if (ACPI_FAILURE(status)) { | 179 | if (!tables) { |
113 | ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace")); | 180 | return_ACPI_STATUS(AE_NO_MEMORY); |
114 | goto error_exit; | ||
115 | } | 181 | } |
116 | 182 | ||
117 | return_ACPI_STATUS(AE_OK); | 183 | ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size); |
118 | 184 | ||
119 | error_exit: | 185 | acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count; |
120 | ACPI_EXCEPTION((AE_INFO, status, "Could not load tables")); | 186 | acpi_gbl_root_table_list.tables = tables; |
121 | return_ACPI_STATUS(status); | 187 | acpi_gbl_root_table_list.flags = |
122 | } | 188 | ACPI_TABLE_ORIGIN_ALLOCATED | ACPI_TABLE_FLAGS_ALLOW_RESIZE; |
123 | |||
124 | ACPI_EXPORT_SYMBOL(acpi_load_tables) | ||
125 | 189 | ||
190 | return_ACPI_STATUS(AE_OK); | ||
191 | } | ||
126 | /******************************************************************************* | 192 | /******************************************************************************* |
127 | * | 193 | * |
128 | * FUNCTION: acpi_load_table | 194 | * FUNCTION: acpi_load_table |
@@ -141,342 +207,358 @@ ACPI_EXPORT_SYMBOL(acpi_load_tables) | |||
141 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) | 207 | acpi_status acpi_load_table(struct acpi_table_header *table_ptr) |
142 | { | 208 | { |
143 | acpi_status status; | 209 | acpi_status status; |
144 | struct acpi_table_desc table_info; | 210 | acpi_native_uint table_index; |
145 | struct acpi_pointer address; | ||
146 | |||
147 | ACPI_FUNCTION_TRACE(acpi_load_table); | ||
148 | |||
149 | if (!table_ptr) { | ||
150 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
151 | } | ||
152 | 211 | ||
153 | /* Copy the table to a local buffer */ | 212 | /* |
154 | 213 | * Install the new table into the local data structures | |
155 | address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING; | 214 | */ |
156 | address.pointer.logical = table_ptr; | 215 | status = acpi_tb_add_table(table_ptr, &table_index); |
157 | |||
158 | status = acpi_tb_get_table_body(&address, table_ptr, &table_info); | ||
159 | if (ACPI_FAILURE(status)) { | ||
160 | return_ACPI_STATUS(status); | ||
161 | } | ||
162 | |||
163 | /* Check signature for a valid table type */ | ||
164 | |||
165 | status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL); | ||
166 | if (ACPI_FAILURE(status)) { | 216 | if (ACPI_FAILURE(status)) { |
167 | return_ACPI_STATUS(status); | 217 | return_ACPI_STATUS(status); |
168 | } | 218 | } |
219 | status = acpi_ns_load_table(table_index, acpi_gbl_root_node); | ||
220 | return_ACPI_STATUS(status); | ||
221 | } | ||
169 | 222 | ||
170 | /* Install the new table into the local data structures */ | 223 | ACPI_EXPORT_SYMBOL(acpi_load_table) |
171 | |||
172 | status = acpi_tb_install_table(&table_info); | ||
173 | if (ACPI_FAILURE(status)) { | ||
174 | if (status == AE_ALREADY_EXISTS) { | ||
175 | 224 | ||
176 | /* Table already exists, no error */ | 225 | /****************************************************************************** |
226 | * | ||
227 | * FUNCTION: acpi_get_table_header | ||
228 | * | ||
229 | * PARAMETERS: Signature - ACPI signature of needed table | ||
230 | * Instance - Which instance (for SSDTs) | ||
231 | * out_table_header - Where the pointer to the table header | ||
232 | * is returned | ||
233 | * | ||
234 | * RETURN: Status and pointer to mapped table header | ||
235 | * | ||
236 | * DESCRIPTION: Finds an ACPI table header. | ||
237 | * | ||
238 | * NOTE: Caller is responsible in unmapping the header with | ||
239 | * acpi_os_unmap_memory | ||
240 | * | ||
241 | *****************************************************************************/ | ||
242 | acpi_status | ||
243 | acpi_get_table_header(char *signature, | ||
244 | acpi_native_uint instance, | ||
245 | struct acpi_table_header **out_table_header) | ||
246 | { | ||
247 | acpi_native_uint i; | ||
248 | acpi_native_uint j; | ||
177 | 249 | ||
178 | status = AE_OK; | 250 | /* |
251 | * Walk the root table list | ||
252 | */ | ||
253 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
254 | if (!ACPI_COMPARE_NAME | ||
255 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
256 | signature)) { | ||
257 | continue; | ||
179 | } | 258 | } |
180 | 259 | ||
181 | /* Free table allocated by acpi_tb_get_table_body */ | 260 | if (++j < instance) { |
182 | 261 | continue; | |
183 | acpi_tb_delete_single_table(&table_info); | 262 | } |
184 | return_ACPI_STATUS(status); | ||
185 | } | ||
186 | |||
187 | /* Convert the table to common format if necessary */ | ||
188 | |||
189 | switch (table_info.type) { | ||
190 | case ACPI_TABLE_ID_FADT: | ||
191 | |||
192 | status = acpi_tb_convert_table_fadt(); | ||
193 | break; | ||
194 | |||
195 | case ACPI_TABLE_ID_FACS: | ||
196 | |||
197 | status = acpi_tb_build_common_facs(&table_info); | ||
198 | break; | ||
199 | |||
200 | default: | ||
201 | /* Load table into namespace if it contains executable AML */ | ||
202 | |||
203 | status = | ||
204 | acpi_ns_load_table(table_info.installed_desc, | ||
205 | acpi_gbl_root_node); | ||
206 | break; | ||
207 | } | ||
208 | 263 | ||
209 | if (ACPI_FAILURE(status)) { | 264 | *out_table_header = |
265 | acpi_tb_map(acpi_gbl_root_table_list.tables[i].address, | ||
266 | (u32) sizeof(struct acpi_table_header), | ||
267 | acpi_gbl_root_table_list.tables[i]. | ||
268 | flags & ACPI_TABLE_ORIGIN_MASK); | ||
210 | 269 | ||
211 | /* Uninstall table and free the buffer */ | 270 | if (!out_table_header) { |
271 | return (AE_NO_MEMORY); | ||
272 | } | ||
212 | 273 | ||
213 | (void)acpi_tb_uninstall_table(table_info.installed_desc); | 274 | return (AE_OK); |
214 | } | 275 | } |
215 | 276 | ||
216 | return_ACPI_STATUS(status); | 277 | return (AE_NOT_FOUND); |
217 | } | 278 | } |
218 | 279 | ||
219 | ACPI_EXPORT_SYMBOL(acpi_load_table) | 280 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) |
220 | 281 | ||
221 | /******************************************************************************* | 282 | |
283 | /****************************************************************************** | ||
222 | * | 284 | * |
223 | * FUNCTION: acpi_unload_table_id | 285 | * FUNCTION: acpi_unload_table_id |
224 | * | 286 | * |
225 | * PARAMETERS: table_type - Type of table to be unloaded | 287 | * PARAMETERS: id - Owner ID of the table to be removed. |
226 | * id - Owner ID of the table to be removed. | ||
227 | * | 288 | * |
228 | * RETURN: Status | 289 | * RETURN: Status |
229 | * | 290 | * |
230 | * DESCRIPTION: This routine is used to force the unload of a table (by id) | 291 | * DESCRIPTION: This routine is used to force the unload of a table (by id) |
231 | * | 292 | * |
232 | ******************************************************************************/ | 293 | ******************************************************************************/ |
233 | acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id) | 294 | acpi_status acpi_unload_table_id(acpi_owner_id id) |
234 | { | 295 | { |
235 | struct acpi_table_desc *table_desc; | 296 | int i; |
236 | acpi_status status; | 297 | acpi_status status = AE_NOT_EXIST; |
237 | 298 | ||
238 | ACPI_FUNCTION_TRACE(acpi_unload_table); | 299 | ACPI_FUNCTION_TRACE(acpi_unload_table); |
239 | 300 | ||
240 | /* Parameter validation */ | ||
241 | if (table_type > ACPI_TABLE_ID_MAX) | ||
242 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
243 | |||
244 | /* Find table from the requested type list */ | 301 | /* Find table from the requested type list */ |
245 | table_desc = acpi_gbl_table_lists[table_type].next; | 302 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
246 | while (table_desc && table_desc->owner_id != id) | 303 | if (id != acpi_gbl_root_table_list.tables[i].owner_id) { |
247 | table_desc = table_desc->next; | 304 | continue; |
248 | 305 | } | |
249 | if (!table_desc) | 306 | /* |
250 | return_ACPI_STATUS(AE_NOT_EXIST); | 307 | * Delete all namespace objects owned by this table. Note that these |
251 | 308 | * objects can appear anywhere in the namespace by virtue of the AML | |
252 | /* | 309 | * "Scope" operator. Thus, we need to track ownership by an ID, not |
253 | * Delete all namespace objects owned by this table. Note that these | 310 | * simply a position within the hierarchy |
254 | * objects can appear anywhere in the namespace by virtue of the AML | 311 | */ |
255 | * "Scope" operator. Thus, we need to track ownership by an ID, not | 312 | acpi_tb_delete_namespace_by_owner(i); |
256 | * simply a position within the hierarchy | 313 | acpi_tb_release_owner_id(i); |
257 | */ | 314 | acpi_tb_set_table_loaded_flag(i, FALSE); |
258 | acpi_ns_delete_namespace_by_owner(table_desc->owner_id); | 315 | } |
259 | 316 | return_ACPI_STATUS(status); | |
260 | status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
261 | if (ACPI_FAILURE(status)) | ||
262 | return_ACPI_STATUS(status); | ||
263 | |||
264 | (void)acpi_tb_uninstall_table(table_desc); | ||
265 | |||
266 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
267 | |||
268 | return_ACPI_STATUS(AE_OK); | ||
269 | } | 317 | } |
270 | 318 | ||
271 | ACPI_EXPORT_SYMBOL(acpi_unload_table_id) | 319 | ACPI_EXPORT_SYMBOL(acpi_unload_table_id) |
272 | 320 | ||
273 | #ifdef ACPI_FUTURE_USAGE | ||
274 | /******************************************************************************* | 321 | /******************************************************************************* |
275 | * | 322 | * |
276 | * FUNCTION: acpi_unload_table | 323 | * FUNCTION: acpi_get_table |
277 | * | 324 | * |
278 | * PARAMETERS: table_type - Type of table to be unloaded | 325 | * PARAMETERS: Signature - ACPI signature of needed table |
326 | * Instance - Which instance (for SSDTs) | ||
327 | * out_table - Where the pointer to the table is returned | ||
279 | * | 328 | * |
280 | * RETURN: Status | 329 | * RETURN: Status and pointer to table |
281 | * | 330 | * |
282 | * DESCRIPTION: This routine is used to force the unload of a table | 331 | * DESCRIPTION: Finds and verifies an ACPI table. |
283 | * | 332 | * |
284 | ******************************************************************************/ | 333 | *****************************************************************************/ |
285 | acpi_status acpi_unload_table(acpi_table_type table_type) | 334 | acpi_status |
335 | acpi_get_table(char *signature, | ||
336 | acpi_native_uint instance, struct acpi_table_header ** out_table) | ||
286 | { | 337 | { |
287 | struct acpi_table_desc *table_desc; | 338 | acpi_native_uint i; |
288 | 339 | acpi_native_uint j; | |
289 | ACPI_FUNCTION_TRACE(acpi_unload_table); | 340 | acpi_status status; |
290 | |||
291 | /* Parameter validation */ | ||
292 | 341 | ||
293 | if (table_type > ACPI_TABLE_ID_MAX) { | 342 | /* |
294 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 343 | * Walk the root table list |
295 | } | 344 | */ |
345 | for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) { | ||
346 | if (!ACPI_COMPARE_NAME | ||
347 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
348 | signature)) { | ||
349 | continue; | ||
350 | } | ||
296 | 351 | ||
297 | /* Find all tables of the requested type */ | 352 | if (++j < instance) { |
353 | continue; | ||
354 | } | ||
298 | 355 | ||
299 | table_desc = acpi_gbl_table_lists[table_type].next; | 356 | status = |
300 | if (!table_desc) { | 357 | acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]); |
301 | return_ACPI_STATUS(AE_NOT_EXIST); | 358 | if (ACPI_SUCCESS(status)) { |
302 | } | 359 | *out_table = acpi_gbl_root_table_list.tables[i].pointer; |
360 | } | ||
303 | 361 | ||
304 | while (table_desc) { | 362 | return (status); |
305 | /* | ||
306 | * Delete all namespace objects owned by this table. Note that these | ||
307 | * objects can appear anywhere in the namespace by virtue of the AML | ||
308 | * "Scope" operator. Thus, we need to track ownership by an ID, not | ||
309 | * simply a position within the hierarchy | ||
310 | */ | ||
311 | acpi_ns_delete_namespace_by_owner(table_desc->owner_id); | ||
312 | table_desc = table_desc->next; | ||
313 | } | 363 | } |
314 | 364 | ||
315 | /* Delete (or unmap) all tables of this type */ | 365 | return (AE_NOT_FOUND); |
316 | |||
317 | acpi_tb_delete_tables_by_type(table_type); | ||
318 | return_ACPI_STATUS(AE_OK); | ||
319 | } | 366 | } |
320 | 367 | ||
321 | ACPI_EXPORT_SYMBOL(acpi_unload_table) | 368 | ACPI_EXPORT_SYMBOL(acpi_get_table) |
322 | 369 | ||
323 | /******************************************************************************* | 370 | /******************************************************************************* |
324 | * | 371 | * |
325 | * FUNCTION: acpi_get_table_header | 372 | * FUNCTION: acpi_get_table_by_index |
326 | * | 373 | * |
327 | * PARAMETERS: table_type - one of the defined table types | 374 | * PARAMETERS: table_index - Table index |
328 | * Instance - the non zero instance of the table, allows | 375 | * Table - Where the pointer to the table is returned |
329 | * support for multiple tables of the same type | ||
330 | * see acpi_gbl_acpi_table_flag | ||
331 | * out_table_header - pointer to the struct acpi_table_header if successful | ||
332 | * | 376 | * |
333 | * DESCRIPTION: This function is called to get an ACPI table header. The caller | 377 | * RETURN: Status and pointer to the table |
334 | * supplies an pointer to a data area sufficient to contain an ACPI | ||
335 | * struct acpi_table_header structure. | ||
336 | * | 378 | * |
337 | * The header contains a length field that can be used to determine | 379 | * DESCRIPTION: Obtain a table by an index into the global table list. |
338 | * the size of the buffer needed to contain the entire table. This | ||
339 | * function is not valid for the RSD PTR table since it does not | ||
340 | * have a standard header and is fixed length. | ||
341 | * | 380 | * |
342 | ******************************************************************************/ | 381 | ******************************************************************************/ |
343 | acpi_status | 382 | acpi_status |
344 | acpi_get_table_header(acpi_table_type table_type, | 383 | acpi_get_table_by_index(acpi_native_uint table_index, |
345 | u32 instance, struct acpi_table_header *out_table_header) | 384 | struct acpi_table_header ** table) |
346 | { | 385 | { |
347 | struct acpi_table_header *tbl_ptr; | ||
348 | acpi_status status; | 386 | acpi_status status; |
349 | 387 | ||
350 | ACPI_FUNCTION_TRACE(acpi_get_table_header); | 388 | ACPI_FUNCTION_TRACE(acpi_get_table_by_index); |
351 | 389 | ||
352 | if ((instance == 0) || | 390 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
353 | (table_type == ACPI_TABLE_ID_RSDP) || (!out_table_header)) { | ||
354 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
355 | } | ||
356 | 391 | ||
357 | /* Check the table type and instance */ | 392 | /* Validate index */ |
358 | 393 | ||
359 | if ((table_type > ACPI_TABLE_ID_MAX) || | 394 | if (table_index >= acpi_gbl_root_table_list.count) { |
360 | (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && | 395 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
361 | instance > 1)) { | ||
362 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 396 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
363 | } | 397 | } |
364 | 398 | ||
365 | /* Get a pointer to the entire table */ | 399 | if (!acpi_gbl_root_table_list.tables[table_index].pointer) { |
366 | 400 | ||
367 | status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); | 401 | /* Table is not mapped, map it */ |
368 | if (ACPI_FAILURE(status)) { | ||
369 | return_ACPI_STATUS(status); | ||
370 | } | ||
371 | 402 | ||
372 | /* The function will return a NULL pointer if the table is not loaded */ | 403 | status = |
373 | 404 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | |
374 | if (tbl_ptr == NULL) { | 405 | tables[table_index]); |
375 | return_ACPI_STATUS(AE_NOT_EXIST); | 406 | if (ACPI_FAILURE(status)) { |
407 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
408 | return_ACPI_STATUS(status); | ||
409 | } | ||
376 | } | 410 | } |
377 | 411 | ||
378 | /* Copy the header to the caller's buffer */ | 412 | *table = acpi_gbl_root_table_list.tables[table_index].pointer; |
379 | 413 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | |
380 | ACPI_MEMCPY(ACPI_CAST_PTR(void, out_table_header), | 414 | return_ACPI_STATUS(AE_OK); |
381 | ACPI_CAST_PTR(void, tbl_ptr), | ||
382 | sizeof(struct acpi_table_header)); | ||
383 | |||
384 | return_ACPI_STATUS(status); | ||
385 | } | 415 | } |
386 | 416 | ||
387 | ACPI_EXPORT_SYMBOL(acpi_get_table_header) | 417 | ACPI_EXPORT_SYMBOL(acpi_get_table_by_index) |
388 | #endif /* ACPI_FUTURE_USAGE */ | ||
389 | 418 | ||
390 | /******************************************************************************* | 419 | /******************************************************************************* |
391 | * | 420 | * |
392 | * FUNCTION: acpi_get_table | 421 | * FUNCTION: acpi_tb_load_namespace |
393 | * | 422 | * |
394 | * PARAMETERS: table_type - one of the defined table types | 423 | * PARAMETERS: None |
395 | * Instance - the non zero instance of the table, allows | ||
396 | * support for multiple tables of the same type | ||
397 | * see acpi_gbl_acpi_table_flag | ||
398 | * ret_buffer - pointer to a structure containing a buffer to | ||
399 | * receive the table | ||
400 | * | 424 | * |
401 | * RETURN: Status | 425 | * RETURN: Status |
402 | * | 426 | * |
403 | * DESCRIPTION: This function is called to get an ACPI table. The caller | 427 | * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in |
404 | * supplies an out_buffer large enough to contain the entire ACPI | 428 | * the RSDT/XSDT. |
405 | * table. The caller should call the acpi_get_table_header function | ||
406 | * first to determine the buffer size needed. Upon completion | ||
407 | * the out_buffer->Length field will indicate the number of bytes | ||
408 | * copied into the out_buffer->buf_ptr buffer. This table will be | ||
409 | * a complete table including the header. | ||
410 | * | 429 | * |
411 | ******************************************************************************/ | 430 | ******************************************************************************/ |
412 | acpi_status | 431 | static acpi_status acpi_tb_load_namespace(void) |
413 | acpi_get_table(acpi_table_type table_type, | ||
414 | u32 instance, struct acpi_buffer *ret_buffer) | ||
415 | { | 432 | { |
416 | struct acpi_table_header *tbl_ptr; | ||
417 | acpi_status status; | 433 | acpi_status status; |
418 | acpi_size table_length; | 434 | struct acpi_table_header *table; |
435 | acpi_native_uint i; | ||
419 | 436 | ||
420 | ACPI_FUNCTION_TRACE(acpi_get_table); | 437 | ACPI_FUNCTION_TRACE(tb_load_namespace); |
421 | 438 | ||
422 | /* Parameter validation */ | 439 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
423 | 440 | ||
424 | if (instance == 0) { | 441 | /* |
425 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 442 | * Load the namespace. The DSDT is required, but any SSDT and PSDT tables |
443 | * are optional. | ||
444 | */ | ||
445 | if (!acpi_gbl_root_table_list.count || | ||
446 | !ACPI_COMPARE_NAME(& | ||
447 | (acpi_gbl_root_table_list. | ||
448 | tables[ACPI_TABLE_INDEX_DSDT].signature), | ||
449 | ACPI_SIG_DSDT) | ||
450 | || | ||
451 | ACPI_FAILURE(acpi_tb_verify_table | ||
452 | (&acpi_gbl_root_table_list. | ||
453 | tables[ACPI_TABLE_INDEX_DSDT]))) { | ||
454 | status = AE_NO_ACPI_TABLES; | ||
455 | goto unlock_and_exit; | ||
426 | } | 456 | } |
427 | 457 | ||
428 | status = acpi_ut_validate_buffer(ret_buffer); | 458 | /* |
429 | if (ACPI_FAILURE(status)) { | 459 | * Find DSDT table |
430 | return_ACPI_STATUS(status); | 460 | */ |
461 | status = | ||
462 | acpi_os_table_override(acpi_gbl_root_table_list. | ||
463 | tables[ACPI_TABLE_INDEX_DSDT].pointer, | ||
464 | &table); | ||
465 | if (ACPI_SUCCESS(status) && table) { | ||
466 | /* | ||
467 | * DSDT table has been found | ||
468 | */ | ||
469 | acpi_tb_delete_table(ACPI_TABLE_INDEX_DSDT); | ||
470 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer = | ||
471 | table; | ||
472 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length = | ||
473 | table->length; | ||
474 | acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags = | ||
475 | ACPI_TABLE_ORIGIN_UNKNOWN; | ||
476 | |||
477 | ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); | ||
478 | acpi_tb_print_table_header(0, table); | ||
431 | } | 479 | } |
432 | 480 | ||
433 | /* Check the table type and instance */ | 481 | status = |
482 | acpi_tb_verify_table(&acpi_gbl_root_table_list. | ||
483 | tables[ACPI_TABLE_INDEX_DSDT]); | ||
484 | if (ACPI_FAILURE(status)) { | ||
485 | |||
486 | /* A valid DSDT is required */ | ||
434 | 487 | ||
435 | if ((table_type > ACPI_TABLE_ID_MAX) || | 488 | status = AE_NO_ACPI_TABLES; |
436 | (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) && | 489 | goto unlock_and_exit; |
437 | instance > 1)) { | ||
438 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
439 | } | 490 | } |
440 | 491 | ||
441 | /* Get a pointer to the entire table */ | 492 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); |
442 | 493 | ||
443 | status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr); | 494 | /* |
495 | * Load and parse tables. | ||
496 | */ | ||
497 | status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); | ||
444 | if (ACPI_FAILURE(status)) { | 498 | if (ACPI_FAILURE(status)) { |
445 | return_ACPI_STATUS(status); | 499 | return_ACPI_STATUS(status); |
446 | } | 500 | } |
447 | 501 | ||
448 | /* | 502 | /* |
449 | * acpi_tb_get_table_ptr will return a NULL pointer if the | 503 | * Load any SSDT or PSDT tables. Note: Loop leaves tables locked |
450 | * table is not loaded. | ||
451 | */ | 504 | */ |
452 | if (tbl_ptr == NULL) { | 505 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); |
453 | return_ACPI_STATUS(AE_NOT_EXIST); | 506 | for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { |
507 | if ((!ACPI_COMPARE_NAME | ||
508 | (&(acpi_gbl_root_table_list.tables[i].signature), | ||
509 | ACPI_SIG_SSDT) | ||
510 | && | ||
511 | !ACPI_COMPARE_NAME(& | ||
512 | (acpi_gbl_root_table_list.tables[i]. | ||
513 | signature), ACPI_SIG_PSDT)) | ||
514 | || | ||
515 | ACPI_FAILURE(acpi_tb_verify_table | ||
516 | (&acpi_gbl_root_table_list.tables[i]))) { | ||
517 | continue; | ||
518 | } | ||
519 | |||
520 | /* Ignore errors while loading tables, get as many as possible */ | ||
521 | |||
522 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
523 | (void)acpi_ns_load_table(i, acpi_gbl_root_node); | ||
524 | (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); | ||
454 | } | 525 | } |
455 | 526 | ||
456 | /* Get the table length */ | 527 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n")); |
457 | 528 | ||
458 | if (table_type == ACPI_TABLE_ID_RSDP) { | 529 | unlock_and_exit: |
530 | (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); | ||
531 | return_ACPI_STATUS(status); | ||
532 | } | ||
459 | 533 | ||
460 | /* RSD PTR is the only "table" without a header */ | 534 | /******************************************************************************* |
535 | * | ||
536 | * FUNCTION: acpi_load_tables | ||
537 | * | ||
538 | * PARAMETERS: None | ||
539 | * | ||
540 | * RETURN: Status | ||
541 | * | ||
542 | * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT | ||
543 | * | ||
544 | ******************************************************************************/ | ||
461 | 545 | ||
462 | table_length = sizeof(struct rsdp_descriptor); | 546 | acpi_status acpi_load_tables(void) |
463 | } else { | 547 | { |
464 | table_length = (acpi_size) tbl_ptr->length; | 548 | acpi_status status; |
465 | } | ||
466 | 549 | ||
467 | /* Validate/Allocate/Clear caller buffer */ | 550 | ACPI_FUNCTION_TRACE(acpi_load_tables); |
468 | 551 | ||
469 | status = acpi_ut_initialize_buffer(ret_buffer, table_length); | 552 | /* |
553 | * Load the namespace from the tables | ||
554 | */ | ||
555 | status = acpi_tb_load_namespace(); | ||
470 | if (ACPI_FAILURE(status)) { | 556 | if (ACPI_FAILURE(status)) { |
471 | return_ACPI_STATUS(status); | 557 | ACPI_EXCEPTION((AE_INFO, status, |
558 | "While loading namespace from ACPI tables")); | ||
472 | } | 559 | } |
473 | 560 | ||
474 | /* Copy the table to the buffer */ | 561 | return_ACPI_STATUS(status); |
475 | |||
476 | ACPI_MEMCPY(ACPI_CAST_PTR(void, ret_buffer->pointer), | ||
477 | ACPI_CAST_PTR(void, tbl_ptr), table_length); | ||
478 | |||
479 | return_ACPI_STATUS(AE_OK); | ||
480 | } | 562 | } |
481 | 563 | ||
482 | ACPI_EXPORT_SYMBOL(acpi_get_table) | 564 | ACPI_EXPORT_SYMBOL(acpi_load_tables) |