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