1/****************************************************************************** 2 * 3 * Module Name: tbinstal - ACPI table installation and removal 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2007, R. Byron Moore 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#include <acpi/acpi.h> 45#include <acpi/acnamesp.h> 46#include <acpi/actables.h> 47 48#define _COMPONENT ACPI_TABLES 49ACPI_MODULE_NAME("tbinstal") 50 51/****************************************************************************** 52 * 53 * FUNCTION: acpi_tb_verify_table 54 * 55 * PARAMETERS: table_desc - table 56 * 57 * RETURN: Status 58 * 59 * DESCRIPTION: this function is called to verify and map table 60 * 61 *****************************************************************************/ 62acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc) 63{ 64 acpi_status status = AE_OK; 65 66 ACPI_FUNCTION_TRACE(tb_verify_table); 67 68 /* Map the table if necessary */ 69 70 if (!table_desc->pointer) { 71 if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 72 ACPI_TABLE_ORIGIN_MAPPED) { 73 table_desc->pointer = 74 acpi_os_map_memory(table_desc->address, 75 table_desc->length); 76 } 77 if (!table_desc->pointer) { 78 return_ACPI_STATUS(AE_NO_MEMORY); 79 } 80 } 81 82 /* FACS is the odd table, has no standard ACPI header and no checksum */ 83 84 if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) { 85 86 /* Always calculate checksum, ignore bad checksum if requested */ 87 88 status = 89 acpi_tb_verify_checksum(table_desc->pointer, 90 table_desc->length); 91 } 92 93 return_ACPI_STATUS(status); 94} 95 96/******************************************************************************* 97 * 98 * FUNCTION: acpi_tb_add_table 99 * 100 * PARAMETERS: table_desc - Table descriptor 101 * table_index - Where the table index is returned 102 * 103 * RETURN: Status 104 * 105 * DESCRIPTION: This function is called to add the ACPI table 106 * 107 ******************************************************************************/ 108 109acpi_status 110acpi_tb_add_table(struct acpi_table_desc *table_desc, 111 acpi_native_uint * table_index) 112{ 113 acpi_native_uint i; 114 acpi_native_uint length; 115 acpi_status status = AE_OK; 116 117 ACPI_FUNCTION_TRACE(tb_add_table); 118 119 if (!table_desc->pointer) { 120 status = acpi_tb_verify_table(table_desc); 121 if (ACPI_FAILURE(status) || !table_desc->pointer) { 122 return_ACPI_STATUS(status); 123 } 124 } 125 126 /* The table must be either an SSDT or a PSDT or an OEMx */ 127 128 if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT)) 129 && 130 (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) 131 && (strncmp(table_desc->pointer->signature, "OEM", 3))) { 132 ACPI_ERROR((AE_INFO, 133 "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx", 134 table_desc->pointer->signature)); 135 return_ACPI_STATUS(AE_BAD_SIGNATURE); 136 } 137 138 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 139 140 /* Check if table is already registered */ 141 142 for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { 143 if (!acpi_gbl_root_table_list.tables[i].pointer) { 144 status = 145 acpi_tb_verify_table(&acpi_gbl_root_table_list. 146 tables[i]); 147 if (ACPI_FAILURE(status) 148 || !acpi_gbl_root_table_list.tables[i].pointer) { 149 continue; 150 } 151 } 152 153 length = ACPI_MIN(table_desc->length, 154 acpi_gbl_root_table_list.tables[i].length); 155 if (ACPI_MEMCMP(table_desc->pointer, 156 acpi_gbl_root_table_list.tables[i].pointer, 157 length)) { 158 continue; 159 } 160 161 /* Table is already registered */ 162 163 acpi_tb_delete_table(table_desc); 164 *table_index = i; 165 goto release; 166 } 167 168 /* 169 * Add the table to the global table list 170 */ 171 status = acpi_tb_store_table(table_desc->address, table_desc->pointer, 172 table_desc->length, table_desc->flags, 173 table_index); 174 if (ACPI_FAILURE(status)) { 175 goto release; 176 } 177 178 acpi_tb_print_table_header(table_desc->address, table_desc->pointer); 179 180 release: 181 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 182 return_ACPI_STATUS(status); 183} 184 185/******************************************************************************* 186 * 187 * FUNCTION: acpi_tb_resize_root_table_list 188 * 189 * PARAMETERS: None 190 * 191 * RETURN: Status 192 * 193 * DESCRIPTION: Expand the size of global table array 194 * 195 ******************************************************************************/ 196 197acpi_status acpi_tb_resize_root_table_list(void) 198{ 199 struct acpi_table_desc *tables; 200 201 ACPI_FUNCTION_TRACE(tb_resize_root_table_list); 202 203 /* allow_resize flag is a parameter to acpi_initialize_tables */ 204 205 if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) { 206 ACPI_ERROR((AE_INFO, 207 "Resize of Root Table Array is not allowed")); 208 return_ACPI_STATUS(AE_SUPPORT); 209 } 210 211 /* Increase the Table Array size */ 212 213 tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size + 214 ACPI_ROOT_TABLE_SIZE_INCREMENT) 215 * sizeof(struct acpi_table_desc)); 216 if (!tables) { 217 ACPI_ERROR((AE_INFO, 218 "Could not allocate new root table array")); 219 return_ACPI_STATUS(AE_NO_MEMORY); 220 } 221 222 /* Copy and free the previous table array */ 223 224 if (acpi_gbl_root_table_list.tables) { 225 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, 226 acpi_gbl_root_table_list.size * 227 sizeof(struct acpi_table_desc)); 228 229 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 230 ACPI_FREE(acpi_gbl_root_table_list.tables); 231 } 232 } 233 234 acpi_gbl_root_table_list.tables = tables; 235 acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT; 236 acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED; 237 238 return_ACPI_STATUS(AE_OK); 239} 240 241/******************************************************************************* 242 * 243 * FUNCTION: acpi_tb_store_table 244 * 245 * PARAMETERS: Address - Table address 246 * Table - Table header 247 * Length - Table length 248 * Flags - flags 249 * 250 * RETURN: Status and table index. 251 * 252 * DESCRIPTION: Add an ACPI table to the global table list 253 * 254 ******************************************************************************/ 255 256acpi_status 257acpi_tb_store_table(acpi_physical_address address, 258 struct acpi_table_header *table, 259 u32 length, u8 flags, acpi_native_uint * table_index) 260{ 261 acpi_status status = AE_OK; 262 263 /* Ensure that there is room for the table in the Root Table List */ 264 265 if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) { 266 status = acpi_tb_resize_root_table_list(); 267 if (ACPI_FAILURE(status)) { 268 return (status); 269 } 270 } 271 272 /* Initialize added table */ 273 274 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. 275 address = address; 276 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. 277 pointer = table; 278 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length = 279 length; 280 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count]. 281 owner_id = 0; 282 acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags = 283 flags; 284 285 ACPI_MOVE_32_TO_32(& 286 (acpi_gbl_root_table_list. 287 tables[acpi_gbl_root_table_list.count].signature), 288 table->signature); 289 290 *table_index = acpi_gbl_root_table_list.count; 291 acpi_gbl_root_table_list.count++; 292 return (status); 293} 294 295/******************************************************************************* 296 * 297 * FUNCTION: acpi_tb_delete_table 298 * 299 * PARAMETERS: table_index - Table index 300 * 301 * RETURN: None 302 * 303 * DESCRIPTION: Delete one internal ACPI table 304 * 305 ******************************************************************************/ 306 307void acpi_tb_delete_table(struct acpi_table_desc *table_desc) 308{ 309 /* Table must be mapped or allocated */ 310 if (!table_desc->pointer) { 311 return; 312 } 313 switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) { 314 case ACPI_TABLE_ORIGIN_MAPPED: 315 acpi_os_unmap_memory(table_desc->pointer, table_desc->length); 316 break; 317 case ACPI_TABLE_ORIGIN_ALLOCATED: 318 ACPI_FREE(table_desc->pointer); 319 break; 320 default:; 321 } 322 323 table_desc->pointer = NULL; 324} 325 326/******************************************************************************* 327 * 328 * FUNCTION: acpi_tb_terminate 329 * 330 * PARAMETERS: None 331 * 332 * RETURN: None 333 * 334 * DESCRIPTION: Delete all internal ACPI tables 335 * 336 ******************************************************************************/ 337 338void acpi_tb_terminate(void) 339{ 340 acpi_native_uint i; 341 342 ACPI_FUNCTION_TRACE(tb_terminate); 343 344 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 345 346 /* Delete the individual tables */ 347 348 for (i = 0; i < acpi_gbl_root_table_list.count; ++i) { 349 acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]); 350 } 351 352 /* 353 * Delete the root table array if allocated locally. Array cannot be 354 * mapped, so we don't need to check for that flag. 355 */ 356 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) { 357 ACPI_FREE(acpi_gbl_root_table_list.tables); 358 } 359 360 acpi_gbl_root_table_list.tables = NULL; 361 acpi_gbl_root_table_list.flags = 0; 362 acpi_gbl_root_table_list.count = 0; 363 364 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n")); 365 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 366} 367 368/******************************************************************************* 369 * 370 * FUNCTION: acpi_tb_delete_namespace_by_owner 371 * 372 * PARAMETERS: table_index - Table index 373 * 374 * RETURN: None 375 * 376 * DESCRIPTION: Delete all namespace objects created when this table was loaded. 377 * 378 ******************************************************************************/ 379 380void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index) 381{ 382 acpi_owner_id owner_id; 383 384 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 385 if (table_index < acpi_gbl_root_table_list.count) { 386 owner_id = 387 acpi_gbl_root_table_list.tables[table_index].owner_id; 388 } else { 389 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 390 return; 391 } 392 393 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 394 acpi_ns_delete_namespace_by_owner(owner_id); 395} 396 397/******************************************************************************* 398 * 399 * FUNCTION: acpi_tb_allocate_owner_id 400 * 401 * PARAMETERS: table_index - Table index 402 * 403 * RETURN: Status 404 * 405 * DESCRIPTION: Allocates owner_id in table_desc 406 * 407 ******************************************************************************/ 408 409acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index) 410{ 411 acpi_status status = AE_BAD_PARAMETER; 412 413 ACPI_FUNCTION_TRACE(tb_allocate_owner_id); 414 415 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 416 if (table_index < acpi_gbl_root_table_list.count) { 417 status = acpi_ut_allocate_owner_id 418 (&(acpi_gbl_root_table_list.tables[table_index].owner_id)); 419 } 420 421 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 422 return_ACPI_STATUS(status); 423} 424 425/******************************************************************************* 426 * 427 * FUNCTION: acpi_tb_release_owner_id 428 * 429 * PARAMETERS: table_index - Table index 430 * 431 * RETURN: Status 432 * 433 * DESCRIPTION: Releases owner_id in table_desc 434 * 435 ******************************************************************************/ 436 437acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index) 438{ 439 acpi_status status = AE_BAD_PARAMETER; 440 441 ACPI_FUNCTION_TRACE(tb_release_owner_id); 442 443 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 444 if (table_index < acpi_gbl_root_table_list.count) { 445 acpi_ut_release_owner_id(& 446 (acpi_gbl_root_table_list. 447 tables[table_index].owner_id)); 448 status = AE_OK; 449 } 450 451 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 452 return_ACPI_STATUS(status); 453} 454 455/******************************************************************************* 456 * 457 * FUNCTION: acpi_tb_get_owner_id 458 * 459 * PARAMETERS: table_index - Table index 460 * owner_id - Where the table owner_id is returned 461 * 462 * RETURN: Status 463 * 464 * DESCRIPTION: returns owner_id for the ACPI table 465 * 466 ******************************************************************************/ 467 468acpi_status 469acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id) 470{ 471 acpi_status status = AE_BAD_PARAMETER; 472 473 ACPI_FUNCTION_TRACE(tb_get_owner_id); 474 475 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 476 if (table_index < acpi_gbl_root_table_list.count) { 477 *owner_id = 478 acpi_gbl_root_table_list.tables[table_index].owner_id; 479 status = AE_OK; 480 } 481 482 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 483 return_ACPI_STATUS(status); 484} 485 486/******************************************************************************* 487 * 488 * FUNCTION: acpi_tb_is_table_loaded 489 * 490 * PARAMETERS: table_index - Table index 491 * 492 * RETURN: Table Loaded Flag 493 * 494 ******************************************************************************/ 495 496u8 acpi_tb_is_table_loaded(acpi_native_uint table_index) 497{ 498 u8 is_loaded = FALSE; 499 500 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 501 if (table_index < acpi_gbl_root_table_list.count) { 502 is_loaded = (u8) 503 (acpi_gbl_root_table_list.tables[table_index]. 504 flags & ACPI_TABLE_IS_LOADED); 505 } 506 507 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 508 return (is_loaded); 509} 510 511/******************************************************************************* 512 * 513 * FUNCTION: acpi_tb_set_table_loaded_flag 514 * 515 * PARAMETERS: table_index - Table index 516 * is_loaded - TRUE if table is loaded, FALSE otherwise 517 * 518 * RETURN: None 519 * 520 * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE. 521 * 522 ******************************************************************************/ 523 524void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded) 525{ 526 527 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 528 if (table_index < acpi_gbl_root_table_list.count) { 529 if (is_loaded) { 530 acpi_gbl_root_table_list.tables[table_index].flags |= 531 ACPI_TABLE_IS_LOADED; 532 } else { 533 acpi_gbl_root_table_list.tables[table_index].flags &= 534 ~ACPI_TABLE_IS_LOADED; 535 } 536 } 537 538 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 539} 540