root/drivers/acpi/acpica/tbxface.c

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

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_initialize_tables
  3. ACPI_EXPORT_SYMBOL_INIT
  4. ACPI_EXPORT_SYMBOL_INIT
  5. ACPI_EXPORT_SYMBOL
  6. ACPI_EXPORT_SYMBOL
  7. ACPI_EXPORT_SYMBOL
  8. ACPI_EXPORT_SYMBOL
  9. ACPI_EXPORT_SYMBOL

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: tbxface - ACPI table-oriented 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 "actables.h"
  15 
  16 #define _COMPONENT          ACPI_TABLES
  17 ACPI_MODULE_NAME("tbxface")
  18 
  19 /*******************************************************************************
  20  *
  21  * FUNCTION:    acpi_allocate_root_table
  22  *
  23  * PARAMETERS:  initial_table_count - Size of initial_table_array, in number of
  24  *                                    struct acpi_table_desc structures
  25  *
  26  * RETURN:      Status
  27  *
  28  * DESCRIPTION: Allocate a root table array. Used by iASL compiler and
  29  *              acpi_initialize_tables.
  30  *
  31  ******************************************************************************/
  32 acpi_status acpi_allocate_root_table(u32 initial_table_count)
  33 {
  34 
  35         acpi_gbl_root_table_list.max_table_count = initial_table_count;
  36         acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
  37 
  38         return (acpi_tb_resize_root_table_list());
  39 }
  40 
  41 /*******************************************************************************
  42  *
  43  * FUNCTION:    acpi_initialize_tables
  44  *
  45  * PARAMETERS:  initial_table_array - Pointer to an array of pre-allocated
  46  *                                    struct acpi_table_desc structures. If NULL, the
  47  *                                    array is dynamically allocated.
  48  *              initial_table_count - Size of initial_table_array, in number of
  49  *                                    struct acpi_table_desc structures
  50  *              allow_resize        - Flag to tell Table Manager if resize of
  51  *                                    pre-allocated array is allowed. Ignored
  52  *                                    if initial_table_array is NULL.
  53  *
  54  * RETURN:      Status
  55  *
  56  * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
  57  *
  58  * NOTE:        Allows static allocation of the initial table array in order
  59  *              to avoid the use of dynamic memory in confined environments
  60  *              such as the kernel boot sequence where it may not be available.
  61  *
  62  *              If the host OS memory managers are initialized, use NULL for
  63  *              initial_table_array, and the table will be dynamically allocated.
  64  *
  65  ******************************************************************************/
  66 
  67 acpi_status ACPI_INIT_FUNCTION
  68 acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
  69                        u32 initial_table_count, u8 allow_resize)
  70 {
  71         acpi_physical_address rsdp_address;
  72         acpi_status status;
  73 
  74         ACPI_FUNCTION_TRACE(acpi_initialize_tables);
  75 
  76         /*
  77          * Setup the Root Table Array and allocate the table array
  78          * if requested
  79          */
  80         if (!initial_table_array) {
  81                 status = acpi_allocate_root_table(initial_table_count);
  82                 if (ACPI_FAILURE(status)) {
  83                         return_ACPI_STATUS(status);
  84                 }
  85         } else {
  86                 /* Root Table Array has been statically allocated by the host */
  87 
  88                 memset(initial_table_array, 0,
  89                        (acpi_size)initial_table_count *
  90                        sizeof(struct acpi_table_desc));
  91 
  92                 acpi_gbl_root_table_list.tables = initial_table_array;
  93                 acpi_gbl_root_table_list.max_table_count = initial_table_count;
  94                 acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
  95                 if (allow_resize) {
  96                         acpi_gbl_root_table_list.flags |=
  97                             ACPI_ROOT_ALLOW_RESIZE;
  98                 }
  99         }
 100 
 101         /* Get the address of the RSDP */
 102 
 103         rsdp_address = acpi_os_get_root_pointer();
 104         if (!rsdp_address) {
 105                 return_ACPI_STATUS(AE_NOT_FOUND);
 106         }
 107 
 108         /*
 109          * Get the root table (RSDT or XSDT) and extract all entries to the local
 110          * Root Table Array. This array contains the information of the RSDT/XSDT
 111          * in a common, more usable format.
 112          */
 113         status = acpi_tb_parse_root_table(rsdp_address);
 114         return_ACPI_STATUS(status);
 115 }
 116 
 117 ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
 118 
 119 /*******************************************************************************
 120  *
 121  * FUNCTION:    acpi_reallocate_root_table
 122  *
 123  * PARAMETERS:  None
 124  *
 125  * RETURN:      Status
 126  *
 127  * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
 128  *              root list from the previously provided scratch area. Should
 129  *              be called once dynamic memory allocation is available in the
 130  *              kernel.
 131  *
 132  ******************************************************************************/
 133 acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
 134 {
 135         acpi_status status;
 136         struct acpi_table_desc *table_desc;
 137         u32 i, j;
 138 
 139         ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
 140 
 141         /*
 142          * If there are tables unverified, it is required to reallocate the
 143          * root table list to clean up invalid table entries. Otherwise only
 144          * reallocate the root table list if the host provided a static buffer
 145          * for the table array in the call to acpi_initialize_tables().
 146          */
 147         if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) &&
 148             acpi_gbl_enable_table_validation) {
 149                 return_ACPI_STATUS(AE_SUPPORT);
 150         }
 151 
 152         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 153 
 154         /*
 155          * Ensure OS early boot logic, which is required by some hosts. If the
 156          * table state is reported to be wrong, developers should fix the
 157          * issue by invoking acpi_put_table() for the reported table during the
 158          * early stage.
 159          */
 160         for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
 161                 table_desc = &acpi_gbl_root_table_list.tables[i];
 162                 if (table_desc->pointer) {
 163                         ACPI_ERROR((AE_INFO,
 164                                     "Table [%4.4s] is not invalidated during early boot stage",
 165                                     table_desc->signature.ascii));
 166                 }
 167         }
 168 
 169         if (!acpi_gbl_enable_table_validation) {
 170                 /*
 171                  * Now it's safe to do full table validation. We can do deferred
 172                  * table initialization here once the flag is set.
 173                  */
 174                 acpi_gbl_enable_table_validation = TRUE;
 175                 for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
 176                      ++i) {
 177                         table_desc = &acpi_gbl_root_table_list.tables[i];
 178                         if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) {
 179                                 status =
 180                                     acpi_tb_verify_temp_table(table_desc, NULL,
 181                                                               &j);
 182                                 if (ACPI_FAILURE(status)) {
 183                                         acpi_tb_uninstall_table(table_desc);
 184                                 }
 185                         }
 186                 }
 187         }
 188 
 189         acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
 190         status = acpi_tb_resize_root_table_list();
 191         acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
 192 
 193         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 194         return_ACPI_STATUS(status);
 195 }
 196 
 197 ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table)
 198 
 199 /*******************************************************************************
 200  *
 201  * FUNCTION:    acpi_get_table_header
 202  *
 203  * PARAMETERS:  signature           - ACPI signature of needed table
 204  *              instance            - Which instance (for SSDTs)
 205  *              out_table_header    - The pointer to the table header to fill
 206  *
 207  * RETURN:      Status and pointer to mapped table header
 208  *
 209  * DESCRIPTION: Finds an ACPI table header.
 210  *
 211  * NOTE:        Caller is responsible in unmapping the header with
 212  *              acpi_os_unmap_memory
 213  *
 214  ******************************************************************************/
 215 acpi_status
 216 acpi_get_table_header(char *signature,
 217                       u32 instance, struct acpi_table_header *out_table_header)
 218 {
 219         u32 i;
 220         u32 j;
 221         struct acpi_table_header *header;
 222 
 223         /* Parameter validation */
 224 
 225         if (!signature || !out_table_header) {
 226                 return (AE_BAD_PARAMETER);
 227         }
 228 
 229         /* Walk the root table list */
 230 
 231         for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
 232              i++) {
 233                 if (!ACPI_COMPARE_NAMESEG
 234                     (&(acpi_gbl_root_table_list.tables[i].signature),
 235                      signature)) {
 236                         continue;
 237                 }
 238 
 239                 if (++j < instance) {
 240                         continue;
 241                 }
 242 
 243                 if (!acpi_gbl_root_table_list.tables[i].pointer) {
 244                         if ((acpi_gbl_root_table_list.tables[i].flags &
 245                              ACPI_TABLE_ORIGIN_MASK) ==
 246                             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
 247                                 header =
 248                                     acpi_os_map_memory(acpi_gbl_root_table_list.
 249                                                        tables[i].address,
 250                                                        sizeof(struct
 251                                                               acpi_table_header));
 252                                 if (!header) {
 253                                         return (AE_NO_MEMORY);
 254                                 }
 255 
 256                                 memcpy(out_table_header, header,
 257                                        sizeof(struct acpi_table_header));
 258                                 acpi_os_unmap_memory(header,
 259                                                      sizeof(struct
 260                                                             acpi_table_header));
 261                         } else {
 262                                 return (AE_NOT_FOUND);
 263                         }
 264                 } else {
 265                         memcpy(out_table_header,
 266                                acpi_gbl_root_table_list.tables[i].pointer,
 267                                sizeof(struct acpi_table_header));
 268                 }
 269                 return (AE_OK);
 270         }
 271 
 272         return (AE_NOT_FOUND);
 273 }
 274 
 275 ACPI_EXPORT_SYMBOL(acpi_get_table_header)
 276 
 277 /*******************************************************************************
 278  *
 279  * FUNCTION:    acpi_get_table
 280  *
 281  * PARAMETERS:  signature           - ACPI signature of needed table
 282  *              instance            - Which instance (for SSDTs)
 283  *              out_table           - Where the pointer to the table is returned
 284  *
 285  * RETURN:      Status and pointer to the requested table
 286  *
 287  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
 288  *              RSDT/XSDT.
 289  *              Note that an early stage acpi_get_table() call must be paired
 290  *              with an early stage acpi_put_table() call. otherwise the table
 291  *              pointer mapped by the early stage mapping implementation may be
 292  *              erroneously unmapped by the late stage unmapping implementation
 293  *              in an acpi_put_table() invoked during the late stage.
 294  *
 295  ******************************************************************************/
 296 acpi_status
 297 acpi_get_table(char *signature,
 298                u32 instance, struct acpi_table_header ** out_table)
 299 {
 300         u32 i;
 301         u32 j;
 302         acpi_status status = AE_NOT_FOUND;
 303         struct acpi_table_desc *table_desc;
 304 
 305         /* Parameter validation */
 306 
 307         if (!signature || !out_table) {
 308                 return (AE_BAD_PARAMETER);
 309         }
 310 
 311         /*
 312          * Note that the following line is required by some OSPMs, they only
 313          * check if the returned table is NULL instead of the returned status
 314          * to determined if this function is succeeded.
 315          */
 316         *out_table = NULL;
 317 
 318         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 319 
 320         /* Walk the root table list */
 321 
 322         for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
 323              i++) {
 324                 table_desc = &acpi_gbl_root_table_list.tables[i];
 325 
 326                 if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
 327                         continue;
 328                 }
 329 
 330                 if (++j < instance) {
 331                         continue;
 332                 }
 333 
 334                 status = acpi_tb_get_table(table_desc, out_table);
 335                 break;
 336         }
 337 
 338         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 339         return (status);
 340 }
 341 
 342 ACPI_EXPORT_SYMBOL(acpi_get_table)
 343 
 344 /*******************************************************************************
 345  *
 346  * FUNCTION:    acpi_put_table
 347  *
 348  * PARAMETERS:  table               - The pointer to the table
 349  *
 350  * RETURN:      None
 351  *
 352  * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
 353  *              Note that it is not safe if this function was invoked after an
 354  *              uninstallation happened to the original table descriptor.
 355  *              Currently there is no OSPMs' requirement to handle such
 356  *              situations.
 357  *
 358  ******************************************************************************/
 359 void acpi_put_table(struct acpi_table_header *table)
 360 {
 361         u32 i;
 362         struct acpi_table_desc *table_desc;
 363 
 364         ACPI_FUNCTION_TRACE(acpi_put_table);
 365 
 366         if (!table) {
 367                 return_VOID;
 368         }
 369 
 370         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 371 
 372         /* Walk the root table list */
 373 
 374         for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
 375                 table_desc = &acpi_gbl_root_table_list.tables[i];
 376 
 377                 if (table_desc->pointer != table) {
 378                         continue;
 379                 }
 380 
 381                 acpi_tb_put_table(table_desc);
 382                 break;
 383         }
 384 
 385         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 386         return_VOID;
 387 }
 388 
 389 ACPI_EXPORT_SYMBOL(acpi_put_table)
 390 
 391 /*******************************************************************************
 392  *
 393  * FUNCTION:    acpi_get_table_by_index
 394  *
 395  * PARAMETERS:  table_index         - Table index
 396  *              out_table           - Where the pointer to the table is returned
 397  *
 398  * RETURN:      Status and pointer to the requested table
 399  *
 400  * DESCRIPTION: Obtain a table by an index into the global table list. Used
 401  *              internally also.
 402  *
 403  ******************************************************************************/
 404 acpi_status
 405 acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
 406 {
 407         acpi_status status;
 408 
 409         ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
 410 
 411         /* Parameter validation */
 412 
 413         if (!out_table) {
 414                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 415         }
 416 
 417         /*
 418          * Note that the following line is required by some OSPMs, they only
 419          * check if the returned table is NULL instead of the returned status
 420          * to determined if this function is succeeded.
 421          */
 422         *out_table = NULL;
 423 
 424         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
 425 
 426         /* Validate index */
 427 
 428         if (table_index >= acpi_gbl_root_table_list.current_table_count) {
 429                 status = AE_BAD_PARAMETER;
 430                 goto unlock_and_exit;
 431         }
 432 
 433         status =
 434             acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
 435                               out_table);
 436 
 437 unlock_and_exit:
 438         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
 439         return_ACPI_STATUS(status);
 440 }
 441 
 442 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
 443 
 444 /*******************************************************************************
 445  *
 446  * FUNCTION:    acpi_install_table_handler
 447  *
 448  * PARAMETERS:  handler         - Table event handler
 449  *              context         - Value passed to the handler on each event
 450  *
 451  * RETURN:      Status
 452  *
 453  * DESCRIPTION: Install a global table event handler.
 454  *
 455  ******************************************************************************/
 456 acpi_status
 457 acpi_install_table_handler(acpi_table_handler handler, void *context)
 458 {
 459         acpi_status status;
 460 
 461         ACPI_FUNCTION_TRACE(acpi_install_table_handler);
 462 
 463         if (!handler) {
 464                 return_ACPI_STATUS(AE_BAD_PARAMETER);
 465         }
 466 
 467         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 468         if (ACPI_FAILURE(status)) {
 469                 return_ACPI_STATUS(status);
 470         }
 471 
 472         /* Don't allow more than one handler */
 473 
 474         if (acpi_gbl_table_handler) {
 475                 status = AE_ALREADY_EXISTS;
 476                 goto cleanup;
 477         }
 478 
 479         /* Install the handler */
 480 
 481         acpi_gbl_table_handler = handler;
 482         acpi_gbl_table_handler_context = context;
 483 
 484 cleanup:
 485         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 486         return_ACPI_STATUS(status);
 487 }
 488 
 489 ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
 490 
 491 /*******************************************************************************
 492  *
 493  * FUNCTION:    acpi_remove_table_handler
 494  *
 495  * PARAMETERS:  handler         - Table event handler that was installed
 496  *                                previously.
 497  *
 498  * RETURN:      Status
 499  *
 500  * DESCRIPTION: Remove a table event handler
 501  *
 502  ******************************************************************************/
 503 acpi_status acpi_remove_table_handler(acpi_table_handler handler)
 504 {
 505         acpi_status status;
 506 
 507         ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
 508 
 509         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
 510         if (ACPI_FAILURE(status)) {
 511                 return_ACPI_STATUS(status);
 512         }
 513 
 514         /* Make sure that the installed handler is the same */
 515 
 516         if (!handler || handler != acpi_gbl_table_handler) {
 517                 status = AE_BAD_PARAMETER;
 518                 goto cleanup;
 519         }
 520 
 521         /* Remove the handler */
 522 
 523         acpi_gbl_table_handler = NULL;
 524 
 525 cleanup:
 526         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
 527         return_ACPI_STATUS(status);
 528 }
 529 
 530 ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)

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