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 - 2007, R. Byron Moore
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 <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/actables.h>
48
49#define _COMPONENT          ACPI_TABLES
50ACPI_MODULE_NAME("tbxface")
51
52/* Local prototypes */
53static acpi_status acpi_tb_load_namespace(void);
54
55/*******************************************************************************
56 *
57 * FUNCTION:    acpi_allocate_root_table
58 *
59 * PARAMETERS:  initial_table_count - Size of initial_table_array, in number of
60 *                                    struct acpi_table_desc structures
61 *
62 * RETURN:      Status
63 *
64 * DESCRIPTION: Allocate a root table array. Used by i_aSL compiler and
65 *              acpi_initialize_tables.
66 *
67 ******************************************************************************/
68
69acpi_status acpi_allocate_root_table(u32 initial_table_count)
70{
71
72	acpi_gbl_root_table_list.size = initial_table_count;
73	acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
74
75	return (acpi_tb_resize_root_table_list());
76}
77
78/*******************************************************************************
79 *
80 * FUNCTION:    acpi_initialize_tables
81 *
82 * PARAMETERS:  initial_table_array - Pointer to an array of pre-allocated
83 *                                    struct acpi_table_desc structures. If NULL, the
84 *                                    array is dynamically allocated.
85 *              initial_table_count - Size of initial_table_array, in number of
86 *                                    struct acpi_table_desc structures
87 *              allow_realloc       - Flag to tell Table Manager if resize of
88 *                                    pre-allocated array is allowed. Ignored
89 *                                    if initial_table_array is NULL.
90 *
91 * RETURN:      Status
92 *
93 * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
94 *
95 * NOTE:        Allows static allocation of the initial table array in order
96 *              to avoid the use of dynamic memory in confined environments
97 *              such as the kernel boot sequence where it may not be available.
98 *
99 *              If the host OS memory managers are initialized, use NULL for
100 *              initial_table_array, and the table will be dynamically allocated.
101 *
102 ******************************************************************************/
103
104acpi_status __init
105acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
106		       u32 initial_table_count, u8 allow_resize)
107{
108	acpi_physical_address rsdp_address;
109	acpi_status status;
110
111	ACPI_FUNCTION_TRACE(acpi_initialize_tables);
112
113	/*
114	 * Set up the Root Table Array
115	 * Allocate the table array if requested
116	 */
117	if (!initial_table_array) {
118		status = acpi_allocate_root_table(initial_table_count);
119		if (ACPI_FAILURE(status)) {
120			return_ACPI_STATUS(status);
121		}
122	} else {
123		/* Root Table Array has been statically allocated by the host */
124
125		ACPI_MEMSET(initial_table_array, 0,
126			    initial_table_count *
127			    sizeof(struct acpi_table_desc));
128
129		acpi_gbl_root_table_list.tables = initial_table_array;
130		acpi_gbl_root_table_list.size = initial_table_count;
131		acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
132		if (allow_resize) {
133			acpi_gbl_root_table_list.flags |=
134			    ACPI_ROOT_ALLOW_RESIZE;
135		}
136	}
137
138	/* Get the address of the RSDP */
139
140	rsdp_address = acpi_os_get_root_pointer();
141	if (!rsdp_address) {
142		return_ACPI_STATUS(AE_NOT_FOUND);
143	}
144
145	/*
146	 * Get the root table (RSDT or XSDT) and extract all entries to the local
147	 * Root Table Array. This array contains the information of the RSDT/XSDT
148	 * in a common, more useable format.
149	 */
150	status =
151	    acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
152	return_ACPI_STATUS(status);
153}
154
155/*******************************************************************************
156 *
157 * FUNCTION:    acpi_reallocate_root_table
158 *
159 * PARAMETERS:  None
160 *
161 * RETURN:      Status
162 *
163 * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
164 *              root list from the previously provided scratch area. Should
165 *              be called once dynamic memory allocation is available in the
166 *              kernel
167 *
168 ******************************************************************************/
169acpi_status acpi_reallocate_root_table(void)
170{
171	struct acpi_table_desc *tables;
172	acpi_size new_size;
173
174	ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
175
176	/*
177	 * Only reallocate the root table if the host provided a static buffer
178	 * for the table array in the call to acpi_initialize_tables.
179	 */
180	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
181		return_ACPI_STATUS(AE_SUPPORT);
182	}
183
184	new_size =
185	    (acpi_gbl_root_table_list.count +
186	     ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc);
187
188	/* Create new array and copy the old array */
189
190	tables = ACPI_ALLOCATE_ZEROED(new_size);
191	if (!tables) {
192		return_ACPI_STATUS(AE_NO_MEMORY);
193	}
194
195	ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size);
196
197	acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count;
198	acpi_gbl_root_table_list.tables = tables;
199	acpi_gbl_root_table_list.flags =
200	    ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
201
202	return_ACPI_STATUS(AE_OK);
203}
204
205/*******************************************************************************
206 *
207 * FUNCTION:    acpi_load_table
208 *
209 * PARAMETERS:  table_ptr       - pointer to a buffer containing the entire
210 *                                table to be loaded
211 *
212 * RETURN:      Status
213 *
214 * DESCRIPTION: This function is called to load a table from the caller's
215 *              buffer. The buffer must contain an entire ACPI Table including
216 *              a valid header. The header fields will be verified, and if it
217 *              is determined that the table is invalid, the call will fail.
218 *
219 ******************************************************************************/
220acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
221{
222	acpi_status status;
223	acpi_native_uint table_index;
224	struct acpi_table_desc table_desc;
225
226	if (!table_ptr)
227		return AE_BAD_PARAMETER;
228
229	ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
230	table_desc.pointer = table_ptr;
231	table_desc.length = table_ptr->length;
232	table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
233
234	/*
235	 * Install the new table into the local data structures
236	 */
237	status = acpi_tb_add_table(&table_desc, &table_index);
238	if (ACPI_FAILURE(status)) {
239		return status;
240	}
241	status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
242	return status;
243}
244
245ACPI_EXPORT_SYMBOL(acpi_load_table)
246
247/******************************************************************************
248 *
249 * FUNCTION:    acpi_get_table_header
250 *
251 * PARAMETERS:  Signature           - ACPI signature of needed table
252 *              Instance            - Which instance (for SSDTs)
253 *              out_table_header    - The pointer to the table header to fill
254 *
255 * RETURN:      Status and pointer to mapped table header
256 *
257 * DESCRIPTION: Finds an ACPI table header.
258 *
259 * NOTE:        Caller is responsible in unmapping the header with
260 *              acpi_os_unmap_memory
261 *
262 *****************************************************************************/
263acpi_status
264acpi_get_table_header(char *signature,
265		      acpi_native_uint instance,
266		      struct acpi_table_header * out_table_header)
267{
268	acpi_native_uint i;
269	acpi_native_uint j;
270	struct acpi_table_header *header;
271
272	/* Parameter validation */
273
274	if (!signature || !out_table_header) {
275		return (AE_BAD_PARAMETER);
276	}
277
278	/*
279	 * Walk the root table list
280	 */
281	for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
282		if (!ACPI_COMPARE_NAME
283		    (&(acpi_gbl_root_table_list.tables[i].signature),
284		     signature)) {
285			continue;
286		}
287
288		if (++j < instance) {
289			continue;
290		}
291
292		if (!acpi_gbl_root_table_list.tables[i].pointer) {
293			if ((acpi_gbl_root_table_list.tables[i].
294			     flags & ACPI_TABLE_ORIGIN_MASK) ==
295			    ACPI_TABLE_ORIGIN_MAPPED) {
296				header =
297				    acpi_os_map_memory(acpi_gbl_root_table_list.
298						       tables[i].address,
299						       sizeof(struct
300							      acpi_table_header));
301				if (!header) {
302					return AE_NO_MEMORY;
303				}
304				ACPI_MEMCPY(out_table_header, header,
305					    sizeof(struct acpi_table_header));
306				acpi_os_unmap_memory(header,
307						     sizeof(struct
308							    acpi_table_header));
309			} else {
310				return AE_NOT_FOUND;
311			}
312		} else {
313			ACPI_MEMCPY(out_table_header,
314				    acpi_gbl_root_table_list.tables[i].pointer,
315				    sizeof(struct acpi_table_header));
316		}
317		return (AE_OK);
318	}
319
320	return (AE_NOT_FOUND);
321}
322
323ACPI_EXPORT_SYMBOL(acpi_get_table_header)
324
325/******************************************************************************
326 *
327 * FUNCTION:    acpi_unload_table_id
328 *
329 * PARAMETERS:  id            - Owner ID of the table to be removed.
330 *
331 * RETURN:      Status
332 *
333 * DESCRIPTION: This routine is used to force the unload of a table (by id)
334 *
335 ******************************************************************************/
336acpi_status acpi_unload_table_id(acpi_owner_id id)
337{
338	int i;
339	acpi_status status = AE_NOT_EXIST;
340
341	ACPI_FUNCTION_TRACE(acpi_unload_table_id);
342
343	/* Find table in the global table list */
344	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
345		if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
346			continue;
347		}
348		/*
349		 * Delete all namespace objects owned by this table. Note that these
350		 * objects can appear anywhere in the namespace by virtue of the AML
351		 * "Scope" operator. Thus, we need to track ownership by an ID, not
352		 * simply a position within the hierarchy
353		 */
354		acpi_tb_delete_namespace_by_owner(i);
355		status = acpi_tb_release_owner_id(i);
356		acpi_tb_set_table_loaded_flag(i, FALSE);
357		break;
358	}
359	return_ACPI_STATUS(status);
360}
361
362ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
363
364/*******************************************************************************
365 *
366 * FUNCTION:    acpi_get_table
367 *
368 * PARAMETERS:  Signature           - ACPI signature of needed table
369 *              Instance            - Which instance (for SSDTs)
370 *              out_table           - Where the pointer to the table is returned
371 *
372 * RETURN:      Status and pointer to table
373 *
374 * DESCRIPTION: Finds and verifies an ACPI table.
375 *
376 *****************************************************************************/
377acpi_status
378acpi_get_table(char *signature,
379	       acpi_native_uint instance, struct acpi_table_header **out_table)
380{
381	acpi_native_uint i;
382	acpi_native_uint j;
383	acpi_status status;
384
385	/* Parameter validation */
386
387	if (!signature || !out_table) {
388		return (AE_BAD_PARAMETER);
389	}
390
391	/*
392	 * Walk the root table list
393	 */
394	for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
395		if (!ACPI_COMPARE_NAME
396		    (&(acpi_gbl_root_table_list.tables[i].signature),
397		     signature)) {
398			continue;
399		}
400
401		if (++j < instance) {
402			continue;
403		}
404
405		status =
406		    acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
407		if (ACPI_SUCCESS(status)) {
408			*out_table = acpi_gbl_root_table_list.tables[i].pointer;
409		}
410
411		if (!acpi_gbl_permanent_mmap) {
412			acpi_gbl_root_table_list.tables[i].pointer = NULL;
413		}
414
415		return (status);
416	}
417
418	return (AE_NOT_FOUND);
419}
420
421ACPI_EXPORT_SYMBOL(acpi_get_table)
422
423/*******************************************************************************
424 *
425 * FUNCTION:    acpi_get_table_by_index
426 *
427 * PARAMETERS:  table_index         - Table index
428 *              Table               - Where the pointer to the table is returned
429 *
430 * RETURN:      Status and pointer to the table
431 *
432 * DESCRIPTION: Obtain a table by an index into the global table list.
433 *
434 ******************************************************************************/
435acpi_status
436acpi_get_table_by_index(acpi_native_uint table_index,
437			struct acpi_table_header ** table)
438{
439	acpi_status status;
440
441	ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
442
443	/* Parameter validation */
444
445	if (!table) {
446		return_ACPI_STATUS(AE_BAD_PARAMETER);
447	}
448
449	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
450
451	/* Validate index */
452
453	if (table_index >= acpi_gbl_root_table_list.count) {
454		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
455		return_ACPI_STATUS(AE_BAD_PARAMETER);
456	}
457
458	if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
459
460		/* Table is not mapped, map it */
461
462		status =
463		    acpi_tb_verify_table(&acpi_gbl_root_table_list.
464					 tables[table_index]);
465		if (ACPI_FAILURE(status)) {
466			(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
467			return_ACPI_STATUS(status);
468		}
469	}
470
471	*table = acpi_gbl_root_table_list.tables[table_index].pointer;
472	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
473	return_ACPI_STATUS(AE_OK);
474}
475
476ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
477
478/*******************************************************************************
479 *
480 * FUNCTION:    acpi_tb_load_namespace
481 *
482 * PARAMETERS:  None
483 *
484 * RETURN:      Status
485 *
486 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
487 *              the RSDT/XSDT.
488 *
489 ******************************************************************************/
490static acpi_status acpi_tb_load_namespace(void)
491{
492	acpi_status status;
493	struct acpi_table_header *table;
494	acpi_native_uint i;
495
496	ACPI_FUNCTION_TRACE(tb_load_namespace);
497
498	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
499
500	/*
501	 * Load the namespace. The DSDT is required, but any SSDT and PSDT tables
502	 * are optional.
503	 */
504	if (!acpi_gbl_root_table_list.count ||
505	    !ACPI_COMPARE_NAME(&
506			       (acpi_gbl_root_table_list.
507				tables[ACPI_TABLE_INDEX_DSDT].signature),
508			       ACPI_SIG_DSDT)
509	    ||
510	    ACPI_FAILURE(acpi_tb_verify_table
511			 (&acpi_gbl_root_table_list.
512			  tables[ACPI_TABLE_INDEX_DSDT]))) {
513		status = AE_NO_ACPI_TABLES;
514		goto unlock_and_exit;
515	}
516
517	/*
518	 * Find DSDT table
519	 */
520	status =
521	    acpi_os_table_override(acpi_gbl_root_table_list.
522				   tables[ACPI_TABLE_INDEX_DSDT].pointer,
523				   &table);
524	if (ACPI_SUCCESS(status) && table) {
525		/*
526		 * DSDT table has been found
527		 */
528		acpi_tb_delete_table(&acpi_gbl_root_table_list.
529				     tables[ACPI_TABLE_INDEX_DSDT]);
530		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
531		    table;
532		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
533		    table->length;
534		acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
535		    ACPI_TABLE_ORIGIN_UNKNOWN;
536
537		ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
538		acpi_tb_print_table_header(0, table);
539	}
540
541	status =
542	    acpi_tb_verify_table(&acpi_gbl_root_table_list.
543				 tables[ACPI_TABLE_INDEX_DSDT]);
544	if (ACPI_FAILURE(status)) {
545
546		/* A valid DSDT is required */
547
548		status = AE_NO_ACPI_TABLES;
549		goto unlock_and_exit;
550	}
551
552	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
553
554	/*
555	 * Load and parse tables.
556	 */
557	status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
558	if (ACPI_FAILURE(status)) {
559		return_ACPI_STATUS(status);
560	}
561
562	/*
563	 * Load any SSDT or PSDT tables. Note: Loop leaves tables locked
564	 */
565	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
566	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
567		if ((!ACPI_COMPARE_NAME
568		     (&(acpi_gbl_root_table_list.tables[i].signature),
569		      ACPI_SIG_SSDT)
570		     &&
571		     !ACPI_COMPARE_NAME(&
572					(acpi_gbl_root_table_list.tables[i].
573					 signature), ACPI_SIG_PSDT))
574		    ||
575		    ACPI_FAILURE(acpi_tb_verify_table
576				 (&acpi_gbl_root_table_list.tables[i]))) {
577			continue;
578		}
579
580		/* Ignore errors while loading tables, get as many as possible */
581
582		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
583		(void)acpi_ns_load_table(i, acpi_gbl_root_node);
584		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
585	}
586
587	ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
588
589      unlock_and_exit:
590	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
591	return_ACPI_STATUS(status);
592}
593
594/*******************************************************************************
595 *
596 * FUNCTION:    acpi_load_tables
597 *
598 * PARAMETERS:  None
599 *
600 * RETURN:      Status
601 *
602 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
603 *
604 ******************************************************************************/
605
606acpi_status acpi_load_tables(void)
607{
608	acpi_status status;
609
610	ACPI_FUNCTION_TRACE(acpi_load_tables);
611
612	/*
613	 * Load the namespace from the tables
614	 */
615	status = acpi_tb_load_namespace();
616	if (ACPI_FAILURE(status)) {
617		ACPI_EXCEPTION((AE_INFO, status,
618				"While loading namespace from ACPI tables"));
619	}
620
621	return_ACPI_STATUS(status);
622}
623
624ACPI_EXPORT_SYMBOL(acpi_load_tables)
625