linux/drivers/acpi/acpica/tbinstal.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: tbinstal - ACPI table installation and removal
   5 *
   6 * Copyright (C) 2000 - 2021, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "actables.h"
  13
  14#define _COMPONENT          ACPI_TABLES
  15ACPI_MODULE_NAME("tbinstal")
  16
  17/*******************************************************************************
  18 *
  19 * FUNCTION:    acpi_tb_install_table_with_override
  20 *
  21 * PARAMETERS:  new_table_desc          - New table descriptor to install
  22 *              override                - Whether override should be performed
  23 *              table_index             - Where the table index is returned
  24 *
  25 * RETURN:      None
  26 *
  27 * DESCRIPTION: Install an ACPI table into the global data structure. The
  28 *              table override mechanism is called to allow the host
  29 *              OS to replace any table before it is installed in the root
  30 *              table array.
  31 *
  32 ******************************************************************************/
  33void
  34acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc,
  35                                    u8 override, u32 *table_index)
  36{
  37        u32 i;
  38        acpi_status status;
  39
  40        status = acpi_tb_get_next_table_descriptor(&i, NULL);
  41        if (ACPI_FAILURE(status)) {
  42                return;
  43        }
  44
  45        /*
  46         * ACPI Table Override:
  47         *
  48         * Before we install the table, let the host OS override it with a new
  49         * one if desired. Any table within the RSDT/XSDT can be replaced,
  50         * including the DSDT which is pointed to by the FADT.
  51         */
  52        if (override) {
  53                acpi_tb_override_table(new_table_desc);
  54        }
  55
  56        acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i],
  57                                      new_table_desc->address,
  58                                      new_table_desc->flags,
  59                                      new_table_desc->pointer);
  60
  61        acpi_tb_print_table_header(new_table_desc->address,
  62                                   new_table_desc->pointer);
  63
  64        /* This synchronizes acpi_gbl_dsdt_index */
  65
  66        *table_index = i;
  67
  68        /* Set the global integer width (based upon revision of the DSDT) */
  69
  70        if (i == acpi_gbl_dsdt_index) {
  71                acpi_ut_set_integer_width(new_table_desc->pointer->revision);
  72        }
  73}
  74
  75/*******************************************************************************
  76 *
  77 * FUNCTION:    acpi_tb_install_standard_table
  78 *
  79 * PARAMETERS:  address             - Address of the table (might be a virtual
  80 *                                    address depending on the table_flags)
  81 *              flags               - Flags for the table
  82 *              reload              - Whether reload should be performed
  83 *              override            - Whether override should be performed
  84 *              table_index         - Where the table index is returned
  85 *
  86 * RETURN:      Status
  87 *
  88 * DESCRIPTION: This function is called to verify and install an ACPI table.
  89 *              When this function is called by "Load" or "LoadTable" opcodes,
  90 *              or by acpi_load_table() API, the "Reload" parameter is set.
  91 *              After successfully returning from this function, table is
  92 *              "INSTALLED" but not "VALIDATED".
  93 *
  94 ******************************************************************************/
  95
  96acpi_status
  97acpi_tb_install_standard_table(acpi_physical_address address,
  98                               u8 flags,
  99                               u8 reload, u8 override, u32 *table_index)
 100{
 101        u32 i;
 102        acpi_status status = AE_OK;
 103        struct acpi_table_desc new_table_desc;
 104
 105        ACPI_FUNCTION_TRACE(tb_install_standard_table);
 106
 107        /* Acquire a temporary table descriptor for validation */
 108
 109        status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags);
 110        if (ACPI_FAILURE(status)) {
 111                ACPI_ERROR((AE_INFO,
 112                            "Could not acquire table length at %8.8X%8.8X",
 113                            ACPI_FORMAT_UINT64(address)));
 114                return_ACPI_STATUS(status);
 115        }
 116
 117        /*
 118         * Optionally do not load any SSDTs from the RSDT/XSDT. This can
 119         * be useful for debugging ACPI problems on some machines.
 120         */
 121        if (!reload &&
 122            acpi_gbl_disable_ssdt_table_install &&
 123            ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) {
 124                ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X",
 125                           new_table_desc.signature.ascii,
 126                           ACPI_FORMAT_UINT64(address)));
 127                goto release_and_exit;
 128        }
 129
 130        /* Acquire the table lock */
 131
 132        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 133
 134        /* Validate and verify a table before installation */
 135
 136        status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i);
 137        if (ACPI_FAILURE(status)) {
 138                if (status == AE_CTRL_TERMINATE) {
 139                        /*
 140                         * Table was unloaded, allow it to be reloaded.
 141                         * As we are going to return AE_OK to the caller, we should
 142                         * take the responsibility of freeing the input descriptor.
 143                         * Refill the input descriptor to ensure
 144                         * acpi_tb_install_table_with_override() can be called again to
 145                         * indicate the re-installation.
 146                         */
 147                        acpi_tb_uninstall_table(&new_table_desc);
 148                        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 149                        *table_index = i;
 150                        return_ACPI_STATUS(AE_OK);
 151                }
 152                goto unlock_and_exit;
 153        }
 154
 155        /* Add the table to the global root table list */
 156
 157        acpi_tb_install_table_with_override(&new_table_desc, override,
 158                                            table_index);
 159
 160        /* Invoke table handler */
 161
 162        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 163        acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer);
 164        (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 165
 166unlock_and_exit:
 167
 168        /* Release the table lock */
 169
 170        (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 171
 172release_and_exit:
 173
 174        /* Release the temporary table descriptor */
 175
 176        acpi_tb_release_temp_table(&new_table_desc);
 177        return_ACPI_STATUS(status);
 178}
 179
 180/*******************************************************************************
 181 *
 182 * FUNCTION:    acpi_tb_override_table
 183 *
 184 * PARAMETERS:  old_table_desc      - Validated table descriptor to be
 185 *                                    overridden
 186 *
 187 * RETURN:      None
 188 *
 189 * DESCRIPTION: Attempt table override by calling the OSL override functions.
 190 *              Note: If the table is overridden, then the entire new table
 191 *              is acquired and returned by this function.
 192 *              Before/after invocation, the table descriptor is in a state
 193 *              that is "VALIDATED".
 194 *
 195 ******************************************************************************/
 196
 197void acpi_tb_override_table(struct acpi_table_desc *old_table_desc)
 198{
 199        acpi_status status;
 200        struct acpi_table_desc new_table_desc;
 201        struct acpi_table_header *table;
 202        acpi_physical_address address;
 203        u32 length;
 204        ACPI_ERROR_ONLY(char *override_type);
 205
 206        /* (1) Attempt logical override (returns a logical address) */
 207
 208        status = acpi_os_table_override(old_table_desc->pointer, &table);
 209        if (ACPI_SUCCESS(status) && table) {
 210                acpi_tb_acquire_temp_table(&new_table_desc,
 211                                           ACPI_PTR_TO_PHYSADDR(table),
 212                                           ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
 213                ACPI_ERROR_ONLY(override_type = "Logical");
 214                goto finish_override;
 215        }
 216
 217        /* (2) Attempt physical override (returns a physical address) */
 218
 219        status = acpi_os_physical_table_override(old_table_desc->pointer,
 220                                                 &address, &length);
 221        if (ACPI_SUCCESS(status) && address && length) {
 222                acpi_tb_acquire_temp_table(&new_table_desc, address,
 223                                           ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
 224                ACPI_ERROR_ONLY(override_type = "Physical");
 225                goto finish_override;
 226        }
 227
 228        return;                 /* There was no override */
 229
 230finish_override:
 231
 232        /*
 233         * Validate and verify a table before overriding, no nested table
 234         * duplication check as it's too complicated and unnecessary.
 235         */
 236        status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL);
 237        if (ACPI_FAILURE(status)) {
 238                return;
 239        }
 240
 241        ACPI_INFO(("%4.4s 0x%8.8X%8.8X"
 242                   " %s table override, new table: 0x%8.8X%8.8X",
 243                   old_table_desc->signature.ascii,
 244                   ACPI_FORMAT_UINT64(old_table_desc->address),
 245                   override_type, ACPI_FORMAT_UINT64(new_table_desc.address)));
 246
 247        /* We can now uninstall the original table */
 248
 249        acpi_tb_uninstall_table(old_table_desc);
 250
 251        /*
 252         * Replace the original table descriptor and keep its state as
 253         * "VALIDATED".
 254         */
 255        acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address,
 256                                      new_table_desc.flags,
 257                                      new_table_desc.pointer);
 258        acpi_tb_validate_temp_table(old_table_desc);
 259
 260        /* Release the temporary table descriptor */
 261
 262        acpi_tb_release_temp_table(&new_table_desc);
 263}
 264
 265/*******************************************************************************
 266 *
 267 * FUNCTION:    acpi_tb_uninstall_table
 268 *
 269 * PARAMETERS:  table_desc          - Table descriptor
 270 *
 271 * RETURN:      None
 272 *
 273 * DESCRIPTION: Delete one internal ACPI table
 274 *
 275 ******************************************************************************/
 276
 277void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc)
 278{
 279
 280        ACPI_FUNCTION_TRACE(tb_uninstall_table);
 281
 282        /* Table must be installed */
 283
 284        if (!table_desc->address) {
 285                return_VOID;
 286        }
 287
 288        acpi_tb_invalidate_table(table_desc);
 289
 290        if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
 291            ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) {
 292                ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address));
 293        }
 294
 295        table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL);
 296        return_VOID;
 297}
 298