1/******************************************************************************
2 *
3 * Module Name: tbxfload - Table load/unload external interfaces
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2014, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions, and the following disclaimer,
16 *    without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 *    substantially similar to the "NO WARRANTY" disclaimer below
19 *    ("Disclaimer") and any redistribution must be conditioned upon
20 *    including a substantially similar Disclaimer requirement for further
21 *    binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 *    of any contributors may be used to endorse or promote products derived
24 *    from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#define EXPORT_ACPI_INTERFACES
45
46#include <acpi/acpi.h>
47#include "accommon.h"
48#include "acnamesp.h"
49#include "actables.h"
50
51#define _COMPONENT          ACPI_TABLES
52ACPI_MODULE_NAME("tbxfload")
53
54/* Local prototypes */
55static acpi_status acpi_tb_load_namespace(void);
56
57/*******************************************************************************
58 *
59 * FUNCTION:    acpi_load_tables
60 *
61 * PARAMETERS:  None
62 *
63 * RETURN:      Status
64 *
65 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
66 *
67 ******************************************************************************/
68
69acpi_status __init acpi_load_tables(void)
70{
71	acpi_status status;
72
73	ACPI_FUNCTION_TRACE(acpi_load_tables);
74
75	/* Load the namespace from the tables */
76
77	status = acpi_tb_load_namespace();
78	if (ACPI_FAILURE(status)) {
79		ACPI_EXCEPTION((AE_INFO, status,
80				"While loading namespace from ACPI tables"));
81	}
82
83	return_ACPI_STATUS(status);
84}
85
86ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
87
88/*******************************************************************************
89 *
90 * FUNCTION:    acpi_tb_load_namespace
91 *
92 * PARAMETERS:  None
93 *
94 * RETURN:      Status
95 *
96 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
97 *              the RSDT/XSDT.
98 *
99 ******************************************************************************/
100static acpi_status acpi_tb_load_namespace(void)
101{
102	acpi_status status;
103	u32 i;
104	struct acpi_table_header *new_dsdt;
105
106	ACPI_FUNCTION_TRACE(tb_load_namespace);
107
108	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
109
110	/*
111	 * Load the namespace. The DSDT is required, but any SSDT and
112	 * PSDT tables are optional. Verify the DSDT.
113	 */
114	if (!acpi_gbl_root_table_list.current_table_count ||
115	    !ACPI_COMPARE_NAME(&
116			       (acpi_gbl_root_table_list.
117				tables[ACPI_TABLE_INDEX_DSDT].signature),
118			       ACPI_SIG_DSDT)
119	    ||
120	    ACPI_FAILURE(acpi_tb_validate_table
121			 (&acpi_gbl_root_table_list.
122			  tables[ACPI_TABLE_INDEX_DSDT]))) {
123		status = AE_NO_ACPI_TABLES;
124		goto unlock_and_exit;
125	}
126
127	/*
128	 * Save the DSDT pointer for simple access. This is the mapped memory
129	 * address. We must take care here because the address of the .Tables
130	 * array can change dynamically as tables are loaded at run-time. Note:
131	 * .Pointer field is not validated until after call to acpi_tb_validate_table.
132	 */
133	acpi_gbl_DSDT =
134	    acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
135
136	/*
137	 * Optionally copy the entire DSDT to local memory (instead of simply
138	 * mapping it.) There are some BIOSs that corrupt or replace the original
139	 * DSDT, creating the need for this option. Default is FALSE, do not copy
140	 * the DSDT.
141	 */
142	if (acpi_gbl_copy_dsdt_locally) {
143		new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT);
144		if (new_dsdt) {
145			acpi_gbl_DSDT = new_dsdt;
146		}
147	}
148
149	/*
150	 * Save the original DSDT header for detection of table corruption
151	 * and/or replacement of the DSDT from outside the OS.
152	 */
153	ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
154		    sizeof(struct acpi_table_header));
155
156	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
157
158	/* Load and parse tables */
159
160	status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
161	if (ACPI_FAILURE(status)) {
162		return_ACPI_STATUS(status);
163	}
164
165	/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
166
167	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
168	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
169		if ((!ACPI_COMPARE_NAME
170		     (&(acpi_gbl_root_table_list.tables[i].signature),
171		      ACPI_SIG_SSDT)
172		     &&
173		     !ACPI_COMPARE_NAME(&
174					(acpi_gbl_root_table_list.tables[i].
175					 signature), ACPI_SIG_PSDT))
176		    ||
177		    ACPI_FAILURE(acpi_tb_validate_table
178				 (&acpi_gbl_root_table_list.tables[i]))) {
179			continue;
180		}
181
182		/* Ignore errors while loading tables, get as many as possible */
183
184		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
185		(void)acpi_ns_load_table(i, acpi_gbl_root_node);
186		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
187	}
188
189	ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired"));
190
191unlock_and_exit:
192	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
193	return_ACPI_STATUS(status);
194}
195
196/*******************************************************************************
197 *
198 * FUNCTION:    acpi_install_table
199 *
200 * PARAMETERS:  address             - Address of the ACPI table to be installed.
201 *              physical            - Whether the address is a physical table
202 *                                    address or not
203 *
204 * RETURN:      Status
205 *
206 * DESCRIPTION: Dynamically install an ACPI table.
207 *              Note: This function should only be invoked after
208 *                    acpi_initialize_tables() and before acpi_load_tables().
209 *
210 ******************************************************************************/
211
212acpi_status __init
213acpi_install_table(acpi_physical_address address, u8 physical)
214{
215	acpi_status status;
216	u8 flags;
217	u32 table_index;
218
219	ACPI_FUNCTION_TRACE(acpi_install_table);
220
221	if (physical) {
222		flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
223	} else {
224		flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
225	}
226
227	status = acpi_tb_install_standard_table(address, flags,
228						FALSE, FALSE, &table_index);
229
230	return_ACPI_STATUS(status);
231}
232
233ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
234
235/*******************************************************************************
236 *
237 * FUNCTION:    acpi_load_table
238 *
239 * PARAMETERS:  table               - Pointer to a buffer containing the ACPI
240 *                                    table to be loaded.
241 *
242 * RETURN:      Status
243 *
244 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
245 *              be a valid ACPI table with a valid ACPI table header.
246 *              Note1: Mainly intended to support hotplug addition of SSDTs.
247 *              Note2: Does not copy the incoming table. User is responsible
248 *              to ensure that the table is not deleted or unmapped.
249 *
250 ******************************************************************************/
251acpi_status acpi_load_table(struct acpi_table_header *table)
252{
253	acpi_status status;
254	u32 table_index;
255
256	ACPI_FUNCTION_TRACE(acpi_load_table);
257
258	/* Parameter validation */
259
260	if (!table) {
261		return_ACPI_STATUS(AE_BAD_PARAMETER);
262	}
263
264	/* Must acquire the interpreter lock during this operation */
265
266	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
267	if (ACPI_FAILURE(status)) {
268		return_ACPI_STATUS(status);
269	}
270
271	/* Install the table and load it into the namespace */
272
273	ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
274	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
275
276	status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
277						ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
278						TRUE, FALSE, &table_index);
279
280	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
281	if (ACPI_FAILURE(status)) {
282		goto unlock_and_exit;
283	}
284
285	/*
286	 * Note: Now table is "INSTALLED", it must be validated before
287	 * using.
288	 */
289	status =
290	    acpi_tb_validate_table(&acpi_gbl_root_table_list.
291				   tables[table_index]);
292	if (ACPI_FAILURE(status)) {
293		goto unlock_and_exit;
294	}
295
296	status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
297
298	/* Invoke table handler if present */
299
300	if (acpi_gbl_table_handler) {
301		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
302					     acpi_gbl_table_handler_context);
303	}
304
305unlock_and_exit:
306	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
307	return_ACPI_STATUS(status);
308}
309
310ACPI_EXPORT_SYMBOL(acpi_load_table)
311
312/*******************************************************************************
313 *
314 * FUNCTION:    acpi_unload_parent_table
315 *
316 * PARAMETERS:  object              - Handle to any namespace object owned by
317 *                                    the table to be unloaded
318 *
319 * RETURN:      Status
320 *
321 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
322 *              the table and deletes all namespace objects associated with
323 *              that table. Unloading of the DSDT is not allowed.
324 *              Note: Mainly intended to support hotplug removal of SSDTs.
325 *
326 ******************************************************************************/
327acpi_status acpi_unload_parent_table(acpi_handle object)
328{
329	struct acpi_namespace_node *node =
330	    ACPI_CAST_PTR(struct acpi_namespace_node, object);
331	acpi_status status = AE_NOT_EXIST;
332	acpi_owner_id owner_id;
333	u32 i;
334
335	ACPI_FUNCTION_TRACE(acpi_unload_parent_table);
336
337	/* Parameter validation */
338
339	if (!object) {
340		return_ACPI_STATUS(AE_BAD_PARAMETER);
341	}
342
343	/*
344	 * The node owner_id is currently the same as the parent table ID.
345	 * However, this could change in the future.
346	 */
347	owner_id = node->owner_id;
348	if (!owner_id) {
349
350		/* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */
351
352		return_ACPI_STATUS(AE_TYPE);
353	}
354
355	/* Must acquire the interpreter lock during this operation */
356
357	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
358	if (ACPI_FAILURE(status)) {
359		return_ACPI_STATUS(status);
360	}
361
362	/* Find the table in the global table list */
363
364	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
365		if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) {
366			continue;
367		}
368
369		/*
370		 * Allow unload of SSDT and OEMx tables only. Do not allow unload
371		 * of the DSDT. No other types of tables should get here, since
372		 * only these types can contain AML and thus are the only types
373		 * that can create namespace objects.
374		 */
375		if (ACPI_COMPARE_NAME
376		    (acpi_gbl_root_table_list.tables[i].signature.ascii,
377		     ACPI_SIG_DSDT)) {
378			status = AE_TYPE;
379			break;
380		}
381
382		/* Ensure the table is actually loaded */
383
384		if (!acpi_tb_is_table_loaded(i)) {
385			status = AE_NOT_EXIST;
386			break;
387		}
388
389		/* Invoke table handler if present */
390
391		if (acpi_gbl_table_handler) {
392			(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
393						     acpi_gbl_root_table_list.
394						     tables[i].pointer,
395						     acpi_gbl_table_handler_context);
396		}
397
398		/*
399		 * Delete all namespace objects owned by this table. Note that
400		 * these objects can appear anywhere in the namespace by virtue
401		 * of the AML "Scope" operator. Thus, we need to track ownership
402		 * by an ID, not simply a position within the hierarchy.
403		 */
404		status = acpi_tb_delete_namespace_by_owner(i);
405		if (ACPI_FAILURE(status)) {
406			break;
407		}
408
409		status = acpi_tb_release_owner_id(i);
410		acpi_tb_set_table_loaded_flag(i, FALSE);
411		break;
412	}
413
414	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
415	return_ACPI_STATUS(status);
416}
417
418ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)
419