root/drivers/acpi/acpica/tbxfload.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. ACPI_EXPORT_SYMBOL_INIT
  3. acpi_install_table
  4. ACPI_EXPORT_SYMBOL_INIT
  5. ACPI_EXPORT_SYMBOL

   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 - 2019, 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
  19 ACPI_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  ******************************************************************************/
  32 acpi_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 
  87 ACPI_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  ******************************************************************************/
 101 acpi_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 
 221 unlock_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 
 242 acpi_status ACPI_INIT_FUNCTION
 243 acpi_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 
 263 ACPI_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  *
 272  * RETURN:      Status
 273  *
 274  * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must
 275  *              be a valid ACPI table with a valid ACPI table header.
 276  *              Note1: Mainly intended to support hotplug addition of SSDTs.
 277  *              Note2: Does not copy the incoming table. User is responsible
 278  *              to ensure that the table is not deleted or unmapped.
 279  *
 280  ******************************************************************************/
 281 acpi_status acpi_load_table(struct acpi_table_header *table)
 282 {
 283         acpi_status status;
 284         u32 table_index;
 285 
 286         ACPI_FUNCTION_TRACE(acpi_load_table);
 287 
 288         /* Parameter validation */
 289 
 290         if (!table) {
 291                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 292         }
 293 
 294         /* Install the table and load it into the namespace */
 295 
 296         ACPI_INFO(("Host-directed Dynamic ACPI Table Load:"));
 297         status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
 298                                                 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL,
 299                                                 FALSE, &table_index);
 300         if (ACPI_SUCCESS(status)) {
 301 
 302                 /* Complete the initialization/resolution of new objects */
 303 
 304                 acpi_ns_initialize_objects();
 305         }
 306 
 307         return_ACPI_STATUS(status);
 308 }
 309 
 310 ACPI_EXPORT_SYMBOL(acpi_load_table)
 311 
 312 /*******************************************************************************
 313  *
 314  * FUNCTION:    acpi_unload_parent_table
 315  *
 316  * PARAMETERS:  object              - Handle to any namespace object owned by
 317  *                                    the table to be unloaded
 318  *
 319  * RETURN:      Status
 320  *
 321  * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads
 322  *              the table and deletes all namespace objects associated with
 323  *              that table. Unloading of the DSDT is not allowed.
 324  *              Note: Mainly intended to support hotplug removal of SSDTs.
 325  *
 326  ******************************************************************************/
 327 acpi_status acpi_unload_parent_table(acpi_handle object)
 328 {
 329         struct acpi_namespace_node *node =
 330             ACPI_CAST_PTR(struct acpi_namespace_node, object);
 331         acpi_status status = AE_NOT_EXIST;
 332         acpi_owner_id owner_id;
 333         u32 i;
 334 
 335         ACPI_FUNCTION_TRACE(acpi_unload_parent_table);
 336 
 337         /* Parameter validation */
 338 
 339         if (!object) {
 340                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 341         }
 342 
 343         /*
 344          * The node owner_id is currently the same as the parent table ID.
 345          * However, this could change in the future.
 346          */
 347         owner_id = node->owner_id;
 348         if (!owner_id) {
 349 
 350                 /* owner_id==0 means DSDT is the owner. DSDT cannot be unloaded */
 351 
 352                 return_ACPI_STATUS(AE_TYPE);
 353         }
 354 
 355         /* Must acquire the table lock during this operation */
 356 
 357         status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 358         if (ACPI_FAILURE(status)) {
 359                 return_ACPI_STATUS(status);
 360         }
 361 
 362         /* Find the table in the global table list */
 363 
 364         for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
 365                 if (owner_id != acpi_gbl_root_table_list.tables[i].owner_id) {
 366                         continue;
 367                 }
 368 
 369                 /*
 370                  * Allow unload of SSDT and OEMx tables only. Do not allow unload
 371                  * of the DSDT. No other types of tables should get here, since
 372                  * only these types can contain AML and thus are the only types
 373                  * that can create namespace objects.
 374                  */
 375                 if (ACPI_COMPARE_NAMESEG
 376                     (acpi_gbl_root_table_list.tables[i].signature.ascii,
 377                      ACPI_SIG_DSDT)) {
 378                         status = AE_TYPE;
 379                         break;
 380                 }
 381 
 382                 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 383                 status = acpi_tb_unload_table(i);
 384                 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 385                 break;
 386         }
 387 
 388         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 389         return_ACPI_STATUS(status);
 390 }
 391 
 392 ACPI_EXPORT_SYMBOL(acpi_unload_parent_table)

/* [<][>][^][v][top][bottom][index][help] */