Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6595 serge 1
/******************************************************************************
2
 *
3
 * Module Name: tbxfload - Table load/unload external interfaces
4
 *
5
 *****************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2015, 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 
47
#include "accommon.h"
48
#include "acnamesp.h"
49
#include "actables.h"
50
 
51
#define _COMPONENT          ACPI_TABLES
52
ACPI_MODULE_NAME("tbxfload")
53
 
54
/*******************************************************************************
55
 *
56
 * FUNCTION:    acpi_load_tables
57
 *
58
 * PARAMETERS:  None
59
 *
60
 * RETURN:      Status
61
 *
62
 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
63
 *
64
 ******************************************************************************/
65
acpi_status __init acpi_load_tables(void)
66
{
67
	acpi_status status;
68
 
69
	ACPI_FUNCTION_TRACE(acpi_load_tables);
70
 
71
	/* Load the namespace from the tables */
72
 
73
	status = acpi_tb_load_namespace();
74
 
75
	/* Don't let single failures abort the load */
76
 
77
	if (status == AE_CTRL_TERMINATE) {
78
		status = AE_OK;
79
	}
80
 
81
	if (ACPI_FAILURE(status)) {
82
		ACPI_EXCEPTION((AE_INFO, status,
83
				"While loading namespace from ACPI tables"));
84
	}
85
 
86
	return_ACPI_STATUS(status);
87
}
88
 
89
ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
90
 
91
/*******************************************************************************
92
 *
93
 * FUNCTION:    acpi_tb_load_namespace
94
 *
95
 * PARAMETERS:  None
96
 *
97
 * RETURN:      Status
98
 *
99
 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
100
 *              the RSDT/XSDT.
101
 *
102
 ******************************************************************************/
103
acpi_status acpi_tb_load_namespace(void)
104
{
105
	acpi_status status;
106
	u32 i;
107
	struct acpi_table_header *new_dsdt;
108
	struct acpi_table_desc *table;
109
	u32 tables_loaded = 0;
110
	u32 tables_failed = 0;
111
 
112
	ACPI_FUNCTION_TRACE(tb_load_namespace);
113
 
114
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
115
 
116
	/*
117
	 * Load the namespace. The DSDT is required, but any SSDT and
118
	 * PSDT tables are optional. Verify the DSDT.
119
	 */
120
	table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index];
121
 
122
	if (!acpi_gbl_root_table_list.current_table_count ||
123
	    !ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_DSDT) ||
124
	    ACPI_FAILURE(acpi_tb_validate_table(table))) {
125
		status = AE_NO_ACPI_TABLES;
126
		goto unlock_and_exit;
127
	}
128
 
129
	/*
130
	 * Save the DSDT pointer for simple access. This is the mapped memory
131
	 * address. We must take care here because the address of the .Tables
132
	 * array can change dynamically as tables are loaded at run-time. Note:
133
	 * .Pointer field is not validated until after call to acpi_tb_validate_table.
134
	 */
135
	acpi_gbl_DSDT = table->pointer;
136
 
137
	/*
138
	 * Optionally copy the entire DSDT to local memory (instead of simply
139
	 * mapping it.) There are some BIOSs that corrupt or replace the original
140
	 * DSDT, creating the need for this option. Default is FALSE, do not copy
141
	 * the DSDT.
142
	 */
143
	if (acpi_gbl_copy_dsdt_locally) {
144
		new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index);
145
		if (new_dsdt) {
146
			acpi_gbl_DSDT = new_dsdt;
147
		}
148
	}
149
 
150
	/*
151
	 * Save the original DSDT header for detection of table corruption
152
	 * and/or replacement of the DSDT from outside the OS.
153
	 */
154
	memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
155
	       sizeof(struct acpi_table_header));
156
 
157
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
158
 
159
	/* Load and parse tables */
160
 
161
	status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node);
162
	if (ACPI_FAILURE(status)) {
163
		ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
164
		tables_failed++;
165
	} else {
166
		tables_loaded++;
167
	}
168
 
169
	/* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
170
 
171
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
172
	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
173
		table = &acpi_gbl_root_table_list.tables[i];
174
 
175
		if (!acpi_gbl_root_table_list.tables[i].address ||
176
		    (!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_SSDT)
177
		     && !ACPI_COMPARE_NAME(table->signature.ascii,
178
					   ACPI_SIG_PSDT)
179
		     && !ACPI_COMPARE_NAME(table->signature.ascii,
180
					   ACPI_SIG_OSDT))
181
		    || ACPI_FAILURE(acpi_tb_validate_table(table))) {
182
			continue;
183
		}
184
 
185
		/* Ignore errors while loading tables, get as many as possible */
186
 
187
		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
188
		status = acpi_ns_load_table(i, acpi_gbl_root_node);
189
		if (ACPI_FAILURE(status)) {
190
			ACPI_EXCEPTION((AE_INFO, status,
191
					"(%4.4s:%8.8s) while loading table",
192
					table->signature.ascii,
193
					table->pointer->oem_table_id));
194
			tables_failed++;
195
 
196
			ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
197
					      "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n",
198
					      table->signature.ascii,
199
					      table->pointer->oem_table_id));
200
		} else {
201
			tables_loaded++;
202
		}
203
 
204
		(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
205
	}
206
 
207
	if (!tables_failed) {
208
		ACPI_INFO((AE_INFO,
209
			   "%u ACPI AML tables successfully acquired and loaded",
210
			   tables_loaded));
211
	} else {
212
		ACPI_ERROR((AE_INFO,
213
			    "%u table load failures, %u successful",
214
			    tables_failed, tables_loaded));
215
 
216
		/* Indicate at least one failure */
217
 
218
		status = AE_CTRL_TERMINATE;
219
	}
220
 
221
unlock_and_exit:
222
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
223
	return_ACPI_STATUS(status);
224
}
225
 
226
/*******************************************************************************
227
 *
228
 * FUNCTION:    acpi_install_table
229
 *
230
 * PARAMETERS:  address             - Address of the ACPI table to be installed.
231
 *              physical            - Whether the address is a physical table
232
 *                                    address or not
233
 *
234
 * RETURN:      Status
235
 *
236
 * DESCRIPTION: Dynamically install an ACPI table.
237
 *              Note: This function should only be invoked after
238
 *                    acpi_initialize_tables() and before acpi_load_tables().
239
 *
240
 ******************************************************************************/
241
 
242
acpi_status __init
243
acpi_install_table(acpi_physical_address address, u8 physical)
244
{
245
	acpi_status status;
246
	u8 flags;
247
	u32 table_index;
248
 
249
	ACPI_FUNCTION_TRACE(acpi_install_table);
250
 
251
	if (physical) {
252
		flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
253
	} else {
254
		flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
255
	}
256
 
257
	status = acpi_tb_install_standard_table(address, flags,
258
						FALSE, FALSE, &table_index);
259
 
260
	return_ACPI_STATUS(status);
261
}
262
 
263
ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
264
 
265
/*******************************************************************************
266
 *
267
 * FUNCTION:    acpi_load_table
268
 *
269
 * PARAMETERS:  table               - Pointer to a buffer containing the ACPI
270
 *                                    table to be loaded.
271
 *
272
 * RETURN:      Status
273
 *
274
 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
275
 *              be a valid ACPI table with a valid ACPI table header.
276
 *              Note1: Mainly intended to support hotplug addition of SSDTs.
277
 *              Note2: Does not copy the incoming table. User is responsible
278
 *              to ensure that the table is not deleted or unmapped.
279
 *
280
 ******************************************************************************/
281
acpi_status acpi_load_table(struct acpi_table_header *table)
282
{
283
	acpi_status status;
284
	u32 table_index;
285
 
286
	ACPI_FUNCTION_TRACE(acpi_load_table);
287
 
288
	/* Parameter validation */
289
 
290
	if (!table) {
291
		return_ACPI_STATUS(AE_BAD_PARAMETER);
292
	}
293
 
294
	/* Must acquire the interpreter lock during this operation */
295
 
296
	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
297
	if (ACPI_FAILURE(status)) {
298
		return_ACPI_STATUS(status);
299
	}
300
 
301
	/* Install the table and load it into the namespace */
302
 
303
	ACPI_INFO((AE_INFO, "Host-directed Dynamic ACPI Table Load:"));
304
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
305
 
306
	status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
307
						ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
308
						TRUE, FALSE, &table_index);
309
 
310
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
311
	if (ACPI_FAILURE(status)) {
312
		goto unlock_and_exit;
313
	}
314
 
315
	/*
316
	 * Note: Now table is "INSTALLED", it must be validated before
317
	 * using.
318
	 */
319
	status =
320
	    acpi_tb_validate_table(&acpi_gbl_root_table_list.
321
				   tables[table_index]);
322
	if (ACPI_FAILURE(status)) {
323
		goto unlock_and_exit;
324
	}
325
 
326
	status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
327
 
328
	/* Invoke table handler if present */
329
 
330
	if (acpi_gbl_table_handler) {
331
		(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
332
					     acpi_gbl_table_handler_context);
333
	}
334
 
335
unlock_and_exit:
336
	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
337
	return_ACPI_STATUS(status);
338
}
339
 
340
ACPI_EXPORT_SYMBOL(acpi_load_table)
341
 
342
/*******************************************************************************
343
 *
344
 * FUNCTION:    acpi_unload_parent_table
345
 *
346
 * PARAMETERS:  object              - Handle to any namespace object owned by
347
 *                                    the table to be unloaded
348
 *
349
 * RETURN:      Status
350
 *
351
 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
352
 *              the table and deletes all namespace objects associated with
353
 *              that table. Unloading of the DSDT is not allowed.
354
 *              Note: Mainly intended to support hotplug removal of SSDTs.
355
 *
356
 ******************************************************************************/
357
acpi_status acpi_unload_parent_table(acpi_handle object)
358
{
359
	struct acpi_namespace_node *node =
360
	    ACPI_CAST_PTR(struct acpi_namespace_node, object);
361
	acpi_status status = AE_NOT_EXIST;
362
	acpi_owner_id owner_id;
363
	u32 i;
364
 
365
	ACPI_FUNCTION_TRACE(acpi_unload_parent_table);
366
 
367
	/* Parameter validation */
368
 
369
	if (!object) {
370
		return_ACPI_STATUS(AE_BAD_PARAMETER);
371
	}
372
 
373
	/*
374
	 * The node owner_id is currently the same as the parent table ID.
375
	 * However, this could change in the future.
376
	 */
377
	owner_id = node->owner_id;
378
	if (!owner_id) {
379
 
380
		/* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */
381
 
382
		return_ACPI_STATUS(AE_TYPE);
383
	}
384
 
385
	/* Must acquire the interpreter lock during this operation */
386
 
387
	status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
388
	if (ACPI_FAILURE(status)) {
389
		return_ACPI_STATUS(status);
390
	}
391
 
392
	/* Find the table in the global table list */
393
 
394
	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
395
		if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) {
396
			continue;
397
		}
398
 
399
		/*
400
		 * Allow unload of SSDT and OEMx tables only. Do not allow unload
401
		 * of the DSDT. No other types of tables should get here, since
402
		 * only these types can contain AML and thus are the only types
403
		 * that can create namespace objects.
404
		 */
405
		if (ACPI_COMPARE_NAME
406
		    (acpi_gbl_root_table_list.tables[i].signature.ascii,
407
		     ACPI_SIG_DSDT)) {
408
			status = AE_TYPE;
409
			break;
410
		}
411
 
412
		/* Ensure the table is actually loaded */
413
 
414
		if (!acpi_tb_is_table_loaded(i)) {
415
			status = AE_NOT_EXIST;
416
			break;
417
		}
418
 
419
		/* Invoke table handler if present */
420
 
421
		if (acpi_gbl_table_handler) {
422
			(void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
423
						     acpi_gbl_root_table_list.
424
						     tables[i].pointer,
425
						     acpi_gbl_table_handler_context);
426
		}
427
 
428
		/*
429
		 * Delete all namespace objects owned by this table. Note that
430
		 * these objects can appear anywhere in the namespace by virtue
431
		 * of the AML "Scope" operator. Thus, we need to track ownership
432
		 * by an ID, not simply a position within the hierarchy.
433
		 */
434
		status = acpi_tb_delete_namespace_by_owner(i);
435
		if (ACPI_FAILURE(status)) {
436
			break;
437
		}
438
 
439
		status = acpi_tb_release_owner_id(i);
440
		acpi_tb_set_table_loaded_flag(i, FALSE);
441
		break;
442
	}
443
 
444
	(void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
445
	return_ACPI_STATUS(status);
446
}
447
 
448
ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)