linux/drivers/acpi/acpica/tbxfload.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: tbxfload - Table load/unload external interfaces
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2016, Intel Corp.
   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#define EXPORT_ACPI_INTERFACES
  45
  46#include <acpi/acpi.h>
  47#include "accommon.h"
  48#include "acnamesp.h"
  49#include "actables.h"
  50#include "acevents.h"
  51
  52#define _COMPONENT          ACPI_TABLES
  53ACPI_MODULE_NAME("tbxfload")
  54
  55/*******************************************************************************
  56 *
  57 * FUNCTION:    acpi_load_tables
  58 *
  59 * PARAMETERS:  None
  60 *
  61 * RETURN:      Status
  62 *
  63 * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT
  64 *
  65 ******************************************************************************/
  66acpi_status __init acpi_load_tables(void)
  67{
  68        acpi_status status;
  69
  70        ACPI_FUNCTION_TRACE(acpi_load_tables);
  71
  72        /*
  73         * Install the default operation region handlers. These are the
  74         * handlers that are defined by the ACPI specification to be
  75         * "always accessible" -- namely, system_memory, system_IO, and
  76         * PCI_Config. This also means that no _REG methods need to be
  77         * run for these address spaces. We need to have these handlers
  78         * installed before any AML code can be executed, especially any
  79         * module-level code (11/2015).
  80         * Note that we allow OSPMs to install their own region handlers
  81         * between acpi_initialize_subsystem() and acpi_load_tables() to use
  82         * their customized default region handlers.
  83         */
  84        status = acpi_ev_install_region_handlers();
  85        if (ACPI_FAILURE(status)) {
  86                ACPI_EXCEPTION((AE_INFO, status,
  87                                "During Region initialization"));
  88                return_ACPI_STATUS(status);
  89        }
  90
  91        /* Load the namespace from the tables */
  92
  93        status = acpi_tb_load_namespace();
  94
  95        /* Don't let single failures abort the load */
  96
  97        if (status == AE_CTRL_TERMINATE) {
  98                status = AE_OK;
  99        }
 100
 101        if (ACPI_FAILURE(status)) {
 102                ACPI_EXCEPTION((AE_INFO, status,
 103                                "While loading namespace from ACPI tables"));
 104        }
 105
 106        if (!acpi_gbl_group_module_level_code) {
 107                /*
 108                 * Initialize the objects that remain uninitialized. This
 109                 * runs the executable AML that may be part of the
 110                 * declaration of these objects:
 111                 * operation_regions, buffer_fields, Buffers, and Packages.
 112                 */
 113                status = acpi_ns_initialize_objects();
 114                if (ACPI_FAILURE(status)) {
 115                        return_ACPI_STATUS(status);
 116                }
 117        }
 118
 119        acpi_gbl_namespace_initialized = TRUE;
 120        return_ACPI_STATUS(status);
 121}
 122
 123ACPI_EXPORT_SYMBOL_INIT(acpi_load_tables)
 124
 125/*******************************************************************************
 126 *
 127 * FUNCTION:    acpi_tb_load_namespace
 128 *
 129 * PARAMETERS:  None
 130 *
 131 * RETURN:      Status
 132 *
 133 * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in
 134 *              the RSDT/XSDT.
 135 *
 136 ******************************************************************************/
 137acpi_status acpi_tb_load_namespace(void)
 138{
 139        acpi_status status;
 140        u32 i;
 141        struct acpi_table_header *new_dsdt;
 142        struct acpi_table_desc *table;
 143        u32 tables_loaded = 0;
 144        u32 tables_failed = 0;
 145
 146        ACPI_FUNCTION_TRACE(tb_load_namespace);
 147
 148        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 149
 150        /*
 151         * Load the namespace. The DSDT is required, but any SSDT and
 152         * PSDT tables are optional. Verify the DSDT.
 153         */
 154        table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index];
 155
 156        if (!acpi_gbl_root_table_list.current_table_count ||
 157            !ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_DSDT) ||
 158            ACPI_FAILURE(acpi_tb_validate_table(table))) {
 159                status = AE_NO_ACPI_TABLES;
 160                goto unlock_and_exit;
 161        }
 162
 163        /*
 164         * Save the DSDT pointer for simple access. This is the mapped memory
 165         * address. We must take care here because the address of the .Tables
 166         * array can change dynamically as tables are loaded at run-time. Note:
 167         * .Pointer field is not validated until after call to acpi_tb_validate_table.
 168         */
 169        acpi_gbl_DSDT = table->pointer;
 170
 171        /*
 172         * Optionally copy the entire DSDT to local memory (instead of simply
 173         * mapping it.) There are some BIOSs that corrupt or replace the original
 174         * DSDT, creating the need for this option. Default is FALSE, do not copy
 175         * the DSDT.
 176         */
 177        if (acpi_gbl_copy_dsdt_locally) {
 178                new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index);
 179                if (new_dsdt) {
 180                        acpi_gbl_DSDT = new_dsdt;
 181                }
 182        }
 183
 184        /*
 185         * Save the original DSDT header for detection of table corruption
 186         * and/or replacement of the DSDT from outside the OS.
 187         */
 188        memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
 189               sizeof(struct acpi_table_header));
 190
 191        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 192
 193        /* Load and parse tables */
 194
 195        status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node);
 196        if (ACPI_FAILURE(status)) {
 197                ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed"));
 198                tables_failed++;
 199        } else {
 200                tables_loaded++;
 201        }
 202
 203        /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */
 204
 205        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 206        for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
 207                table = &acpi_gbl_root_table_list.tables[i];
 208
 209                if (!acpi_gbl_root_table_list.tables[i].address ||
 210                    (!ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_SSDT)
 211                     && !ACPI_COMPARE_NAME(table->signature.ascii,
 212                                           ACPI_SIG_PSDT)
 213                     && !ACPI_COMPARE_NAME(table->signature.ascii,
 214                                           ACPI_SIG_OSDT))
 215                    || ACPI_FAILURE(acpi_tb_validate_table(table))) {
 216                        continue;
 217                }
 218
 219                /* Ignore errors while loading tables, get as many as possible */
 220
 221                (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 222                status = acpi_ns_load_table(i, acpi_gbl_root_node);
 223                if (ACPI_FAILURE(status)) {
 224                        ACPI_EXCEPTION((AE_INFO, status,
 225                                        "(%4.4s:%8.8s) while loading table",
 226                                        table->signature.ascii,
 227                                        table->pointer->oem_table_id));
 228
 229                        tables_failed++;
 230
 231                        ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
 232                                              "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n",
 233                                              table->signature.ascii,
 234                                              table->pointer->oem_table_id));
 235                } else {
 236                        tables_loaded++;
 237                }
 238
 239                (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 240        }
 241
 242        if (!tables_failed) {
 243                ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded\n", tables_loaded));
 244        } else {
 245                ACPI_ERROR((AE_INFO,
 246                            "%u table load failures, %u successful",
 247                            tables_failed, tables_loaded));
 248
 249                /* Indicate at least one failure */
 250
 251                status = AE_CTRL_TERMINATE;
 252        }
 253
 254unlock_and_exit:
 255        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 256        return_ACPI_STATUS(status);
 257}
 258
 259/*******************************************************************************
 260 *
 261 * FUNCTION:    acpi_install_table
 262 *
 263 * PARAMETERS:  address             - Address of the ACPI table to be installed.
 264 *              physical            - Whether the address is a physical table
 265 *                                    address or not
 266 *
 267 * RETURN:      Status
 268 *
 269 * DESCRIPTION: Dynamically install an ACPI table.
 270 *              Note: This function should only be invoked after
 271 *                    acpi_initialize_tables() and before acpi_load_tables().
 272 *
 273 ******************************************************************************/
 274
 275acpi_status __init
 276acpi_install_table(acpi_physical_address address, u8 physical)
 277{
 278        acpi_status status;
 279        u8 flags;
 280        u32 table_index;
 281
 282        ACPI_FUNCTION_TRACE(acpi_install_table);
 283
 284        if (physical) {
 285                flags = ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL;
 286        } else {
 287                flags = ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL;
 288        }
 289
 290        status = acpi_tb_install_standard_table(address, flags,
 291                                                FALSE, FALSE, &table_index);
 292
 293        return_ACPI_STATUS(status);
 294}
 295
 296ACPI_EXPORT_SYMBOL_INIT(acpi_install_table)
 297
 298/*******************************************************************************
 299 *
 300 * FUNCTION:    acpi_load_table
 301 *
 302 * PARAMETERS:  table               - Pointer to a buffer containing the ACPI
 303 *                                    table to be loaded.
 304 *
 305 * RETURN:      Status
 306 *
 307 * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
 308 *              be a valid ACPI table with a valid ACPI table header.
 309 *              Note1: Mainly intended to support hotplug addition of SSDTs.
 310 *              Note2: Does not copy the incoming table. User is responsible
 311 *              to ensure that the table is not deleted or unmapped.
 312 *
 313 ******************************************************************************/
 314acpi_status acpi_load_table(struct acpi_table_header *table)
 315{
 316        acpi_status status;
 317        u32 table_index;
 318
 319        ACPI_FUNCTION_TRACE(acpi_load_table);
 320
 321        /* Parameter validation */
 322
 323        if (!table) {
 324                return_ACPI_STATUS(AE_BAD_PARAMETER);
 325        }
 326
 327        /* Must acquire the interpreter lock during this operation */
 328
 329        status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
 330        if (ACPI_FAILURE(status)) {
 331                return_ACPI_STATUS(status);
 332        }
 333
 334        /* Install the table and load it into the namespace */
 335
 336        ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
 337        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 338
 339        status = acpi_tb_install_standard_table(ACPI_PTR_TO_PHYSADDR(table),
 340                                                ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
 341                                                TRUE, FALSE, &table_index);
 342
 343        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 344        if (ACPI_FAILURE(status)) {
 345                goto unlock_and_exit;
 346        }
 347
 348        /*
 349         * Note: Now table is "INSTALLED", it must be validated before
 350         * using.
 351         */
 352        status =
 353            acpi_tb_validate_table(&acpi_gbl_root_table_list.
 354                                   tables[table_index]);
 355        if (ACPI_FAILURE(status)) {
 356                goto unlock_and_exit;
 357        }
 358
 359        status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
 360
 361        /* Invoke table handler if present */
 362
 363        if (acpi_gbl_table_handler) {
 364                (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
 365                                             acpi_gbl_table_handler_context);
 366        }
 367
 368unlock_and_exit:
 369        (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 370        return_ACPI_STATUS(status);
 371}
 372
 373ACPI_EXPORT_SYMBOL(acpi_load_table)
 374
 375/*******************************************************************************
 376 *
 377 * FUNCTION:    acpi_unload_parent_table
 378 *
 379 * PARAMETERS:  object              - Handle to any namespace object owned by
 380 *                                    the table to be unloaded
 381 *
 382 * RETURN:      Status
 383 *
 384 * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
 385 *              the table and deletes all namespace objects associated with
 386 *              that table. Unloading of the DSDT is not allowed.
 387 *              Note: Mainly intended to support hotplug removal of SSDTs.
 388 *
 389 ******************************************************************************/
 390acpi_status acpi_unload_parent_table(acpi_handle object)
 391{
 392        struct acpi_namespace_node *node =
 393            ACPI_CAST_PTR(struct acpi_namespace_node, object);
 394        acpi_status status = AE_NOT_EXIST;
 395        acpi_owner_id owner_id;
 396        u32 i;
 397
 398        ACPI_FUNCTION_TRACE(acpi_unload_parent_table);
 399
 400        /* Parameter validation */
 401
 402        if (!object) {
 403                return_ACPI_STATUS(AE_BAD_PARAMETER);
 404        }
 405
 406        /*
 407         * The node owner_id is currently the same as the parent table ID.
 408         * However, this could change in the future.
 409         */
 410        owner_id = node->owner_id;
 411        if (!owner_id) {
 412
 413                /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */
 414
 415                return_ACPI_STATUS(AE_TYPE);
 416        }
 417
 418        /* Must acquire the interpreter lock during this operation */
 419
 420        status = acpi_ut_acquire_mutex(ACPI_MTX_INTERPRETER);
 421        if (ACPI_FAILURE(status)) {
 422                return_ACPI_STATUS(status);
 423        }
 424
 425        /* Find the table in the global table list */
 426
 427        for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
 428                if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) {
 429                        continue;
 430                }
 431
 432                /*
 433                 * Allow unload of SSDT and OEMx tables only. Do not allow unload
 434                 * of the DSDT. No other types of tables should get here, since
 435                 * only these types can contain AML and thus are the only types
 436                 * that can create namespace objects.
 437                 */
 438                if (ACPI_COMPARE_NAME
 439                    (acpi_gbl_root_table_list.tables[i].signature.ascii,
 440                     ACPI_SIG_DSDT)) {
 441                        status = AE_TYPE;
 442                        break;
 443                }
 444
 445                /* Ensure the table is actually loaded */
 446
 447                if (!acpi_tb_is_table_loaded(i)) {
 448                        status = AE_NOT_EXIST;
 449                        break;
 450                }
 451
 452                /* Invoke table handler if present */
 453
 454                if (acpi_gbl_table_handler) {
 455                        (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_UNLOAD,
 456                                                     acpi_gbl_root_table_list.
 457                                                     tables[i].pointer,
 458                                                     acpi_gbl_table_handler_context);
 459                }
 460
 461                /*
 462                 * Delete all namespace objects owned by this table. Note that
 463                 * these objects can appear anywhere in the namespace by virtue
 464                 * of the AML "Scope" operator. Thus, we need to track ownership
 465                 * by an ID, not simply a position within the hierarchy.
 466                 */
 467                status = acpi_tb_delete_namespace_by_owner(i);
 468                if (ACPI_FAILURE(status)) {
 469                        break;
 470                }
 471
 472                status = acpi_tb_release_owner_id(i);
 473                acpi_tb_set_table_loaded_flag(i, FALSE);
 474                break;
 475        }
 476
 477        (void)acpi_ut_release_mutex(ACPI_MTX_INTERPRETER);
 478        return_ACPI_STATUS(status);
 479}
 480
 481ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)
 482