Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: tbxface - ACPI table-oriented external interfaces
0005  *
0006  * Copyright (C) 2000 - 2022, Intel Corp.
0007  *
0008  *****************************************************************************/
0009 
0010 #define EXPORT_ACPI_INTERFACES
0011 
0012 #include <acpi/acpi.h>
0013 #include "accommon.h"
0014 #include "actables.h"
0015 
0016 #define _COMPONENT          ACPI_TABLES
0017 ACPI_MODULE_NAME("tbxface")
0018 
0019 /*******************************************************************************
0020  *
0021  * FUNCTION:    acpi_allocate_root_table
0022  *
0023  * PARAMETERS:  initial_table_count - Size of initial_table_array, in number of
0024  *                                    struct acpi_table_desc structures
0025  *
0026  * RETURN:      Status
0027  *
0028  * DESCRIPTION: Allocate a root table array. Used by iASL compiler and
0029  *              acpi_initialize_tables.
0030  *
0031  ******************************************************************************/
0032 acpi_status acpi_allocate_root_table(u32 initial_table_count)
0033 {
0034 
0035     acpi_gbl_root_table_list.max_table_count = initial_table_count;
0036     acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
0037 
0038     return (acpi_tb_resize_root_table_list());
0039 }
0040 
0041 /*******************************************************************************
0042  *
0043  * FUNCTION:    acpi_initialize_tables
0044  *
0045  * PARAMETERS:  initial_table_array - Pointer to an array of pre-allocated
0046  *                                    struct acpi_table_desc structures. If NULL, the
0047  *                                    array is dynamically allocated.
0048  *              initial_table_count - Size of initial_table_array, in number of
0049  *                                    struct acpi_table_desc structures
0050  *              allow_resize        - Flag to tell Table Manager if resize of
0051  *                                    pre-allocated array is allowed. Ignored
0052  *                                    if initial_table_array is NULL.
0053  *
0054  * RETURN:      Status
0055  *
0056  * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
0057  *
0058  * NOTE:        Allows static allocation of the initial table array in order
0059  *              to avoid the use of dynamic memory in confined environments
0060  *              such as the kernel boot sequence where it may not be available.
0061  *
0062  *              If the host OS memory managers are initialized, use NULL for
0063  *              initial_table_array, and the table will be dynamically allocated.
0064  *
0065  ******************************************************************************/
0066 
0067 acpi_status ACPI_INIT_FUNCTION
0068 acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
0069                u32 initial_table_count, u8 allow_resize)
0070 {
0071     acpi_physical_address rsdp_address;
0072     acpi_status status;
0073 
0074     ACPI_FUNCTION_TRACE(acpi_initialize_tables);
0075 
0076     /*
0077      * Setup the Root Table Array and allocate the table array
0078      * if requested
0079      */
0080     if (!initial_table_array) {
0081         status = acpi_allocate_root_table(initial_table_count);
0082         if (ACPI_FAILURE(status)) {
0083             return_ACPI_STATUS(status);
0084         }
0085     } else {
0086         /* Root Table Array has been statically allocated by the host */
0087 
0088         memset(initial_table_array, 0,
0089                (acpi_size)initial_table_count *
0090                sizeof(struct acpi_table_desc));
0091 
0092         acpi_gbl_root_table_list.tables = initial_table_array;
0093         acpi_gbl_root_table_list.max_table_count = initial_table_count;
0094         acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
0095         if (allow_resize) {
0096             acpi_gbl_root_table_list.flags |=
0097                 ACPI_ROOT_ALLOW_RESIZE;
0098         }
0099     }
0100 
0101     /* Get the address of the RSDP */
0102 
0103     rsdp_address = acpi_os_get_root_pointer();
0104     if (!rsdp_address) {
0105         return_ACPI_STATUS(AE_NOT_FOUND);
0106     }
0107 
0108     /*
0109      * Get the root table (RSDT or XSDT) and extract all entries to the local
0110      * Root Table Array. This array contains the information of the RSDT/XSDT
0111      * in a common, more usable format.
0112      */
0113     status = acpi_tb_parse_root_table(rsdp_address);
0114     return_ACPI_STATUS(status);
0115 }
0116 
0117 ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
0118 
0119 /*******************************************************************************
0120  *
0121  * FUNCTION:    acpi_reallocate_root_table
0122  *
0123  * PARAMETERS:  None
0124  *
0125  * RETURN:      Status
0126  *
0127  * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
0128  *              root list from the previously provided scratch area. Should
0129  *              be called once dynamic memory allocation is available in the
0130  *              kernel.
0131  *
0132  ******************************************************************************/
0133 acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
0134 {
0135     acpi_status status;
0136     struct acpi_table_desc *table_desc;
0137     u32 i, j;
0138 
0139     ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
0140 
0141     /*
0142      * If there are tables unverified, it is required to reallocate the
0143      * root table list to clean up invalid table entries. Otherwise only
0144      * reallocate the root table list if the host provided a static buffer
0145      * for the table array in the call to acpi_initialize_tables().
0146      */
0147     if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) &&
0148         acpi_gbl_enable_table_validation) {
0149         return_ACPI_STATUS(AE_SUPPORT);
0150     }
0151 
0152     (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0153 
0154     /*
0155      * Ensure OS early boot logic, which is required by some hosts. If the
0156      * table state is reported to be wrong, developers should fix the
0157      * issue by invoking acpi_put_table() for the reported table during the
0158      * early stage.
0159      */
0160     for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
0161         table_desc = &acpi_gbl_root_table_list.tables[i];
0162         if (table_desc->pointer) {
0163             ACPI_ERROR((AE_INFO,
0164                     "Table [%4.4s] is not invalidated during early boot stage",
0165                     table_desc->signature.ascii));
0166         }
0167     }
0168 
0169     if (!acpi_gbl_enable_table_validation) {
0170         /*
0171          * Now it's safe to do full table validation. We can do deferred
0172          * table initialization here once the flag is set.
0173          */
0174         acpi_gbl_enable_table_validation = TRUE;
0175         for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
0176              ++i) {
0177             table_desc = &acpi_gbl_root_table_list.tables[i];
0178             if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) {
0179                 status =
0180                     acpi_tb_verify_temp_table(table_desc, NULL,
0181                                   &j);
0182                 if (ACPI_FAILURE(status)) {
0183                     acpi_tb_uninstall_table(table_desc);
0184                 }
0185             }
0186         }
0187     }
0188 
0189     acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
0190     status = acpi_tb_resize_root_table_list();
0191     acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
0192 
0193     (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0194     return_ACPI_STATUS(status);
0195 }
0196 
0197 ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table)
0198 
0199 /*******************************************************************************
0200  *
0201  * FUNCTION:    acpi_get_table_header
0202  *
0203  * PARAMETERS:  signature           - ACPI signature of needed table
0204  *              instance            - Which instance (for SSDTs)
0205  *              out_table_header    - The pointer to the where the table header
0206  *                                    is returned
0207  *
0208  * RETURN:      Status and a copy of the table header
0209  *
0210  * DESCRIPTION: Finds and returns an ACPI table header. Caller provides the
0211  *              memory where a copy of the header is to be returned
0212  *              (fixed length).
0213  *
0214  ******************************************************************************/
0215 acpi_status
0216 acpi_get_table_header(char *signature,
0217               u32 instance, struct acpi_table_header *out_table_header)
0218 {
0219     u32 i;
0220     u32 j;
0221     struct acpi_table_header *header;
0222 
0223     /* Parameter validation */
0224 
0225     if (!signature || !out_table_header) {
0226         return (AE_BAD_PARAMETER);
0227     }
0228 
0229     /* Walk the root table list */
0230 
0231     for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
0232          i++) {
0233         if (!ACPI_COMPARE_NAMESEG
0234             (&(acpi_gbl_root_table_list.tables[i].signature),
0235              signature)) {
0236             continue;
0237         }
0238 
0239         if (++j < instance) {
0240             continue;
0241         }
0242 
0243         if (!acpi_gbl_root_table_list.tables[i].pointer) {
0244             if ((acpi_gbl_root_table_list.tables[i].flags &
0245                  ACPI_TABLE_ORIGIN_MASK) ==
0246                 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
0247                 header =
0248                     acpi_os_map_memory(acpi_gbl_root_table_list.
0249                                tables[i].address,
0250                                sizeof(struct
0251                                   acpi_table_header));
0252                 if (!header) {
0253                     return (AE_NO_MEMORY);
0254                 }
0255 
0256                 memcpy(out_table_header, header,
0257                        sizeof(struct acpi_table_header));
0258                 acpi_os_unmap_memory(header,
0259                              sizeof(struct
0260                                 acpi_table_header));
0261             } else {
0262                 return (AE_NOT_FOUND);
0263             }
0264         } else {
0265             memcpy(out_table_header,
0266                    acpi_gbl_root_table_list.tables[i].pointer,
0267                    sizeof(struct acpi_table_header));
0268         }
0269         return (AE_OK);
0270     }
0271 
0272     return (AE_NOT_FOUND);
0273 }
0274 
0275 ACPI_EXPORT_SYMBOL(acpi_get_table_header)
0276 
0277 /*******************************************************************************
0278  *
0279  * FUNCTION:    acpi_get_table
0280  *
0281  * PARAMETERS:  signature           - ACPI signature of needed table
0282  *              instance            - Which instance (for SSDTs)
0283  *              out_table           - Where the pointer to the table is returned
0284  *
0285  * RETURN:      Status and pointer to the requested table
0286  *
0287  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
0288  *              RSDT/XSDT.
0289  *              Note that an early stage acpi_get_table() call must be paired
0290  *              with an early stage acpi_put_table() call. otherwise the table
0291  *              pointer mapped by the early stage mapping implementation may be
0292  *              erroneously unmapped by the late stage unmapping implementation
0293  *              in an acpi_put_table() invoked during the late stage.
0294  *
0295  ******************************************************************************/
0296 acpi_status
0297 acpi_get_table(char *signature,
0298            u32 instance, struct acpi_table_header ** out_table)
0299 {
0300     u32 i;
0301     u32 j;
0302     acpi_status status = AE_NOT_FOUND;
0303     struct acpi_table_desc *table_desc;
0304 
0305     /* Parameter validation */
0306 
0307     if (!signature || !out_table) {
0308         return (AE_BAD_PARAMETER);
0309     }
0310 
0311     /*
0312      * Note that the following line is required by some OSPMs, they only
0313      * check if the returned table is NULL instead of the returned status
0314      * to determined if this function is succeeded.
0315      */
0316     *out_table = NULL;
0317 
0318     (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0319 
0320     /* Walk the root table list */
0321 
0322     for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
0323          i++) {
0324         table_desc = &acpi_gbl_root_table_list.tables[i];
0325 
0326         if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
0327             continue;
0328         }
0329 
0330         if (++j < instance) {
0331             continue;
0332         }
0333 
0334         status = acpi_tb_get_table(table_desc, out_table);
0335         break;
0336     }
0337 
0338     (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0339     return (status);
0340 }
0341 
0342 ACPI_EXPORT_SYMBOL(acpi_get_table)
0343 
0344 /*******************************************************************************
0345  *
0346  * FUNCTION:    acpi_put_table
0347  *
0348  * PARAMETERS:  table               - The pointer to the table
0349  *
0350  * RETURN:      None
0351  *
0352  * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
0353  *              Note that it is not safe if this function was invoked after an
0354  *              uninstallation happened to the original table descriptor.
0355  *              Currently there is no OSPMs' requirement to handle such
0356  *              situations.
0357  *
0358  ******************************************************************************/
0359 void acpi_put_table(struct acpi_table_header *table)
0360 {
0361     u32 i;
0362     struct acpi_table_desc *table_desc;
0363 
0364     ACPI_FUNCTION_TRACE(acpi_put_table);
0365 
0366     if (!table) {
0367         return_VOID;
0368     }
0369 
0370     (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0371 
0372     /* Walk the root table list */
0373 
0374     for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
0375         table_desc = &acpi_gbl_root_table_list.tables[i];
0376 
0377         if (table_desc->pointer != table) {
0378             continue;
0379         }
0380 
0381         acpi_tb_put_table(table_desc);
0382         break;
0383     }
0384 
0385     (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0386     return_VOID;
0387 }
0388 
0389 ACPI_EXPORT_SYMBOL(acpi_put_table)
0390 
0391 /*******************************************************************************
0392  *
0393  * FUNCTION:    acpi_get_table_by_index
0394  *
0395  * PARAMETERS:  table_index         - Table index
0396  *              out_table           - Where the pointer to the table is returned
0397  *
0398  * RETURN:      Status and pointer to the requested table
0399  *
0400  * DESCRIPTION: Obtain a table by an index into the global table list. Used
0401  *              internally also.
0402  *
0403  ******************************************************************************/
0404 acpi_status
0405 acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
0406 {
0407     acpi_status status;
0408 
0409     ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
0410 
0411     /* Parameter validation */
0412 
0413     if (!out_table) {
0414         return_ACPI_STATUS(AE_BAD_PARAMETER);
0415     }
0416 
0417     /*
0418      * Note that the following line is required by some OSPMs, they only
0419      * check if the returned table is NULL instead of the returned status
0420      * to determined if this function is succeeded.
0421      */
0422     *out_table = NULL;
0423 
0424     (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0425 
0426     /* Validate index */
0427 
0428     if (table_index >= acpi_gbl_root_table_list.current_table_count) {
0429         status = AE_BAD_PARAMETER;
0430         goto unlock_and_exit;
0431     }
0432 
0433     status =
0434         acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
0435                   out_table);
0436 
0437 unlock_and_exit:
0438     (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0439     return_ACPI_STATUS(status);
0440 }
0441 
0442 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
0443 
0444 /*******************************************************************************
0445  *
0446  * FUNCTION:    acpi_install_table_handler
0447  *
0448  * PARAMETERS:  handler         - Table event handler
0449  *              context         - Value passed to the handler on each event
0450  *
0451  * RETURN:      Status
0452  *
0453  * DESCRIPTION: Install a global table event handler.
0454  *
0455  ******************************************************************************/
0456 acpi_status
0457 acpi_install_table_handler(acpi_table_handler handler, void *context)
0458 {
0459     acpi_status status;
0460 
0461     ACPI_FUNCTION_TRACE(acpi_install_table_handler);
0462 
0463     if (!handler) {
0464         return_ACPI_STATUS(AE_BAD_PARAMETER);
0465     }
0466 
0467     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0468     if (ACPI_FAILURE(status)) {
0469         return_ACPI_STATUS(status);
0470     }
0471 
0472     /* Don't allow more than one handler */
0473 
0474     if (acpi_gbl_table_handler) {
0475         status = AE_ALREADY_EXISTS;
0476         goto cleanup;
0477     }
0478 
0479     /* Install the handler */
0480 
0481     acpi_gbl_table_handler = handler;
0482     acpi_gbl_table_handler_context = context;
0483 
0484 cleanup:
0485     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0486     return_ACPI_STATUS(status);
0487 }
0488 
0489 ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
0490 
0491 /*******************************************************************************
0492  *
0493  * FUNCTION:    acpi_remove_table_handler
0494  *
0495  * PARAMETERS:  handler         - Table event handler that was installed
0496  *                                previously.
0497  *
0498  * RETURN:      Status
0499  *
0500  * DESCRIPTION: Remove a table event handler
0501  *
0502  ******************************************************************************/
0503 acpi_status acpi_remove_table_handler(acpi_table_handler handler)
0504 {
0505     acpi_status status;
0506 
0507     ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
0508 
0509     status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0510     if (ACPI_FAILURE(status)) {
0511         return_ACPI_STATUS(status);
0512     }
0513 
0514     /* Make sure that the installed handler is the same */
0515 
0516     if (!handler || handler != acpi_gbl_table_handler) {
0517         status = AE_BAD_PARAMETER;
0518         goto cleanup;
0519     }
0520 
0521     /* Remove the handler */
0522 
0523     acpi_gbl_table_handler = NULL;
0524 
0525 cleanup:
0526     (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0527     return_ACPI_STATUS(status);
0528 }
0529 
0530 ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)