tbinstal.c 15.1 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7
/******************************************************************************
 *
 * Module Name: tbinstal - ACPI table installation and removal
 *
 *****************************************************************************/

/*
L
Len Brown 已提交
8
 * Copyright (C) 2000 - 2008, Intel Corp.
L
Linus Torvalds 已提交
9 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
 * 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 <acpi/acpi.h>
45
#include <acpi/acnamesp.h>
L
Linus Torvalds 已提交
46 47 48
#include <acpi/actables.h>

#define _COMPONENT          ACPI_TABLES
L
Len Brown 已提交
49
ACPI_MODULE_NAME("tbinstal")
L
Linus Torvalds 已提交
50

51
/******************************************************************************
L
Linus Torvalds 已提交
52
 *
53
 * FUNCTION:    acpi_tb_verify_table
L
Linus Torvalds 已提交
54
 *
55
 * PARAMETERS:  table_desc          - table
L
Linus Torvalds 已提交
56 57 58
 *
 * RETURN:      Status
 *
59
 * DESCRIPTION: this function is called to verify and map table
L
Linus Torvalds 已提交
60
 *
61 62
 *****************************************************************************/
acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
L
Linus Torvalds 已提交
63
{
64
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
65

66
	ACPI_FUNCTION_TRACE(tb_verify_table);
L
Linus Torvalds 已提交
67

68
	/* Map the table if necessary */
R
Robert Moore 已提交
69

70
	if (!table_desc->pointer) {
71 72 73 74 75 76
		if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
		    ACPI_TABLE_ORIGIN_MAPPED) {
			table_desc->pointer =
			    acpi_os_map_memory(table_desc->address,
					       table_desc->length);
		}
77 78
		if (!table_desc->pointer) {
			return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
79
		}
80
	}
L
Linus Torvalds 已提交
81

82
	/* FACS is the odd table, has no standard ACPI header and no checksum */
B
Bob Moore 已提交
83

84
	if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
L
Linus Torvalds 已提交
85

86 87 88 89 90 91
		/* Always calculate checksum, ignore bad checksum if requested */

		status =
		    acpi_tb_verify_checksum(table_desc->pointer,
					    table_desc->length);
	}
L
Linus Torvalds 已提交
92

93
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
94 95 96 97
}

/*******************************************************************************
 *
98
 * FUNCTION:    acpi_tb_add_table
L
Linus Torvalds 已提交
99
 *
100
 * PARAMETERS:  table_desc          - Table descriptor
101
 *              table_index         - Where the table index is returned
L
Linus Torvalds 已提交
102 103 104
 *
 * RETURN:      Status
 *
105
 * DESCRIPTION: This function is called to add the ACPI table
L
Linus Torvalds 已提交
106 107 108
 *
 ******************************************************************************/

109
acpi_status
110
acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index)
L
Linus Torvalds 已提交
111
{
112 113
	u32 i;
	u32 length;
114
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
115

116
	ACPI_FUNCTION_TRACE(tb_add_table);
L
Linus Torvalds 已提交
117

118 119 120 121 122 123 124
	if (!table_desc->pointer) {
		status = acpi_tb_verify_table(table_desc);
		if (ACPI_FAILURE(status) || !table_desc->pointer) {
			return_ACPI_STATUS(status);
		}
	}

125 126 127 128 129 130 131
	/*
	 * Originally, we checked the table signature for "SSDT" or "PSDT" here.
	 * Next, we added support for OEMx tables, signature "OEM".
	 * Valid tables were encountered with a null signature, so we've just
	 * given up on validating the signature, since it seems to be a waste
	 * of code. The original code was removed (05/2008).
	 */
132

133
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
L
Linus Torvalds 已提交
134

135 136 137 138 139 140 141 142 143 144 145 146 147
	/* Check if table is already registered */

	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
		if (!acpi_gbl_root_table_list.tables[i].pointer) {
			status =
			    acpi_tb_verify_table(&acpi_gbl_root_table_list.
						 tables[i]);
			if (ACPI_FAILURE(status)
			    || !acpi_gbl_root_table_list.tables[i].pointer) {
				continue;
			}
		}

148 149 150 151 152
		length = ACPI_MIN(table_desc->length,
				  acpi_gbl_root_table_list.tables[i].length);
		if (ACPI_MEMCMP(table_desc->pointer,
				acpi_gbl_root_table_list.tables[i].pointer,
				length)) {
153 154 155 156 157
			continue;
		}

		/* Table is already registered */

158
		acpi_tb_delete_table(table_desc);
159
		*table_index = i;
L
Lin Ming 已提交
160
		status = AE_ALREADY_EXISTS;
161
		goto release;
L
Linus Torvalds 已提交
162 163
	}

164
	/*
165
	 * Add the table to the global table list
166
	 */
167 168 169
	status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
				     table_desc->length, table_desc->flags,
				     table_index);
L
Len Brown 已提交
170
	if (ACPI_FAILURE(status)) {
171
		goto release;
172 173
	}

174
	acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
L
Linus Torvalds 已提交
175

176
      release:
L
Len Brown 已提交
177 178
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
179 180 181 182
}

/*******************************************************************************
 *
183
 * FUNCTION:    acpi_tb_resize_root_table_list
L
Linus Torvalds 已提交
184
 *
185
 * PARAMETERS:  None
L
Linus Torvalds 已提交
186 187 188
 *
 * RETURN:      Status
 *
189
 * DESCRIPTION: Expand the size of global table array
L
Linus Torvalds 已提交
190 191 192
 *
 ******************************************************************************/

193
acpi_status acpi_tb_resize_root_table_list(void)
L
Linus Torvalds 已提交
194
{
195
	struct acpi_table_desc *tables;
L
Linus Torvalds 已提交
196

197
	ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
L
Linus Torvalds 已提交
198

199
	/* allow_resize flag is a parameter to acpi_initialize_tables */
L
Linus Torvalds 已提交
200

201
	if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
202 203 204
		ACPI_ERROR((AE_INFO,
			    "Resize of Root Table Array is not allowed"));
		return_ACPI_STATUS(AE_SUPPORT);
L
Linus Torvalds 已提交
205 206
	}

207 208
	/* Increase the Table Array size */

209 210
	tables = ACPI_ALLOCATE_ZEROED(((acpi_size) acpi_gbl_root_table_list.
				       size + ACPI_ROOT_TABLE_SIZE_INCREMENT)
211 212 213 214 215
				      * sizeof(struct acpi_table_desc));
	if (!tables) {
		ACPI_ERROR((AE_INFO,
			    "Could not allocate new root table array"));
		return_ACPI_STATUS(AE_NO_MEMORY);
L
Linus Torvalds 已提交
216 217
	}

218 219 220 221
	/* Copy and free the previous table array */

	if (acpi_gbl_root_table_list.tables) {
		ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
222
			    (acpi_size) acpi_gbl_root_table_list.size *
223 224
			    sizeof(struct acpi_table_desc));

225
		if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
226 227
			ACPI_FREE(acpi_gbl_root_table_list.tables);
		}
L
Linus Torvalds 已提交
228 229
	}

230 231
	acpi_gbl_root_table_list.tables = tables;
	acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
232
	acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
L
Linus Torvalds 已提交
233

234
	return_ACPI_STATUS(AE_OK);
L
Linus Torvalds 已提交
235 236 237 238
}

/*******************************************************************************
 *
239
 * FUNCTION:    acpi_tb_store_table
L
Linus Torvalds 已提交
240
 *
241 242 243 244
 * PARAMETERS:  Address             - Table address
 *              Table               - Table header
 *              Length              - Table length
 *              Flags               - flags
L
Linus Torvalds 已提交
245
 *
246
 * RETURN:      Status and table index.
L
Linus Torvalds 已提交
247
 *
248
 * DESCRIPTION: Add an ACPI table to the global table list
L
Linus Torvalds 已提交
249 250 251 252
 *
 ******************************************************************************/

acpi_status
253 254
acpi_tb_store_table(acpi_physical_address address,
		    struct acpi_table_header *table,
255
		    u32 length, u8 flags, u32 *table_index)
L
Linus Torvalds 已提交
256
{
257
	acpi_status status = AE_OK;
L
Linus Torvalds 已提交
258

259
	/* Ensure that there is room for the table in the Root Table List */
260

261 262 263 264 265
	if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
		status = acpi_tb_resize_root_table_list();
		if (ACPI_FAILURE(status)) {
			return (status);
		}
266 267
	}

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
	/* Initialize added table */

	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
	    address = address;
	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
	    pointer = table;
	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
	    length;
	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
	    owner_id = 0;
	acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
	    flags;

	ACPI_MOVE_32_TO_32(&
			   (acpi_gbl_root_table_list.
			    tables[acpi_gbl_root_table_list.count].signature),
			   table->signature);

	*table_index = acpi_gbl_root_table_list.count;
	acpi_gbl_root_table_list.count++;
	return (status);
}
L
Linus Torvalds 已提交
290

291 292 293 294 295 296 297 298 299 300 301
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_delete_table
 *
 * PARAMETERS:  table_index         - Table index
 *
 * RETURN:      None
 *
 * DESCRIPTION: Delete one internal ACPI table
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
302

303
void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
304 305 306 307
{
	/* Table must be mapped or allocated */
	if (!table_desc->pointer) {
		return;
L
Linus Torvalds 已提交
308
	}
309 310 311 312 313
	switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
	case ACPI_TABLE_ORIGIN_MAPPED:
		acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
		break;
	case ACPI_TABLE_ORIGIN_ALLOCATED:
314
		ACPI_FREE(table_desc->pointer);
315 316
		break;
	default:;
L
Linus Torvalds 已提交
317 318
	}

319
	table_desc->pointer = NULL;
L
Linus Torvalds 已提交
320 321 322 323
}

/*******************************************************************************
 *
324
 * FUNCTION:    acpi_tb_terminate
L
Linus Torvalds 已提交
325
 *
326
 * PARAMETERS:  None
L
Linus Torvalds 已提交
327
 *
328
 * RETURN:      None
L
Linus Torvalds 已提交
329 330 331 332 333
 *
 * DESCRIPTION: Delete all internal ACPI tables
 *
 ******************************************************************************/

334
void acpi_tb_terminate(void)
L
Linus Torvalds 已提交
335
{
336
	u32 i;
337 338 339 340 341 342 343 344

	ACPI_FUNCTION_TRACE(tb_terminate);

	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);

	/* Delete the individual tables */

	for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
345
		acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
346
	}
L
Linus Torvalds 已提交
347 348

	/*
349 350
	 * Delete the root table array if allocated locally. Array cannot be
	 * mapped, so we don't need to check for that flag.
L
Linus Torvalds 已提交
351
	 */
352
	if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
353
		ACPI_FREE(acpi_gbl_root_table_list.tables);
L
Linus Torvalds 已提交
354
	}
355 356 357 358 359 360 361

	acpi_gbl_root_table_list.tables = NULL;
	acpi_gbl_root_table_list.flags = 0;
	acpi_gbl_root_table_list.count = 0;

	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
L
Linus Torvalds 已提交
362 363 364 365
}

/*******************************************************************************
 *
366
 * FUNCTION:    acpi_tb_delete_namespace_by_owner
L
Linus Torvalds 已提交
367
 *
368
 * PARAMETERS:  table_index         - Table index
L
Linus Torvalds 已提交
369
 *
370
 * RETURN:      None
L
Linus Torvalds 已提交
371
 *
372
 * DESCRIPTION: Delete all namespace objects created when this table was loaded.
L
Linus Torvalds 已提交
373 374 375
 *
 ******************************************************************************/

376
void acpi_tb_delete_namespace_by_owner(u32 table_index)
L
Linus Torvalds 已提交
377
{
378
	acpi_owner_id owner_id;
L
Linus Torvalds 已提交
379

380 381 382 383 384 385
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		owner_id =
		    acpi_gbl_root_table_list.tables[table_index].owner_id;
	} else {
		(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
L
Linus Torvalds 已提交
386 387 388
		return;
	}

389 390 391
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	acpi_ns_delete_namespace_by_owner(owner_id);
}
L
Linus Torvalds 已提交
392

393 394 395 396 397 398 399 400 401 402 403
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_allocate_owner_id
 *
 * PARAMETERS:  table_index         - Table index
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Allocates owner_id in table_desc
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
404

405
acpi_status acpi_tb_allocate_owner_id(u32 table_index)
406 407
{
	acpi_status status = AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
408

409
	ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
L
Linus Torvalds 已提交
410

411 412 413 414
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		status = acpi_ut_allocate_owner_id
		    (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
L
Linus Torvalds 已提交
415 416
	}

L
Len Brown 已提交
417
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
418
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
419 420 421 422
}

/*******************************************************************************
 *
423
 * FUNCTION:    acpi_tb_release_owner_id
L
Linus Torvalds 已提交
424
 *
425
 * PARAMETERS:  table_index         - Table index
L
Linus Torvalds 已提交
426
 *
427
 * RETURN:      Status
L
Linus Torvalds 已提交
428
 *
429
 * DESCRIPTION: Releases owner_id in table_desc
L
Linus Torvalds 已提交
430 431 432
 *
 ******************************************************************************/

433
acpi_status acpi_tb_release_owner_id(u32 table_index)
L
Linus Torvalds 已提交
434
{
435
	acpi_status status = AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
436

437
	ACPI_FUNCTION_TRACE(tb_release_owner_id);
L
Linus Torvalds 已提交
438

439 440 441 442 443 444
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		acpi_ut_release_owner_id(&
					 (acpi_gbl_root_table_list.
					  tables[table_index].owner_id));
		status = AE_OK;
L
Linus Torvalds 已提交
445 446
	}

447 448
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
L
Linus Torvalds 已提交
449 450 451 452
}

/*******************************************************************************
 *
453
 * FUNCTION:    acpi_tb_get_owner_id
L
Linus Torvalds 已提交
454
 *
455 456
 * PARAMETERS:  table_index         - Table index
 *              owner_id            - Where the table owner_id is returned
L
Linus Torvalds 已提交
457
 *
458
 * RETURN:      Status
L
Linus Torvalds 已提交
459
 *
460
 * DESCRIPTION: returns owner_id for the ACPI table
L
Linus Torvalds 已提交
461 462 463
 *
 ******************************************************************************/

464
acpi_status acpi_tb_get_owner_id(u32 table_index, acpi_owner_id *owner_id)
L
Linus Torvalds 已提交
465
{
466
	acpi_status status = AE_BAD_PARAMETER;
L
Linus Torvalds 已提交
467

468
	ACPI_FUNCTION_TRACE(tb_get_owner_id);
L
Linus Torvalds 已提交
469

470 471 472 473 474
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		*owner_id =
		    acpi_gbl_root_table_list.tables[table_index].owner_id;
		status = AE_OK;
L
Linus Torvalds 已提交
475 476
	}

477 478 479
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return_ACPI_STATUS(status);
}
L
Linus Torvalds 已提交
480

481 482 483 484 485 486 487 488 489
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_is_table_loaded
 *
 * PARAMETERS:  table_index         - Table index
 *
 * RETURN:      Table Loaded Flag
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
490

491
u8 acpi_tb_is_table_loaded(u32 table_index)
492 493
{
	u8 is_loaded = FALSE;
L
Linus Torvalds 已提交
494

495 496 497 498
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		is_loaded = (u8)
		    (acpi_gbl_root_table_list.tables[table_index].
499
		     flags & ACPI_TABLE_IS_LOADED);
L
Linus Torvalds 已提交
500 501
	}

502 503 504
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
	return (is_loaded);
}
B
Bob Moore 已提交
505

506 507 508 509 510 511 512 513 514 515 516 517
/*******************************************************************************
 *
 * FUNCTION:    acpi_tb_set_table_loaded_flag
 *
 * PARAMETERS:  table_index         - Table index
 *              is_loaded           - TRUE if table is loaded, FALSE otherwise
 *
 * RETURN:      None
 *
 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
 *
 ******************************************************************************/
L
Linus Torvalds 已提交
518

519
void acpi_tb_set_table_loaded_flag(u32 table_index, u8 is_loaded)
520
{
L
Linus Torvalds 已提交
521

522 523 524 525
	(void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
	if (table_index < acpi_gbl_root_table_list.count) {
		if (is_loaded) {
			acpi_gbl_root_table_list.tables[table_index].flags |=
526
			    ACPI_TABLE_IS_LOADED;
527 528
		} else {
			acpi_gbl_root_table_list.tables[table_index].flags &=
529
			    ~ACPI_TABLE_IS_LOADED;
530 531
		}
	}
L
Linus Torvalds 已提交
532

533
	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
L
Linus Torvalds 已提交
534
}