linux/drivers/acpi/tables/tbinstal.c
<<
>>
Prefs
   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