tbxface.c 12.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8
/******************************************************************************
 *
 * Module Name: tbxface - Public interfaces to the ACPI subsystem
 *                         ACPI table oriented interfaces
 *
 *****************************************************************************/

/*
B
Bob Moore 已提交
9
 * Copyright (C) 2000 - 2006, R. Byron Moore
L
Linus Torvalds 已提交
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
 * All rights reserved.
 *
 * 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.
 *
 * 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.
 *
 * 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.
 */

#include <linux/module.h>

#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/actables.h>

#define _COMPONENT          ACPI_TABLES
L
Len Brown 已提交
52
ACPI_MODULE_NAME("tbxface")
L
Linus Torvalds 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65

/*******************************************************************************
 *
 * FUNCTION:    acpi_load_tables
 *
 * PARAMETERS:  None
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to load the ACPI tables from the
 *              provided RSDT
 *
 ******************************************************************************/
L
Len Brown 已提交
66
acpi_status acpi_load_tables(void)
L
Linus Torvalds 已提交
67
{
L
Len Brown 已提交
68 69
	struct acpi_pointer rsdp_address;
	acpi_status status;
L
Linus Torvalds 已提交
70

L
Len Brown 已提交
71
	ACPI_FUNCTION_TRACE("acpi_load_tables");
L
Linus Torvalds 已提交
72 73 74

	/* Get the RSDP */

L
Len Brown 已提交
75 76 77
	status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
					  &rsdp_address);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
78
		ACPI_EXCEPTION((AE_INFO, status, "Could not get the RSDP"));
L
Linus Torvalds 已提交
79 80 81 82 83 84 85
		goto error_exit;
	}

	/* Map and validate the RSDP */

	acpi_gbl_table_flags = rsdp_address.pointer_type;

L
Len Brown 已提交
86 87
	status = acpi_tb_verify_rsdp(&rsdp_address);
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
88
		ACPI_EXCEPTION((AE_INFO, status, "During RSDP validation"));
L
Linus Torvalds 已提交
89 90 91 92 93
		goto error_exit;
	}

	/* Get the RSDT via the RSDP */

L
Len Brown 已提交
94 95
	status = acpi_tb_get_table_rsdt();
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
96
		ACPI_EXCEPTION((AE_INFO, status, "Could not load RSDT"));
L
Linus Torvalds 已提交
97 98 99 100 101
		goto error_exit;
	}

	/* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */

L
Len Brown 已提交
102 103
	status = acpi_tb_get_required_tables();
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
104 105
		ACPI_EXCEPTION((AE_INFO, status,
				"Could not get all required tables (DSDT/FADT/FACS)"));
L
Linus Torvalds 已提交
106 107 108
		goto error_exit;
	}

L
Len Brown 已提交
109
	ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
L
Linus Torvalds 已提交
110 111 112

	/* Load the namespace from the tables */

L
Len Brown 已提交
113 114
	status = acpi_ns_load_namespace();
	if (ACPI_FAILURE(status)) {
B
Bob Moore 已提交
115
		ACPI_EXCEPTION((AE_INFO, status, "Could not load namespace"));
L
Linus Torvalds 已提交
116 117 118
		goto error_exit;
	}

L
Len Brown 已提交
119
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
120

L
Len Brown 已提交
121
      error_exit:
B
Bob Moore 已提交
122
	ACPI_EXCEPTION((AE_INFO, status, "Could not load tables"));
L
Len Brown 已提交
123
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
}

#ifdef ACPI_FUTURE_USAGE
/*******************************************************************************
 *
 * FUNCTION:    acpi_load_table
 *
 * PARAMETERS:  table_ptr       - pointer to a buffer containing the entire
 *                                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.
 *
 ******************************************************************************/

L
Len Brown 已提交
143
acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
L
Linus Torvalds 已提交
144
{
L
Len Brown 已提交
145 146 147
	acpi_status status;
	struct acpi_table_desc table_info;
	struct acpi_pointer address;
L
Linus Torvalds 已提交
148

L
Len Brown 已提交
149
	ACPI_FUNCTION_TRACE("acpi_load_table");
L
Linus Torvalds 已提交
150 151

	if (!table_ptr) {
L
Len Brown 已提交
152
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
153 154 155 156
	}

	/* Copy the table to a local buffer */

L
Len Brown 已提交
157
	address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
L
Linus Torvalds 已提交
158 159
	address.pointer.logical = table_ptr;

L
Len Brown 已提交
160 161 162
	status = acpi_tb_get_table_body(&address, table_ptr, &table_info);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
163 164
	}

165 166
	/* Check signature for a valid table type */

L
Len Brown 已提交
167 168 169
	status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
170 171
	}

L
Linus Torvalds 已提交
172 173
	/* Install the new table into the local data structures */

L
Len Brown 已提交
174 175
	status = acpi_tb_install_table(&table_info);
	if (ACPI_FAILURE(status)) {
176 177 178 179 180 181
		if (status == AE_ALREADY_EXISTS) {
			/* Table already exists, no error */

			status = AE_OK;
		}

L
Linus Torvalds 已提交
182 183
		/* Free table allocated by acpi_tb_get_table_body */

L
Len Brown 已提交
184 185
		acpi_tb_delete_single_table(&table_info);
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
186 187 188 189 190 191 192
	}

	/* Convert the table to common format if necessary */

	switch (table_info.type) {
	case ACPI_TABLE_FADT:

L
Len Brown 已提交
193
		status = acpi_tb_convert_table_fadt();
L
Linus Torvalds 已提交
194 195 196 197
		break;

	case ACPI_TABLE_FACS:

L
Len Brown 已提交
198
		status = acpi_tb_build_common_facs(&table_info);
L
Linus Torvalds 已提交
199 200 201 202 203
		break;

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

L
Len Brown 已提交
204 205 206
		status =
		    acpi_ns_load_table(table_info.installed_desc,
				       acpi_gbl_root_node);
L
Linus Torvalds 已提交
207 208 209
		break;
	}

L
Len Brown 已提交
210
	if (ACPI_FAILURE(status)) {
L
Linus Torvalds 已提交
211 212
		/* Uninstall table and free the buffer */

L
Len Brown 已提交
213
		(void)acpi_tb_uninstall_table(table_info.installed_desc);
L
Linus Torvalds 已提交
214 215
	}

L
Len Brown 已提交
216
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
217 218 219 220 221 222 223 224 225 226 227 228 229 230
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_unload_table
 *
 * PARAMETERS:  table_type    - Type of table to be unloaded
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This routine is used to force the unload of a table
 *
 ******************************************************************************/

L
Len Brown 已提交
231
acpi_status acpi_unload_table(acpi_table_type table_type)
L
Linus Torvalds 已提交
232
{
L
Len Brown 已提交
233
	struct acpi_table_desc *table_desc;
L
Linus Torvalds 已提交
234

L
Len Brown 已提交
235
	ACPI_FUNCTION_TRACE("acpi_unload_table");
L
Linus Torvalds 已提交
236 237 238 239

	/* Parameter validation */

	if (table_type > ACPI_TABLE_MAX) {
L
Len Brown 已提交
240
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
241 242 243 244 245 246 247 248 249 250 251 252
	}

	/* Find all tables of the requested type */

	table_desc = acpi_gbl_table_lists[table_type].next;
	while (table_desc) {
		/*
		 * 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
		 */
L
Len Brown 已提交
253 254
		acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
		acpi_ut_release_owner_id(&table_desc->owner_id);
L
Linus Torvalds 已提交
255 256 257 258 259
		table_desc = table_desc->next;
	}

	/* Delete (or unmap) all tables of this type */

L
Len Brown 已提交
260 261
	acpi_tb_delete_tables_by_type(table_type);
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_get_table_header
 *
 * PARAMETERS:  table_type      - one of the defined table types
 *              Instance        - the non zero instance of the table, allows
 *                                support for multiple tables of the same type
 *                                see acpi_gbl_acpi_table_flag
 *              out_table_header - pointer to the struct acpi_table_header if successful
 *
 * 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
 *              struct acpi_table_header structure.
 *
 *              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.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
286 287
acpi_get_table_header(acpi_table_type table_type,
		      u32 instance, struct acpi_table_header *out_table_header)
L
Linus Torvalds 已提交
288
{
L
Len Brown 已提交
289 290
	struct acpi_table_header *tbl_ptr;
	acpi_status status;
L
Linus Torvalds 已提交
291

L
Len Brown 已提交
292
	ACPI_FUNCTION_TRACE("acpi_get_table_header");
L
Linus Torvalds 已提交
293

L
Len Brown 已提交
294 295 296
	if ((instance == 0) ||
	    (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
297 298 299 300
	}

	/* Check the table type and instance */

L
Len Brown 已提交
301 302 303 304
	if ((table_type > ACPI_TABLE_MAX) ||
	    (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
	     instance > 1)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
305 306 307 308
	}

	/* Get a pointer to the entire table */

L
Len Brown 已提交
309 310 311
	status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
312 313
	}

R
Robert Moore 已提交
314 315
	/* The function will return a NULL pointer if the table is not loaded */

L
Linus Torvalds 已提交
316
	if (tbl_ptr == NULL) {
L
Len Brown 已提交
317
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
318 319
	}

R
Robert Moore 已提交
320 321
	/* Copy the header to the caller's buffer */

L
Len Brown 已提交
322 323
	ACPI_MEMCPY((void *)out_table_header, (void *)tbl_ptr,
		    sizeof(struct acpi_table_header));
L
Linus Torvalds 已提交
324

L
Len Brown 已提交
325
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
326 327
}

L
Len Brown 已提交
328
#endif				/*  ACPI_FUTURE_USAGE  */
L
Linus Torvalds 已提交
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353

/*******************************************************************************
 *
 * FUNCTION:    acpi_get_table
 *
 * PARAMETERS:  table_type      - one of the defined table types
 *              Instance        - the non zero instance of the table, allows
 *                                support for multiple tables of the same type
 *                                see acpi_gbl_acpi_table_flag
 *              ret_buffer      - pointer to a structure containing a buffer to
 *                                receive the table
 *
 * RETURN:      Status
 *
 * DESCRIPTION: This function is called to get an ACPI table.  The caller
 *              supplies an out_buffer large enough to contain the entire ACPI
 *              table.  The caller should call the acpi_get_table_header function
 *              first to determine the buffer size needed.  Upon completion
 *              the out_buffer->Length field will indicate the number of bytes
 *              copied into the out_buffer->buf_ptr buffer. This table will be
 *              a complete table including the header.
 *
 ******************************************************************************/

acpi_status
L
Len Brown 已提交
354 355
acpi_get_table(acpi_table_type table_type,
	       u32 instance, struct acpi_buffer *ret_buffer)
L
Linus Torvalds 已提交
356
{
L
Len Brown 已提交
357 358 359
	struct acpi_table_header *tbl_ptr;
	acpi_status status;
	acpi_size table_length;
L
Linus Torvalds 已提交
360

L
Len Brown 已提交
361
	ACPI_FUNCTION_TRACE("acpi_get_table");
L
Linus Torvalds 已提交
362 363 364 365

	/* Parameter validation */

	if (instance == 0) {
L
Len Brown 已提交
366
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
367 368
	}

L
Len Brown 已提交
369 370 371
	status = acpi_ut_validate_buffer(ret_buffer);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
372 373 374 375
	}

	/* Check the table type and instance */

L
Len Brown 已提交
376 377 378 379
	if ((table_type > ACPI_TABLE_MAX) ||
	    (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
	     instance > 1)) {
		return_ACPI_STATUS(AE_BAD_PARAMETER);
L
Linus Torvalds 已提交
380 381 382 383
	}

	/* Get a pointer to the entire table */

L
Len Brown 已提交
384 385 386
	status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
387 388 389 390 391 392 393
	}

	/*
	 * acpi_tb_get_table_ptr will return a NULL pointer if the
	 * table is not loaded.
	 */
	if (tbl_ptr == NULL) {
L
Len Brown 已提交
394
		return_ACPI_STATUS(AE_NOT_EXIST);
L
Linus Torvalds 已提交
395 396 397 398 399
	}

	/* Get the table length */

	if (table_type == ACPI_TABLE_RSDP) {
R
Robert Moore 已提交
400 401
		/* RSD PTR is the only "table" without a header */

L
Len Brown 已提交
402 403
		table_length = sizeof(struct rsdp_descriptor);
	} else {
L
Linus Torvalds 已提交
404 405 406 407 408
		table_length = (acpi_size) tbl_ptr->length;
	}

	/* Validate/Allocate/Clear caller buffer */

L
Len Brown 已提交
409 410 411
	status = acpi_ut_initialize_buffer(ret_buffer, table_length);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
412 413 414 415
	}

	/* Copy the table to the buffer */

L
Len Brown 已提交
416 417
	ACPI_MEMCPY((void *)ret_buffer->pointer, (void *)tbl_ptr, table_length);
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
418 419
}

L
Len Brown 已提交
420
EXPORT_SYMBOL(acpi_get_table);