tbxface.c 12.8 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8
/******************************************************************************
 *
 * Module Name: tbxface - Public interfaces to the ACPI subsystem
 *                         ACPI table oriented interfaces
 *
 *****************************************************************************/

/*
9
 * Copyright (C) 2000 - 2004, R. Byron Moore
10
 * All rights reserved.
Linus Torvalds's avatar
Linus Torvalds committed
11
 *
12 13 14 15 16 17 18 19 20 21 22 23 24 25
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
Linus Torvalds's avatar
Linus Torvalds committed
26
 *
27 28 29
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
Linus Torvalds's avatar
Linus Torvalds committed
30
 *
31 32 33 34 35 36 37 38 39 40 41 42
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
Linus Torvalds's avatar
Linus Torvalds committed
43 44
 */

Len Brown's avatar
Len Brown committed
45
#include <linux/module.h>
Linus Torvalds's avatar
Linus Torvalds committed
46

47 48 49
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/actables.h>
Linus Torvalds's avatar
Linus Torvalds committed
50 51


Linus Torvalds's avatar
Linus Torvalds committed
52
#define _COMPONENT          ACPI_TABLES
Andy Grover's avatar
Andy Grover committed
53
	 ACPI_MODULE_NAME    ("tbxface")
Linus Torvalds's avatar
Linus Torvalds committed
54 55 56 57


/*******************************************************************************
 *
58
 * FUNCTION:    acpi_load_tables
Linus Torvalds's avatar
Linus Torvalds committed
59 60 61 62 63 64 65 66 67 68
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to load the ACPI tables from the
 *              provided RSDT
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
69 70
acpi_status
acpi_load_tables (void)
Linus Torvalds's avatar
Linus Torvalds committed
71
{
72 73
	struct acpi_pointer             rsdp_address;
	acpi_status                     status;
Linus Torvalds's avatar
Linus Torvalds committed
74 75


76
	ACPI_FUNCTION_TRACE ("acpi_load_tables");
Linus Torvalds's avatar
Linus Torvalds committed
77 78 79 80 81


	/* Get the RSDP */

	status = acpi_os_get_root_pointer (ACPI_LOGICAL_ADDRESSING,
Andy Grover's avatar
Andy Grover committed
82
			  &rsdp_address);
Linus Torvalds's avatar
Linus Torvalds committed
83
	if (ACPI_FAILURE (status)) {
84
		ACPI_REPORT_ERROR (("acpi_load_tables: Could not get RSDP, %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
85 86
				  acpi_format_exception (status)));
		goto error_exit;
Linus Torvalds's avatar
Linus Torvalds committed
87 88
	}

Linus Torvalds's avatar
Linus Torvalds committed
89 90
	/* Map and validate the RSDP */

Andy Grover's avatar
Andy Grover committed
91 92 93
	acpi_gbl_table_flags = rsdp_address.pointer_type;

	status = acpi_tb_verify_rsdp (&rsdp_address);
Linus Torvalds's avatar
Linus Torvalds committed
94
	if (ACPI_FAILURE (status)) {
95
		ACPI_REPORT_ERROR (("acpi_load_tables: RSDP Failed validation: %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
96
				  acpi_format_exception (status)));
Linus Torvalds's avatar
Linus Torvalds committed
97 98 99 100 101
		goto error_exit;
	}

	/* Get the RSDT via the RSDP */

Andy Grover's avatar
Andy Grover committed
102
	status = acpi_tb_get_table_rsdt ();
Linus Torvalds's avatar
Linus Torvalds committed
103
	if (ACPI_FAILURE (status)) {
104
		ACPI_REPORT_ERROR (("acpi_load_tables: Could not load RSDT: %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
105
				  acpi_format_exception (status)));
Linus Torvalds's avatar
Linus Torvalds committed
106 107 108
		goto error_exit;
	}

Andy Grover's avatar
Andy Grover committed
109
	/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */
Linus Torvalds's avatar
Linus Torvalds committed
110

Andy Grover's avatar
Andy Grover committed
111
	status = acpi_tb_get_required_tables ();
Linus Torvalds's avatar
Linus Torvalds committed
112
	if (ACPI_FAILURE (status)) {
113
		ACPI_REPORT_ERROR (("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
114
				  acpi_format_exception (status)));
Linus Torvalds's avatar
Linus Torvalds committed
115 116 117
		goto error_exit;
	}

118
	ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
Linus Torvalds's avatar
Linus Torvalds committed
119

Linus Torvalds's avatar
Linus Torvalds committed
120 121 122 123 124

	/* Load the namespace from the tables */

	status = acpi_ns_load_namespace ();
	if (ACPI_FAILURE (status)) {
125
		ACPI_REPORT_ERROR (("acpi_load_tables: Could not load namespace: %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
126
				  acpi_format_exception (status)));
Linus Torvalds's avatar
Linus Torvalds committed
127 128 129
		goto error_exit;
	}

Linus Torvalds's avatar
Linus Torvalds committed
130
	return_ACPI_STATUS (AE_OK);
Linus Torvalds's avatar
Linus Torvalds committed
131 132 133


error_exit:
134
	ACPI_REPORT_ERROR (("acpi_load_tables: Could not load tables: %s\n",
Linus Torvalds's avatar
Linus Torvalds committed
135
			  acpi_format_exception (status)));
Linus Torvalds's avatar
Linus Torvalds committed
136

Linus Torvalds's avatar
Linus Torvalds committed
137
	return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
138 139 140
}


141 142
#ifdef ACPI_FUTURE_USAGE

Linus Torvalds's avatar
Linus Torvalds committed
143 144
/*******************************************************************************
 *
145
 * FUNCTION:    acpi_load_table
Linus Torvalds's avatar
Linus Torvalds committed
146
 *
147
 * PARAMETERS:  table_ptr       - pointer to a buffer containing the entire
Linus Torvalds's avatar
Linus Torvalds committed
148 149 150 151 152 153 154 155 156 157 158
 *                                table to be loaded
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to load a table from the caller's
 *              buffer.  The buffer must contain an entire ACPI Table including
 *              a valid header.  The header fields will be verified, and if it
 *              is determined that the table is invalid, the call will fail.
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
159
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
160
acpi_load_table (
161
	struct acpi_table_header        *table_ptr)
Linus Torvalds's avatar
Linus Torvalds committed
162
{
163 164 165
	acpi_status                     status;
	struct acpi_table_desc          table_info;
	struct acpi_pointer             address;
Linus Torvalds's avatar
Linus Torvalds committed
166 167


168
	ACPI_FUNCTION_TRACE ("acpi_load_table");
Linus Torvalds's avatar
Linus Torvalds committed
169 170 171


	if (!table_ptr) {
Linus Torvalds's avatar
Linus Torvalds committed
172
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
173 174 175 176
	}

	/* Copy the table to a local buffer */

Andy Grover's avatar
Andy Grover committed
177
	address.pointer_type    = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
Andy Grover's avatar
Andy Grover committed
178 179
	address.pointer.logical = table_ptr;

Andy Grover's avatar
Andy Grover committed
180
	status = acpi_tb_get_table_body (&address, table_ptr, &table_info);
Linus Torvalds's avatar
Linus Torvalds committed
181
	if (ACPI_FAILURE (status)) {
Linus Torvalds's avatar
Linus Torvalds committed
182
		return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
183 184 185 186
	}

	/* Install the new table into the local data structures */

187
	status = acpi_tb_install_table (&table_info);
Linus Torvalds's avatar
Linus Torvalds committed
188
	if (ACPI_FAILURE (status)) {
189
		/* Free table allocated by acpi_tb_get_table_body */
Linus Torvalds's avatar
Linus Torvalds committed
190 191

		acpi_tb_delete_single_table (&table_info);
Linus Torvalds's avatar
Linus Torvalds committed
192
		return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
193 194
	}

Andy Grover's avatar
Andy Grover committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	/* Convert the table to common format if necessary */

	switch (table_info.type) {
	case ACPI_TABLE_FADT:

		status = acpi_tb_convert_table_fadt ();
		break;

	case ACPI_TABLE_FACS:

		status = acpi_tb_build_common_facs (&table_info);
		break;

	default:
		/* Load table into namespace if it contains executable AML */

		status = acpi_ns_load_table (table_info.installed_desc, acpi_gbl_root_node);
		break;
	}
Linus Torvalds's avatar
Linus Torvalds committed
214 215 216 217

	if (ACPI_FAILURE (status)) {
		/* Uninstall table and free the buffer */

218
		(void) acpi_tb_uninstall_table (table_info.installed_desc);
Linus Torvalds's avatar
Linus Torvalds committed
219 220
	}

Linus Torvalds's avatar
Linus Torvalds committed
221
	return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
222 223 224 225 226
}


/*******************************************************************************
 *
227
 * FUNCTION:    acpi_unload_table
Linus Torvalds's avatar
Linus Torvalds committed
228
 *
229
 * PARAMETERS:  table_type    - Type of table to be unloaded
Linus Torvalds's avatar
Linus Torvalds committed
230 231 232 233 234 235 236
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This routine is used to force the unload of a table
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
237
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
238
acpi_unload_table (
239
	acpi_table_type                 table_type)
Linus Torvalds's avatar
Linus Torvalds committed
240
{
241
	struct acpi_table_desc          *table_desc;
Linus Torvalds's avatar
Linus Torvalds committed
242 243


244
	ACPI_FUNCTION_TRACE ("acpi_unload_table");
Linus Torvalds's avatar
Linus Torvalds committed
245

Linus Torvalds's avatar
Linus Torvalds committed
246 247 248 249

	/* Parameter validation */

	if (table_type > ACPI_TABLE_MAX) {
Linus Torvalds's avatar
Linus Torvalds committed
250
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
251 252 253 254 255
	}


	/* Find all tables of the requested type */

256
	table_desc = acpi_gbl_table_lists[table_type].next;
257
	while (table_desc) {
Linus Torvalds's avatar
Linus Torvalds committed
258 259 260 261 262 263
		/*
		 * Delete all namespace entries owned by this table.  Note that these
		 * entries can appear anywhere in the namespace by virtue of the AML
		 * "Scope" operator.  Thus, we need to track ownership by an ID, not
		 * simply a position within the hierarchy
		 */
264
		acpi_ns_delete_namespace_by_owner (table_desc->table_id);
Linus Torvalds's avatar
Linus Torvalds committed
265

266 267
		table_desc = table_desc->next;
	}
Linus Torvalds's avatar
Linus Torvalds committed
268

269
	/* Delete (or unmap) all tables of this type */
Linus Torvalds's avatar
Linus Torvalds committed
270

271
	acpi_tb_delete_tables_by_type (table_type);
Linus Torvalds's avatar
Linus Torvalds committed
272
	return_ACPI_STATUS (AE_OK);
Linus Torvalds's avatar
Linus Torvalds committed
273 274 275 276 277
}


/*******************************************************************************
 *
278
 * FUNCTION:    acpi_get_table_header
Linus Torvalds's avatar
Linus Torvalds committed
279
 *
280
 * PARAMETERS:  table_type      - one of the defined table types
Linus Torvalds's avatar
Linus Torvalds committed
281 282
 *              Instance        - the non zero instance of the table, allows
 *                                support for multiple tables of the same type
283
 *                                see acpi_gbl_acpi_table_flag
284
 *              out_table_header - pointer to the struct acpi_table_header if successful
Linus Torvalds's avatar
Linus Torvalds committed
285 286 287
 *
 * DESCRIPTION: This function is called to get an ACPI table header.  The caller
 *              supplies an pointer to a data area sufficient to contain an ACPI
288
 *              struct acpi_table_header structure.
Linus Torvalds's avatar
Linus Torvalds committed
289 290 291 292 293 294 295 296
 *
 *              The header contains a length field that can be used to determine
 *              the size of the buffer needed to contain the entire table.  This
 *              function is not valid for the RSD PTR table since it does not
 *              have a standard header and is fixed length.
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
297
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
298
acpi_get_table_header (
299 300 301
	acpi_table_type                 table_type,
	u32                             instance,
	struct acpi_table_header        *out_table_header)
Linus Torvalds's avatar
Linus Torvalds committed
302
{
303 304
	struct acpi_table_header        *tbl_ptr;
	acpi_status                     status;
Linus Torvalds's avatar
Linus Torvalds committed
305 306


307
	ACPI_FUNCTION_TRACE ("acpi_get_table_header");
Linus Torvalds's avatar
Linus Torvalds committed
308 309 310 311


	if ((instance == 0)                 ||
		(table_type == ACPI_TABLE_RSDP) ||
Linus Torvalds's avatar
Linus Torvalds committed
312
		(!out_table_header)) {
Linus Torvalds's avatar
Linus Torvalds committed
313
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
314 315 316 317 318
	}

	/* Check the table type and instance */

	if ((table_type > ACPI_TABLE_MAX)   ||
319
		(ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
Linus Torvalds's avatar
Linus Torvalds committed
320
		 instance > 1)) {
Linus Torvalds's avatar
Linus Torvalds committed
321
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
322 323 324 325 326 327 328
	}


	/* Get a pointer to the entire table */

	status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
	if (ACPI_FAILURE (status)) {
Linus Torvalds's avatar
Linus Torvalds committed
329
		return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
330 331 332 333 334 335
	}

	/*
	 * The function will return a NULL pointer if the table is not loaded
	 */
	if (tbl_ptr == NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
336
		return_ACPI_STATUS (AE_NOT_EXIST);
Linus Torvalds's avatar
Linus Torvalds committed
337 338 339 340 341
	}

	/*
	 * Copy the header to the caller's buffer
	 */
Andy Grover's avatar
Andy Grover committed
342
	ACPI_MEMCPY ((void *) out_table_header, (void *) tbl_ptr,
343
			 sizeof (struct acpi_table_header));
Linus Torvalds's avatar
Linus Torvalds committed
344

Linus Torvalds's avatar
Linus Torvalds committed
345
	return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
346 347 348
}


349 350
#endif  /*  ACPI_FUTURE_USAGE  */

Linus Torvalds's avatar
Linus Torvalds committed
351 352
/*******************************************************************************
 *
353
 * FUNCTION:    acpi_get_table
Linus Torvalds's avatar
Linus Torvalds committed
354
 *
355
 * PARAMETERS:  table_type      - one of the defined table types
Linus Torvalds's avatar
Linus Torvalds committed
356 357
 *              Instance        - the non zero instance of the table, allows
 *                                support for multiple tables of the same type
358 359
 *                                see acpi_gbl_acpi_table_flag
 *              ret_buffer      - pointer to a structure containing a buffer to
Linus Torvalds's avatar
Linus Torvalds committed
360 361 362 363 364
 *                                receive the table
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to get an ACPI table.  The caller
365 366
 *              supplies an out_buffer large enough to contain the entire ACPI
 *              table.  The caller should call the acpi_get_table_header function
Linus Torvalds's avatar
Linus Torvalds committed
367
 *              first to determine the buffer size needed.  Upon completion
368 369
 *              the out_buffer->Length field will indicate the number of bytes
 *              copied into the out_buffer->buf_ptr buffer. This table will be
Linus Torvalds's avatar
Linus Torvalds committed
370 371 372 373
 *              a complete table including the header.
 *
 ******************************************************************************/

Linus Torvalds's avatar
Linus Torvalds committed
374
acpi_status
Linus Torvalds's avatar
Linus Torvalds committed
375
acpi_get_table (
376 377 378
	acpi_table_type                 table_type,
	u32                             instance,
	struct acpi_buffer              *ret_buffer)
Linus Torvalds's avatar
Linus Torvalds committed
379
{
380 381 382
	struct acpi_table_header        *tbl_ptr;
	acpi_status                     status;
	acpi_size                       table_length;
Linus Torvalds's avatar
Linus Torvalds committed
383 384


385
	ACPI_FUNCTION_TRACE ("acpi_get_table");
Linus Torvalds's avatar
Linus Torvalds committed
386 387


Andy Grover's avatar
Andy Grover committed
388 389 390
	/* Parameter validation */

	if (instance == 0) {
Linus Torvalds's avatar
Linus Torvalds committed
391
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
392 393
	}

Andy Grover's avatar
Andy Grover committed
394 395 396 397 398
	status = acpi_ut_validate_buffer (ret_buffer);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}

Linus Torvalds's avatar
Linus Torvalds committed
399 400 401
	/* Check the table type and instance */

	if ((table_type > ACPI_TABLE_MAX)   ||
402
		(ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
Linus Torvalds's avatar
Linus Torvalds committed
403
		 instance > 1)) {
Linus Torvalds's avatar
Linus Torvalds committed
404
		return_ACPI_STATUS (AE_BAD_PARAMETER);
Linus Torvalds's avatar
Linus Torvalds committed
405 406 407 408 409 410 411
	}


	/* Get a pointer to the entire table */

	status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
	if (ACPI_FAILURE (status)) {
Linus Torvalds's avatar
Linus Torvalds committed
412
		return_ACPI_STATUS (status);
Linus Torvalds's avatar
Linus Torvalds committed
413 414 415
	}

	/*
416
	 * acpi_tb_get_table_ptr will return a NULL pointer if the
Linus Torvalds's avatar
Linus Torvalds committed
417
	 * table is not loaded.
Linus Torvalds's avatar
Linus Torvalds committed
418 419
	 */
	if (tbl_ptr == NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
420
		return_ACPI_STATUS (AE_NOT_EXIST);
Linus Torvalds's avatar
Linus Torvalds committed
421 422
	}

Andy Grover's avatar
Andy Grover committed
423 424
	/* Get the table length */

Linus Torvalds's avatar
Linus Torvalds committed
425 426 427 428
	if (table_type == ACPI_TABLE_RSDP) {
		/*
		 *  RSD PTR is the only "table" without a header
		 */
429
		table_length = sizeof (struct rsdp_descriptor);
Linus Torvalds's avatar
Linus Torvalds committed
430 431
	}
	else {
432
		table_length = (acpi_size) tbl_ptr->length;
Linus Torvalds's avatar
Linus Torvalds committed
433 434
	}

Andy Grover's avatar
Andy Grover committed
435
	/* Validate/Allocate/Clear caller buffer */
Linus Torvalds's avatar
Linus Torvalds committed
436

Andy Grover's avatar
Andy Grover committed
437 438 439 440
	status = acpi_ut_initialize_buffer (ret_buffer, table_length);
	if (ACPI_FAILURE (status)) {
		return_ACPI_STATUS (status);
	}
Linus Torvalds's avatar
Linus Torvalds committed
441

Andy Grover's avatar
Andy Grover committed
442
	/* Copy the table to the buffer */
Linus Torvalds's avatar
Linus Torvalds committed
443

Andy Grover's avatar
Andy Grover committed
444
	ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length);
Linus Torvalds's avatar
Linus Torvalds committed
445
	return_ACPI_STATUS (AE_OK);
Linus Torvalds's avatar
Linus Torvalds committed
446
}
Len Brown's avatar
Len Brown committed
447
EXPORT_SYMBOL(acpi_get_table);
Linus Torvalds's avatar
Linus Torvalds committed
448