root/drivers/acpi/acpica/exconfig.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ex_load_table_op
  3. acpi_ex_region_read
  4. acpi_ex_load_op
  5. acpi_ex_unload_table

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes)
   5  *
   6  * Copyright (C) 2000 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acinterp.h"
  13 #include "acnamesp.h"
  14 #include "actables.h"
  15 #include "acdispat.h"
  16 #include "acevents.h"
  17 #include "amlcode.h"
  18 
  19 #define _COMPONENT          ACPI_EXECUTER
  20 ACPI_MODULE_NAME("exconfig")
  21 
  22 /* Local prototypes */
  23 static acpi_status
  24 acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle);
  25 
  26 static acpi_status
  27 acpi_ex_region_read(union acpi_operand_object *obj_desc,
  28                     u32 length, u8 *buffer);
  29 
  30 /*******************************************************************************
  31  *
  32  * FUNCTION:    acpi_ex_add_table
  33  *
  34  * PARAMETERS:  table               - Pointer to raw table
  35  *              parent_node         - Where to load the table (scope)
  36  *              ddb_handle          - Where to return the table handle.
  37  *
  38  * RETURN:      Status
  39  *
  40  * DESCRIPTION: Common function to Install and Load an ACPI table with a
  41  *              returned table handle.
  42  *
  43  ******************************************************************************/
  44 
  45 static acpi_status
  46 acpi_ex_add_table(u32 table_index, union acpi_operand_object **ddb_handle)
  47 {
  48         union acpi_operand_object *obj_desc;
  49 
  50         ACPI_FUNCTION_TRACE(ex_add_table);
  51 
  52         /* Create an object to be the table handle */
  53 
  54         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
  55         if (!obj_desc) {
  56                 return_ACPI_STATUS(AE_NO_MEMORY);
  57         }
  58 
  59         /* Init the table handle */
  60 
  61         obj_desc->common.flags |= AOPOBJ_DATA_VALID;
  62         obj_desc->reference.class = ACPI_REFCLASS_TABLE;
  63         obj_desc->reference.value = table_index;
  64         *ddb_handle = obj_desc;
  65         return_ACPI_STATUS(AE_OK);
  66 }
  67 
  68 /*******************************************************************************
  69  *
  70  * FUNCTION:    acpi_ex_load_table_op
  71  *
  72  * PARAMETERS:  walk_state          - Current state with operands
  73  *              return_desc         - Where to store the return object
  74  *
  75  * RETURN:      Status
  76  *
  77  * DESCRIPTION: Load an ACPI table from the RSDT/XSDT
  78  *
  79  ******************************************************************************/
  80 
  81 acpi_status
  82 acpi_ex_load_table_op(struct acpi_walk_state *walk_state,
  83                       union acpi_operand_object **return_desc)
  84 {
  85         acpi_status status;
  86         union acpi_operand_object **operand = &walk_state->operands[0];
  87         struct acpi_namespace_node *parent_node;
  88         struct acpi_namespace_node *start_node;
  89         struct acpi_namespace_node *parameter_node = NULL;
  90         union acpi_operand_object *ddb_handle;
  91         u32 table_index;
  92 
  93         ACPI_FUNCTION_TRACE(ex_load_table_op);
  94 
  95         /* Find the ACPI table in the RSDT/XSDT */
  96 
  97         acpi_ex_exit_interpreter();
  98         status = acpi_tb_find_table(operand[0]->string.pointer,
  99                                     operand[1]->string.pointer,
 100                                     operand[2]->string.pointer, &table_index);
 101         acpi_ex_enter_interpreter();
 102         if (ACPI_FAILURE(status)) {
 103                 if (status != AE_NOT_FOUND) {
 104                         return_ACPI_STATUS(status);
 105                 }
 106 
 107                 /* Table not found, return an Integer=0 and AE_OK */
 108 
 109                 ddb_handle = acpi_ut_create_integer_object((u64) 0);
 110                 if (!ddb_handle) {
 111                         return_ACPI_STATUS(AE_NO_MEMORY);
 112                 }
 113 
 114                 *return_desc = ddb_handle;
 115                 return_ACPI_STATUS(AE_OK);
 116         }
 117 
 118         /* Default nodes */
 119 
 120         start_node = walk_state->scope_info->scope.node;
 121         parent_node = acpi_gbl_root_node;
 122 
 123         /* root_path (optional parameter) */
 124 
 125         if (operand[3]->string.length > 0) {
 126                 /*
 127                  * Find the node referenced by the root_path_string. This is the
 128                  * location within the namespace where the table will be loaded.
 129                  */
 130                 status = acpi_ns_get_node_unlocked(start_node,
 131                                                    operand[3]->string.pointer,
 132                                                    ACPI_NS_SEARCH_PARENT,
 133                                                    &parent_node);
 134                 if (ACPI_FAILURE(status)) {
 135                         return_ACPI_STATUS(status);
 136                 }
 137         }
 138 
 139         /* parameter_path (optional parameter) */
 140 
 141         if (operand[4]->string.length > 0) {
 142                 if ((operand[4]->string.pointer[0] != AML_ROOT_PREFIX) &&
 143                     (operand[4]->string.pointer[0] != AML_PARENT_PREFIX)) {
 144                         /*
 145                          * Path is not absolute, so it will be relative to the node
 146                          * referenced by the root_path_string (or the NS root if omitted)
 147                          */
 148                         start_node = parent_node;
 149                 }
 150 
 151                 /* Find the node referenced by the parameter_path_string */
 152 
 153                 status = acpi_ns_get_node_unlocked(start_node,
 154                                                    operand[4]->string.pointer,
 155                                                    ACPI_NS_SEARCH_PARENT,
 156                                                    &parameter_node);
 157                 if (ACPI_FAILURE(status)) {
 158                         return_ACPI_STATUS(status);
 159                 }
 160         }
 161 
 162         /* Load the table into the namespace */
 163 
 164         ACPI_INFO(("Dynamic OEM Table Load:"));
 165         acpi_ex_exit_interpreter();
 166         status = acpi_tb_load_table(table_index, parent_node);
 167         acpi_ex_enter_interpreter();
 168         if (ACPI_FAILURE(status)) {
 169                 return_ACPI_STATUS(status);
 170         }
 171 
 172         status = acpi_ex_add_table(table_index, &ddb_handle);
 173         if (ACPI_FAILURE(status)) {
 174                 return_ACPI_STATUS(status);
 175         }
 176 
 177         /* Complete the initialization/resolution of new objects */
 178 
 179         acpi_ex_exit_interpreter();
 180         acpi_ns_initialize_objects();
 181         acpi_ex_enter_interpreter();
 182 
 183         /* Parameter Data (optional) */
 184 
 185         if (parameter_node) {
 186 
 187                 /* Store the parameter data into the optional parameter object */
 188 
 189                 status = acpi_ex_store(operand[5],
 190                                        ACPI_CAST_PTR(union acpi_operand_object,
 191                                                      parameter_node),
 192                                        walk_state);
 193                 if (ACPI_FAILURE(status)) {
 194                         (void)acpi_ex_unload_table(ddb_handle);
 195 
 196                         acpi_ut_remove_reference(ddb_handle);
 197                         return_ACPI_STATUS(status);
 198                 }
 199         }
 200 
 201         *return_desc = ddb_handle;
 202         return_ACPI_STATUS(status);
 203 }
 204 
 205 /*******************************************************************************
 206  *
 207  * FUNCTION:    acpi_ex_region_read
 208  *
 209  * PARAMETERS:  obj_desc        - Region descriptor
 210  *              length          - Number of bytes to read
 211  *              buffer          - Pointer to where to put the data
 212  *
 213  * RETURN:      Status
 214  *
 215  * DESCRIPTION: Read data from an operation region. The read starts from the
 216  *              beginning of the region.
 217  *
 218  ******************************************************************************/
 219 
 220 static acpi_status
 221 acpi_ex_region_read(union acpi_operand_object *obj_desc, u32 length, u8 *buffer)
 222 {
 223         acpi_status status;
 224         u64 value;
 225         u32 region_offset = 0;
 226         u32 i;
 227 
 228         /* Bytewise reads */
 229 
 230         for (i = 0; i < length; i++) {
 231                 status =
 232                     acpi_ev_address_space_dispatch(obj_desc, NULL, ACPI_READ,
 233                                                    region_offset, 8, &value);
 234                 if (ACPI_FAILURE(status)) {
 235                         return (status);
 236                 }
 237 
 238                 *buffer = (u8)value;
 239                 buffer++;
 240                 region_offset++;
 241         }
 242 
 243         return (AE_OK);
 244 }
 245 
 246 /*******************************************************************************
 247  *
 248  * FUNCTION:    acpi_ex_load_op
 249  *
 250  * PARAMETERS:  obj_desc        - Region or Buffer/Field where the table will be
 251  *                                obtained
 252  *              target          - Where a handle to the table will be stored
 253  *              walk_state      - Current state
 254  *
 255  * RETURN:      Status
 256  *
 257  * DESCRIPTION: Load an ACPI table from a field or operation region
 258  *
 259  * NOTE: Region Fields (Field, bank_field, index_fields) are resolved to buffer
 260  *       objects before this code is reached.
 261  *
 262  *       If source is an operation region, it must refer to system_memory, as
 263  *       per the ACPI specification.
 264  *
 265  ******************************************************************************/
 266 
 267 acpi_status
 268 acpi_ex_load_op(union acpi_operand_object *obj_desc,
 269                 union acpi_operand_object *target,
 270                 struct acpi_walk_state *walk_state)
 271 {
 272         union acpi_operand_object *ddb_handle;
 273         struct acpi_table_header *table_header;
 274         struct acpi_table_header *table;
 275         u32 table_index;
 276         acpi_status status;
 277         u32 length;
 278 
 279         ACPI_FUNCTION_TRACE(ex_load_op);
 280 
 281         /* Source Object can be either an op_region or a Buffer/Field */
 282 
 283         switch (obj_desc->common.type) {
 284         case ACPI_TYPE_REGION:
 285 
 286                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 287                                   "Load table from Region %p\n", obj_desc));
 288 
 289                 /* Region must be system_memory (from ACPI spec) */
 290 
 291                 if (obj_desc->region.space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
 292                         return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 293                 }
 294 
 295                 /*
 296                  * If the Region Address and Length have not been previously
 297                  * evaluated, evaluate them now and save the results.
 298                  */
 299                 if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
 300                         status = acpi_ds_get_region_arguments(obj_desc);
 301                         if (ACPI_FAILURE(status)) {
 302                                 return_ACPI_STATUS(status);
 303                         }
 304                 }
 305 
 306                 /* Get the table header first so we can get the table length */
 307 
 308                 table_header = ACPI_ALLOCATE(sizeof(struct acpi_table_header));
 309                 if (!table_header) {
 310                         return_ACPI_STATUS(AE_NO_MEMORY);
 311                 }
 312 
 313                 status =
 314                     acpi_ex_region_read(obj_desc,
 315                                         sizeof(struct acpi_table_header),
 316                                         ACPI_CAST_PTR(u8, table_header));
 317                 length = table_header->length;
 318                 ACPI_FREE(table_header);
 319 
 320                 if (ACPI_FAILURE(status)) {
 321                         return_ACPI_STATUS(status);
 322                 }
 323 
 324                 /* Must have at least an ACPI table header */
 325 
 326                 if (length < sizeof(struct acpi_table_header)) {
 327                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
 328                 }
 329 
 330                 /*
 331                  * The original implementation simply mapped the table, with no copy.
 332                  * However, the memory region is not guaranteed to remain stable and
 333                  * we must copy the table to a local buffer. For example, the memory
 334                  * region is corrupted after suspend on some machines. Dynamically
 335                  * loaded tables are usually small, so this overhead is minimal.
 336                  *
 337                  * The latest implementation (5/2009) does not use a mapping at all.
 338                  * We use the low-level operation region interface to read the table
 339                  * instead of the obvious optimization of using a direct mapping.
 340                  * This maintains a consistent use of operation regions across the
 341                  * entire subsystem. This is important if additional processing must
 342                  * be performed in the (possibly user-installed) operation region
 343                  * handler. For example, acpi_exec and ASLTS depend on this.
 344                  */
 345 
 346                 /* Allocate a buffer for the table */
 347 
 348                 table = ACPI_ALLOCATE(length);
 349                 if (!table) {
 350                         return_ACPI_STATUS(AE_NO_MEMORY);
 351                 }
 352 
 353                 /* Read the entire table */
 354 
 355                 status = acpi_ex_region_read(obj_desc, length,
 356                                              ACPI_CAST_PTR(u8, table));
 357                 if (ACPI_FAILURE(status)) {
 358                         ACPI_FREE(table);
 359                         return_ACPI_STATUS(status);
 360                 }
 361                 break;
 362 
 363         case ACPI_TYPE_BUFFER:  /* Buffer or resolved region_field */
 364 
 365                 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 366                                   "Load table from Buffer or Field %p\n",
 367                                   obj_desc));
 368 
 369                 /* Must have at least an ACPI table header */
 370 
 371                 if (obj_desc->buffer.length < sizeof(struct acpi_table_header)) {
 372                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
 373                 }
 374 
 375                 /* Get the actual table length from the table header */
 376 
 377                 table_header =
 378                     ACPI_CAST_PTR(struct acpi_table_header,
 379                                   obj_desc->buffer.pointer);
 380                 length = table_header->length;
 381 
 382                 /* Table cannot extend beyond the buffer */
 383 
 384                 if (length > obj_desc->buffer.length) {
 385                         return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
 386                 }
 387                 if (length < sizeof(struct acpi_table_header)) {
 388                         return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
 389                 }
 390 
 391                 /*
 392                  * Copy the table from the buffer because the buffer could be
 393                  * modified or even deleted in the future
 394                  */
 395                 table = ACPI_ALLOCATE(length);
 396                 if (!table) {
 397                         return_ACPI_STATUS(AE_NO_MEMORY);
 398                 }
 399 
 400                 memcpy(table, table_header, length);
 401                 break;
 402 
 403         default:
 404 
 405                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 406         }
 407 
 408         /* Install the new table into the local data structures */
 409 
 410         ACPI_INFO(("Dynamic OEM Table Load:"));
 411         acpi_ex_exit_interpreter();
 412         status = acpi_tb_install_and_load_table(ACPI_PTR_TO_PHYSADDR(table),
 413                                                 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
 414                                                 TRUE, &table_index);
 415         acpi_ex_enter_interpreter();
 416         if (ACPI_FAILURE(status)) {
 417 
 418                 /* Delete allocated table buffer */
 419 
 420                 ACPI_FREE(table);
 421                 return_ACPI_STATUS(status);
 422         }
 423 
 424         /*
 425          * Add the table to the namespace.
 426          *
 427          * Note: Load the table objects relative to the root of the namespace.
 428          * This appears to go against the ACPI specification, but we do it for
 429          * compatibility with other ACPI implementations.
 430          */
 431         status = acpi_ex_add_table(table_index, &ddb_handle);
 432         if (ACPI_FAILURE(status)) {
 433 
 434                 /* On error, table_ptr was deallocated above */
 435 
 436                 return_ACPI_STATUS(status);
 437         }
 438 
 439         /* Complete the initialization/resolution of new objects */
 440 
 441         acpi_ex_exit_interpreter();
 442         acpi_ns_initialize_objects();
 443         acpi_ex_enter_interpreter();
 444 
 445         /* Store the ddb_handle into the Target operand */
 446 
 447         status = acpi_ex_store(ddb_handle, target, walk_state);
 448         if (ACPI_FAILURE(status)) {
 449                 (void)acpi_ex_unload_table(ddb_handle);
 450 
 451                 /* table_ptr was deallocated above */
 452 
 453                 acpi_ut_remove_reference(ddb_handle);
 454                 return_ACPI_STATUS(status);
 455         }
 456 
 457         /* Remove the reference by added by acpi_ex_store above */
 458 
 459         acpi_ut_remove_reference(ddb_handle);
 460         return_ACPI_STATUS(status);
 461 }
 462 
 463 /*******************************************************************************
 464  *
 465  * FUNCTION:    acpi_ex_unload_table
 466  *
 467  * PARAMETERS:  ddb_handle          - Handle to a previously loaded table
 468  *
 469  * RETURN:      Status
 470  *
 471  * DESCRIPTION: Unload an ACPI table
 472  *
 473  ******************************************************************************/
 474 
 475 acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
 476 {
 477         acpi_status status = AE_OK;
 478         union acpi_operand_object *table_desc = ddb_handle;
 479         u32 table_index;
 480 
 481         ACPI_FUNCTION_TRACE(ex_unload_table);
 482 
 483         /*
 484          * Temporarily emit a warning so that the ASL for the machine can be
 485          * hopefully obtained. This is to say that the Unload() operator is
 486          * extremely rare if not completely unused.
 487          */
 488         ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
 489 
 490         /*
 491          * May 2018: Unload is no longer supported for the following reasons:
 492          * 1) A correct implementation on some hosts may not be possible.
 493          * 2) Other ACPI implementations do not correctly/fully support it.
 494          * 3) It requires host device driver support which does not exist.
 495          *    (To properly support namespace unload out from underneath.)
 496          * 4) This AML operator has never been seen in the field.
 497          */
 498         ACPI_EXCEPTION((AE_INFO, AE_NOT_IMPLEMENTED,
 499                         "AML Unload operator is not supported"));
 500 
 501         /*
 502          * Validate the handle
 503          * Although the handle is partially validated in acpi_ex_reconfiguration()
 504          * when it calls acpi_ex_resolve_operands(), the handle is more completely
 505          * validated here.
 506          *
 507          * Handle must be a valid operand object of type reference. Also, the
 508          * ddb_handle must still be marked valid (table has not been previously
 509          * unloaded)
 510          */
 511         if ((!ddb_handle) ||
 512             (ACPI_GET_DESCRIPTOR_TYPE(ddb_handle) != ACPI_DESC_TYPE_OPERAND) ||
 513             (ddb_handle->common.type != ACPI_TYPE_LOCAL_REFERENCE) ||
 514             (!(ddb_handle->common.flags & AOPOBJ_DATA_VALID))) {
 515                 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
 516         }
 517 
 518         /* Get the table index from the ddb_handle */
 519 
 520         table_index = table_desc->reference.value;
 521 
 522         /*
 523          * Release the interpreter lock so that the table lock won't have
 524          * strict order requirement against it.
 525          */
 526         acpi_ex_exit_interpreter();
 527         status = acpi_tb_unload_table(table_index);
 528         acpi_ex_enter_interpreter();
 529 
 530         /*
 531          * Invalidate the handle. We do this because the handle may be stored
 532          * in a named object and may not be actually deleted until much later.
 533          */
 534         if (ACPI_SUCCESS(status)) {
 535                 ddb_handle->common.flags &= ~AOPOBJ_DATA_VALID;
 536         }
 537         return_ACPI_STATUS(status);
 538 }

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