LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - tbutils.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 77 115 67.0 %
Date: 2022-04-01 14:58:12 Functions: 5 6 83.3 %
Branches: 26 56 46.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: tbutils - ACPI Table utilities
       5                 :            :  *
       6                 :            :  * Copyright (C) 2000 - 2020, Intel Corp.
       7                 :            :  *
       8                 :            :  *****************************************************************************/
       9                 :            : 
      10                 :            : #include <acpi/acpi.h>
      11                 :            : #include "accommon.h"
      12                 :            : #include "actables.h"
      13                 :            : 
      14                 :            : #define _COMPONENT          ACPI_TABLES
      15                 :            : ACPI_MODULE_NAME("tbutils")
      16                 :            : 
      17                 :            : /* Local prototypes */
      18                 :            : static acpi_physical_address
      19                 :            : acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
      20                 :            : 
      21                 :            : #if (!ACPI_REDUCED_HARDWARE)
      22                 :            : /*******************************************************************************
      23                 :            :  *
      24                 :            :  * FUNCTION:    acpi_tb_initialize_facs
      25                 :            :  *
      26                 :            :  * PARAMETERS:  None
      27                 :            :  *
      28                 :            :  * RETURN:      Status
      29                 :            :  *
      30                 :            :  * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global
      31                 :            :  *              for accessing the Global Lock and Firmware Waking Vector
      32                 :            :  *
      33                 :            :  ******************************************************************************/
      34                 :            : 
      35                 :          3 : acpi_status acpi_tb_initialize_facs(void)
      36                 :            : {
      37                 :          3 :         struct acpi_table_facs *facs;
      38                 :            : 
      39                 :            :         /* If Hardware Reduced flag is set, there is no FACS */
      40                 :            : 
      41         [ -  + ]:          3 :         if (acpi_gbl_reduced_hardware) {
      42                 :          0 :                 acpi_gbl_FACS = NULL;
      43                 :          0 :                 return (AE_OK);
      44         [ -  + ]:          3 :         } else if (acpi_gbl_FADT.Xfacs &&
      45         [ #  # ]:          0 :                    (!acpi_gbl_FADT.facs
      46         [ #  # ]:          0 :                     || !acpi_gbl_use32_bit_facs_addresses)) {
      47                 :          0 :                 (void)acpi_get_table_by_index(acpi_gbl_xfacs_index,
      48                 :            :                                               ACPI_CAST_INDIRECT_PTR(struct
      49                 :            :                                                                      acpi_table_header,
      50                 :            :                                                                      &facs));
      51                 :          0 :                 acpi_gbl_FACS = facs;
      52         [ +  - ]:          3 :         } else if (acpi_gbl_FADT.facs) {
      53                 :          3 :                 (void)acpi_get_table_by_index(acpi_gbl_facs_index,
      54                 :            :                                               ACPI_CAST_INDIRECT_PTR(struct
      55                 :            :                                                                      acpi_table_header,
      56                 :            :                                                                      &facs));
      57                 :          3 :                 acpi_gbl_FACS = facs;
      58                 :            :         }
      59                 :            : 
      60                 :            :         /* If there is no FACS, just continue. There was already an error msg */
      61                 :            : 
      62                 :            :         return (AE_OK);
      63                 :            : }
      64                 :            : #endif                          /* !ACPI_REDUCED_HARDWARE */
      65                 :            : 
      66                 :            : /*******************************************************************************
      67                 :            :  *
      68                 :            :  * FUNCTION:    acpi_tb_check_dsdt_header
      69                 :            :  *
      70                 :            :  * PARAMETERS:  None
      71                 :            :  *
      72                 :            :  * RETURN:      None
      73                 :            :  *
      74                 :            :  * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect
      75                 :            :  *              if the DSDT has been replaced from outside the OS and/or if
      76                 :            :  *              the DSDT header has been corrupted.
      77                 :            :  *
      78                 :            :  ******************************************************************************/
      79                 :            : 
      80                 :        216 : void acpi_tb_check_dsdt_header(void)
      81                 :            : {
      82                 :            : 
      83                 :            :         /* Compare original length and checksum to current values */
      84                 :            : 
      85         [ +  - ]:        216 :         if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length ||
      86         [ -  + ]:        216 :             acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) {
      87                 :          0 :                 ACPI_BIOS_ERROR((AE_INFO,
      88                 :            :                                  "The DSDT has been corrupted or replaced - "
      89                 :            :                                  "old, new headers below"));
      90                 :            : 
      91                 :          0 :                 acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
      92                 :          0 :                 acpi_tb_print_table_header(0, acpi_gbl_DSDT);
      93                 :            : 
      94                 :          0 :                 ACPI_ERROR((AE_INFO,
      95                 :            :                             "Please send DMI info to linux-acpi@vger.kernel.org\n"
      96                 :            :                             "If system does not work as expected, please boot with acpi=copy_dsdt"));
      97                 :            : 
      98                 :            :                 /* Disable further error messages */
      99                 :            : 
     100                 :          0 :                 acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
     101                 :          0 :                 acpi_gbl_original_dsdt_header.checksum =
     102                 :          0 :                     acpi_gbl_DSDT->checksum;
     103                 :            :         }
     104                 :        216 : }
     105                 :            : 
     106                 :            : /*******************************************************************************
     107                 :            :  *
     108                 :            :  * FUNCTION:    acpi_tb_copy_dsdt
     109                 :            :  *
     110                 :            :  * PARAMETERS:  table_index         - Index of installed table to copy
     111                 :            :  *
     112                 :            :  * RETURN:      The copied DSDT
     113                 :            :  *
     114                 :            :  * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory.
     115                 :            :  *              Some very bad BIOSs are known to either corrupt the DSDT or
     116                 :            :  *              install a new, bad DSDT. This copy works around the problem.
     117                 :            :  *
     118                 :            :  ******************************************************************************/
     119                 :            : 
     120                 :          0 : struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
     121                 :            : {
     122                 :          0 :         struct acpi_table_header *new_table;
     123                 :          0 :         struct acpi_table_desc *table_desc;
     124                 :            : 
     125                 :          0 :         table_desc = &acpi_gbl_root_table_list.tables[table_index];
     126                 :            : 
     127                 :          0 :         new_table = ACPI_ALLOCATE(table_desc->length);
     128         [ #  # ]:          0 :         if (!new_table) {
     129                 :          0 :                 ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
     130                 :            :                             table_desc->length));
     131                 :          0 :                 return (NULL);
     132                 :            :         }
     133                 :            : 
     134                 :          0 :         memcpy(new_table, table_desc->pointer, table_desc->length);
     135                 :          0 :         acpi_tb_uninstall_table(table_desc);
     136                 :            : 
     137                 :          0 :         acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
     138                 :          0 :                                       tables[acpi_gbl_dsdt_index],
     139                 :            :                                       ACPI_PTR_TO_PHYSADDR(new_table),
     140                 :            :                                       ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
     141                 :            :                                       new_table);
     142                 :            : 
     143                 :          0 :         ACPI_INFO(("Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length));
     144                 :            : 
     145                 :          0 :         return (new_table);
     146                 :            : }
     147                 :            : 
     148                 :            : /*******************************************************************************
     149                 :            :  *
     150                 :            :  * FUNCTION:    acpi_tb_get_root_table_entry
     151                 :            :  *
     152                 :            :  * PARAMETERS:  table_entry         - Pointer to the RSDT/XSDT table entry
     153                 :            :  *              table_entry_size    - sizeof 32 or 64 (RSDT or XSDT)
     154                 :            :  *
     155                 :            :  * RETURN:      Physical address extracted from the root table
     156                 :            :  *
     157                 :            :  * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on
     158                 :            :  *              both 32-bit and 64-bit platforms
     159                 :            :  *
     160                 :            :  * NOTE:        acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on
     161                 :            :  *              64-bit platforms.
     162                 :            :  *
     163                 :            :  ******************************************************************************/
     164                 :            : 
     165                 :            : static acpi_physical_address
     166                 :          9 : acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
     167                 :            : {
     168                 :          9 :         u64 address64;
     169                 :            : 
     170                 :            :         /*
     171                 :            :          * Get the table physical address (32-bit for RSDT, 64-bit for XSDT):
     172                 :            :          * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT
     173                 :            :          */
     174                 :          9 :         if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) {
     175                 :            :                 /*
     176                 :            :                  * 32-bit platform, RSDT: Return 32-bit table entry
     177                 :            :                  * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return
     178                 :            :                  */
     179                 :          9 :                 return ((acpi_physical_address)
     180                 :          9 :                         (*ACPI_CAST_PTR(u32, table_entry)));
     181                 :            :         } else {
     182                 :            :                 /*
     183                 :            :                  * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return
     184                 :            :                  * 64-bit platform, XSDT: Move (unaligned) 64-bit to local,
     185                 :            :                  *  return 64-bit
     186                 :            :                  */
     187                 :          0 :                 ACPI_MOVE_64_TO_64(&address64, table_entry);
     188                 :            : 
     189                 :            : #if ACPI_MACHINE_WIDTH == 32
     190                 :            :                 if (address64 > ACPI_UINT32_MAX) {
     191                 :            : 
     192                 :            :                         /* Will truncate 64-bit address to 32 bits, issue warning */
     193                 :            : 
     194                 :            :                         ACPI_BIOS_WARNING((AE_INFO,
     195                 :            :                                            "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
     196                 :            :                                            " truncating",
     197                 :            :                                            ACPI_FORMAT_UINT64(address64)));
     198                 :            :                 }
     199                 :            : #endif
     200                 :          0 :                 return ((acpi_physical_address)(address64));
     201                 :            :         }
     202                 :            : }
     203                 :            : 
     204                 :            : /*******************************************************************************
     205                 :            :  *
     206                 :            :  * FUNCTION:    acpi_tb_parse_root_table
     207                 :            :  *
     208                 :            :  * PARAMETERS:  rsdp_address        - Pointer to the RSDP
     209                 :            :  *
     210                 :            :  * RETURN:      Status
     211                 :            :  *
     212                 :            :  * DESCRIPTION: This function is called to parse the Root System Description
     213                 :            :  *              Table (RSDT or XSDT)
     214                 :            :  *
     215                 :            :  * NOTE:        Tables are mapped (not copied) for efficiency. The FACS must
     216                 :            :  *              be mapped and cannot be copied because it contains the actual
     217                 :            :  *              memory location of the ACPI Global Lock.
     218                 :            :  *
     219                 :            :  ******************************************************************************/
     220                 :            : 
     221                 :            : acpi_status ACPI_INIT_FUNCTION
     222                 :          3 : acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
     223                 :            : {
     224                 :          3 :         struct acpi_table_rsdp *rsdp;
     225                 :          3 :         u32 table_entry_size;
     226                 :          3 :         u32 i;
     227                 :          3 :         u32 table_count;
     228                 :          3 :         struct acpi_table_header *table;
     229                 :          3 :         acpi_physical_address address;
     230                 :          3 :         u32 length;
     231                 :          3 :         u8 *table_entry;
     232                 :          3 :         acpi_status status;
     233                 :          3 :         u32 table_index;
     234                 :            : 
     235                 :          3 :         ACPI_FUNCTION_TRACE(tb_parse_root_table);
     236                 :            : 
     237                 :            :         /* Map the entire RSDP and extract the address of the RSDT or XSDT */
     238                 :            : 
     239                 :          3 :         rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
     240         [ +  - ]:          3 :         if (!rsdp) {
     241                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
     242                 :            :         }
     243                 :            : 
     244                 :          3 :         acpi_tb_print_table_header(rsdp_address,
     245                 :            :                                    ACPI_CAST_PTR(struct acpi_table_header,
     246                 :            :                                                  rsdp));
     247                 :            : 
     248                 :            :         /* Use XSDT if present and not overridden. Otherwise, use RSDT */
     249                 :            : 
     250         [ -  + ]:          3 :         if ((rsdp->revision > 1) &&
     251   [ #  #  #  # ]:          0 :             rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) {
     252                 :            :                 /*
     253                 :            :                  * RSDP contains an XSDT (64-bit physical addresses). We must use
     254                 :            :                  * the XSDT if the revision is > 1 and the XSDT pointer is present,
     255                 :            :                  * as per the ACPI specification.
     256                 :            :                  */
     257                 :            :                 address = (acpi_physical_address)rsdp->xsdt_physical_address;
     258                 :            :                 table_entry_size = ACPI_XSDT_ENTRY_SIZE;
     259                 :            :         } else {
     260                 :            :                 /* Root table is an RSDT (32-bit physical addresses) */
     261                 :            : 
     262                 :          3 :                 address = (acpi_physical_address)rsdp->rsdt_physical_address;
     263                 :          3 :                 table_entry_size = ACPI_RSDT_ENTRY_SIZE;
     264                 :            :         }
     265                 :            : 
     266                 :            :         /*
     267                 :            :          * It is not possible to map more than one entry in some environments,
     268                 :            :          * so unmap the RSDP here before mapping other tables
     269                 :            :          */
     270                 :          3 :         acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
     271                 :            : 
     272                 :            :         /* Map the RSDT/XSDT table header to get the full table length */
     273                 :            : 
     274                 :          3 :         table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
     275         [ +  - ]:          3 :         if (!table) {
     276                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
     277                 :            :         }
     278                 :            : 
     279                 :          3 :         acpi_tb_print_table_header(address, table);
     280                 :            : 
     281                 :            :         /*
     282                 :            :          * Validate length of the table, and map entire table.
     283                 :            :          * Minimum length table must contain at least one entry.
     284                 :            :          */
     285                 :          3 :         length = table->length;
     286                 :          3 :         acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
     287                 :            : 
     288         [ -  + ]:          3 :         if (length < (sizeof(struct acpi_table_header) + table_entry_size)) {
     289                 :          0 :                 ACPI_BIOS_ERROR((AE_INFO,
     290                 :            :                                  "Invalid table length 0x%X in RSDT/XSDT",
     291                 :            :                                  length));
     292                 :          0 :                 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
     293                 :            :         }
     294                 :            : 
     295                 :          3 :         table = acpi_os_map_memory(address, length);
     296         [ +  - ]:          3 :         if (!table) {
     297                 :            :                 return_ACPI_STATUS(AE_NO_MEMORY);
     298                 :            :         }
     299                 :            : 
     300                 :            :         /* Validate the root table checksum */
     301                 :            : 
     302                 :          3 :         status = acpi_tb_verify_checksum(table, length);
     303         [ -  + ]:          3 :         if (ACPI_FAILURE(status)) {
     304                 :          0 :                 acpi_os_unmap_memory(table, length);
     305                 :          0 :                 return_ACPI_STATUS(status);
     306                 :            :         }
     307                 :            : 
     308                 :            :         /* Get the number of entries and pointer to first entry */
     309                 :            : 
     310                 :          3 :         table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
     311                 :            :                             table_entry_size);
     312                 :          3 :         table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
     313                 :            : 
     314                 :            :         /* Initialize the root table array from the RSDT/XSDT */
     315                 :            : 
     316         [ +  + ]:         12 :         for (i = 0; i < table_count; i++) {
     317                 :            : 
     318                 :            :                 /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */
     319                 :            : 
     320         [ +  - ]:          9 :                 address =
     321                 :            :                     acpi_tb_get_root_table_entry(table_entry, table_entry_size);
     322                 :            : 
     323                 :            :                 /* Skip NULL entries in RSDT/XSDT */
     324                 :            : 
     325         [ -  + ]:          9 :                 if (!address) {
     326                 :          0 :                         goto next_table;
     327                 :            :                 }
     328                 :            : 
     329                 :          9 :                 status = acpi_tb_install_standard_table(address,
     330                 :            :                                                         ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
     331                 :            :                                                         FALSE, TRUE,
     332                 :            :                                                         &table_index);
     333                 :            : 
     334         [ -  + ]:          9 :                 if (ACPI_SUCCESS(status) &&
     335         [ +  + ]:          9 :                     ACPI_COMPARE_NAMESEG(&acpi_gbl_root_table_list.
     336                 :            :                                          tables[table_index].signature,
     337                 :            :                                          ACPI_SIG_FADT)) {
     338                 :          3 :                         acpi_gbl_fadt_index = table_index;
     339                 :          3 :                         acpi_tb_parse_fadt();
     340                 :            :                 }
     341                 :            : 
     342                 :          6 : next_table:
     343                 :            : 
     344                 :          9 :                 table_entry += table_entry_size;
     345                 :            :         }
     346                 :            : 
     347                 :          3 :         acpi_os_unmap_memory(table, length);
     348                 :          3 :         return_ACPI_STATUS(AE_OK);
     349                 :            : }
     350                 :            : 
     351                 :            : /*******************************************************************************
     352                 :            :  *
     353                 :            :  * FUNCTION:    acpi_tb_get_table
     354                 :            :  *
     355                 :            :  * PARAMETERS:  table_desc          - Table descriptor
     356                 :            :  *              out_table           - Where the pointer to the table is returned
     357                 :            :  *
     358                 :            :  * RETURN:      Status and pointer to the requested table
     359                 :            :  *
     360                 :            :  * DESCRIPTION: Increase a reference to a table descriptor and return the
     361                 :            :  *              validated table pointer.
     362                 :            :  *              If the table descriptor is an entry of the root table list,
     363                 :            :  *              this API must be invoked with ACPI_MTX_TABLES acquired.
     364                 :            :  *
     365                 :            :  ******************************************************************************/
     366                 :            : 
     367                 :            : acpi_status
     368                 :         66 : acpi_tb_get_table(struct acpi_table_desc *table_desc,
     369                 :            :                   struct acpi_table_header **out_table)
     370                 :            : {
     371                 :         66 :         acpi_status status;
     372                 :            : 
     373                 :         66 :         ACPI_FUNCTION_TRACE(acpi_tb_get_table);
     374                 :            : 
     375         [ +  + ]:         66 :         if (table_desc->validation_count == 0) {
     376                 :            : 
     377                 :            :                 /* Table need to be "VALIDATED" */
     378                 :            : 
     379                 :         54 :                 status = acpi_tb_validate_table(table_desc);
     380         [ +  - ]:         54 :                 if (ACPI_FAILURE(status)) {
     381                 :            :                         return_ACPI_STATUS(status);
     382                 :            :                 }
     383                 :            :         }
     384                 :            : 
     385         [ +  - ]:         66 :         if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
     386                 :         66 :                 table_desc->validation_count++;
     387                 :            : 
     388                 :            :                 /*
     389                 :            :                  * Detect validation_count overflows to ensure that the warning
     390                 :            :                  * message will only be printed once.
     391                 :            :                  */
     392         [ -  + ]:         66 :                 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
     393                 :          0 :                         ACPI_WARNING((AE_INFO,
     394                 :            :                                       "Table %p, Validation count overflows\n",
     395                 :            :                                       table_desc));
     396                 :            :                 }
     397                 :            :         }
     398                 :            : 
     399                 :         66 :         *out_table = table_desc->pointer;
     400                 :         66 :         return_ACPI_STATUS(AE_OK);
     401                 :            : }
     402                 :            : 
     403                 :            : /*******************************************************************************
     404                 :            :  *
     405                 :            :  * FUNCTION:    acpi_tb_put_table
     406                 :            :  *
     407                 :            :  * PARAMETERS:  table_desc          - Table descriptor
     408                 :            :  *
     409                 :            :  * RETURN:      None
     410                 :            :  *
     411                 :            :  * DESCRIPTION: Decrease a reference to a table descriptor and release the
     412                 :            :  *              validated table pointer if no references.
     413                 :            :  *              If the table descriptor is an entry of the root table list,
     414                 :            :  *              this API must be invoked with ACPI_MTX_TABLES acquired.
     415                 :            :  *
     416                 :            :  ******************************************************************************/
     417                 :            : 
     418                 :         39 : void acpi_tb_put_table(struct acpi_table_desc *table_desc)
     419                 :            : {
     420                 :            : 
     421                 :         39 :         ACPI_FUNCTION_TRACE(acpi_tb_put_table);
     422                 :            : 
     423         [ +  - ]:         39 :         if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
     424                 :         39 :                 table_desc->validation_count--;
     425                 :            : 
     426                 :            :                 /*
     427                 :            :                  * Detect validation_count underflows to ensure that the warning
     428                 :            :                  * message will only be printed once.
     429                 :            :                  */
     430         [ -  + ]:         39 :                 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
     431                 :          0 :                         ACPI_WARNING((AE_INFO,
     432                 :            :                                       "Table %p, Validation count underflows\n",
     433                 :            :                                       table_desc));
     434                 :          0 :                         return_VOID;
     435                 :            :                 }
     436                 :            :         }
     437                 :            : 
     438         [ +  - ]:         39 :         if (table_desc->validation_count == 0) {
     439                 :            : 
     440                 :            :                 /* Table need to be "INVALIDATED" */
     441                 :            : 
     442                 :         39 :                 acpi_tb_invalidate_table(table_desc);
     443                 :            :         }
     444                 :            : 
     445                 :            :         return_VOID;
     446                 :            : }

Generated by: LCOV version 1.14