LCOV - code coverage report
Current view: top level - drivers/acpi - tables.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 124 277 44.8 %
Date: 2022-04-01 14:35:51 Functions: 14 18 77.8 %
Branches: 42 132 31.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  *  acpi_tables.c - ACPI Boot-Time Table Parsing
       4                 :            :  *
       5                 :            :  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
       6                 :            :  */
       7                 :            : 
       8                 :            : /* Uncomment next line to get verbose printout */
       9                 :            : /* #define DEBUG */
      10                 :            : #define pr_fmt(fmt) "ACPI: " fmt
      11                 :            : 
      12                 :            : #include <linux/init.h>
      13                 :            : #include <linux/kernel.h>
      14                 :            : #include <linux/smp.h>
      15                 :            : #include <linux/string.h>
      16                 :            : #include <linux/types.h>
      17                 :            : #include <linux/irq.h>
      18                 :            : #include <linux/errno.h>
      19                 :            : #include <linux/acpi.h>
      20                 :            : #include <linux/memblock.h>
      21                 :            : #include <linux/earlycpio.h>
      22                 :            : #include <linux/initrd.h>
      23                 :            : #include <linux/security.h>
      24                 :            : #include "internal.h"
      25                 :            : 
      26                 :            : #ifdef CONFIG_ACPI_CUSTOM_DSDT
      27                 :            : #include CONFIG_ACPI_CUSTOM_DSDT_FILE
      28                 :            : #endif
      29                 :            : 
      30                 :            : #define ACPI_MAX_TABLES         128
      31                 :            : 
      32                 :            : static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
      33                 :            : static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
      34                 :            : 
      35                 :            : static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
      36                 :            : 
      37                 :            : static int acpi_apic_instance __initdata;
      38                 :            : 
      39                 :            : enum acpi_subtable_type {
      40                 :            :         ACPI_SUBTABLE_COMMON,
      41                 :            :         ACPI_SUBTABLE_HMAT,
      42                 :            : };
      43                 :            : 
      44                 :            : struct acpi_subtable_entry {
      45                 :            :         union acpi_subtable_headers *hdr;
      46                 :            :         enum acpi_subtable_type type;
      47                 :            : };
      48                 :            : 
      49                 :            : /*
      50                 :            :  * Disable table checksum verification for the early stage due to the size
      51                 :            :  * limitation of the current x86 early mapping implementation.
      52                 :            :  */
      53                 :            : static bool acpi_verify_table_checksum __initdata = false;
      54                 :            : 
      55                 :        168 : void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
      56                 :            : {
      57         [ +  - ]:        168 :         if (!header)
      58                 :            :                 return;
      59                 :            : 
      60   [ +  -  +  -  :        168 :         switch (header->type) {
             -  -  -  + ]
      61                 :            : 
      62                 :            :         case ACPI_MADT_TYPE_LOCAL_APIC:
      63                 :            :                 {
      64                 :            :                         struct acpi_madt_local_apic *p =
      65                 :            :                             (struct acpi_madt_local_apic *)header;
      66                 :            :                         pr_debug("LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
      67                 :            :                                  p->processor_id, p->id,
      68                 :            :                                  (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
      69                 :            :                 }
      70                 :            :                 break;
      71                 :            : 
      72                 :            :         case ACPI_MADT_TYPE_LOCAL_X2APIC:
      73                 :            :                 {
      74                 :            :                         struct acpi_madt_local_x2apic *p =
      75                 :            :                             (struct acpi_madt_local_x2apic *)header;
      76                 :            :                         pr_debug("X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n",
      77                 :            :                                  p->local_apic_id, p->uid,
      78                 :            :                                  (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
      79                 :            :                 }
      80                 :            :                 break;
      81                 :            : 
      82                 :            :         case ACPI_MADT_TYPE_IO_APIC:
      83                 :            :                 {
      84                 :            :                         struct acpi_madt_io_apic *p =
      85                 :            :                             (struct acpi_madt_io_apic *)header;
      86                 :            :                         pr_debug("IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
      87                 :            :                                  p->id, p->address, p->global_irq_base);
      88                 :            :                 }
      89                 :            :                 break;
      90                 :            : 
      91                 :        105 :         case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
      92                 :            :                 {
      93                 :        105 :                         struct acpi_madt_interrupt_override *p =
      94                 :            :                             (struct acpi_madt_interrupt_override *)header;
      95                 :        105 :                         pr_info("INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
      96                 :            :                                 p->bus, p->source_irq, p->global_irq,
      97                 :            :                                 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
      98                 :            :                                 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]);
      99         [ -  + ]:        105 :                         if (p->inti_flags  &
     100                 :            :                             ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK))
     101                 :          0 :                                 pr_info("INT_SRC_OVR unexpected reserved flags: 0x%x\n",
     102                 :            :                                         p->inti_flags  &
     103                 :            :                                         ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK));
     104                 :            :                 }
     105                 :            :                 break;
     106                 :            : 
     107                 :          0 :         case ACPI_MADT_TYPE_NMI_SOURCE:
     108                 :            :                 {
     109                 :          0 :                         struct acpi_madt_nmi_source *p =
     110                 :            :                             (struct acpi_madt_nmi_source *)header;
     111                 :          0 :                         pr_info("NMI_SRC (%s %s global_irq %d)\n",
     112                 :            :                                 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
     113                 :            :                                 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
     114                 :            :                                 p->global_irq);
     115                 :            :                 }
     116                 :          0 :                 break;
     117                 :            : 
     118                 :         21 :         case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
     119                 :            :                 {
     120                 :         21 :                         struct acpi_madt_local_apic_nmi *p =
     121                 :            :                             (struct acpi_madt_local_apic_nmi *)header;
     122                 :         21 :                         pr_info("LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
     123                 :            :                                 p->processor_id,
     124                 :            :                                 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK  ],
     125                 :            :                                 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
     126                 :            :                                 p->lint);
     127                 :            :                 }
     128                 :         21 :                 break;
     129                 :            : 
     130                 :          0 :         case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
     131                 :            :                 {
     132                 :          0 :                         u16 polarity, trigger;
     133                 :          0 :                         struct acpi_madt_local_x2apic_nmi *p =
     134                 :            :                             (struct acpi_madt_local_x2apic_nmi *)header;
     135                 :            : 
     136                 :          0 :                         polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK;
     137                 :          0 :                         trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2;
     138                 :            : 
     139                 :          0 :                         pr_info("X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n",
     140                 :            :                                 p->uid,
     141                 :            :                                 mps_inti_flags_polarity[polarity],
     142                 :            :                                 mps_inti_flags_trigger[trigger],
     143                 :            :                                 p->lint);
     144                 :            :                 }
     145                 :          0 :                 break;
     146                 :            : 
     147                 :          0 :         case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
     148                 :            :                 {
     149                 :          0 :                         struct acpi_madt_local_apic_override *p =
     150                 :            :                             (struct acpi_madt_local_apic_override *)header;
     151                 :          0 :                         pr_info("LAPIC_ADDR_OVR (address[%p])\n",
     152                 :            :                                 (void *)(unsigned long)p->address);
     153                 :            :                 }
     154                 :          0 :                 break;
     155                 :            : 
     156                 :            :         case ACPI_MADT_TYPE_IO_SAPIC:
     157                 :            :                 {
     158                 :            :                         struct acpi_madt_io_sapic *p =
     159                 :            :                             (struct acpi_madt_io_sapic *)header;
     160                 :            :                         pr_debug("IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
     161                 :            :                                  p->id, (void *)(unsigned long)p->address,
     162                 :            :                                  p->global_irq_base);
     163                 :            :                 }
     164                 :            :                 break;
     165                 :            : 
     166                 :            :         case ACPI_MADT_TYPE_LOCAL_SAPIC:
     167                 :            :                 {
     168                 :            :                         struct acpi_madt_local_sapic *p =
     169                 :            :                             (struct acpi_madt_local_sapic *)header;
     170                 :            :                         pr_debug("LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
     171                 :            :                                  p->processor_id, p->id, p->eid,
     172                 :            :                                  (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
     173                 :            :                 }
     174                 :            :                 break;
     175                 :            : 
     176                 :          0 :         case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
     177                 :            :                 {
     178                 :          0 :                         struct acpi_madt_interrupt_source *p =
     179                 :            :                             (struct acpi_madt_interrupt_source *)header;
     180                 :          0 :                         pr_info("PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
     181                 :            :                                 mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
     182                 :            :                                 mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
     183                 :            :                                 p->type, p->id, p->eid, p->io_sapic_vector,
     184                 :            :                                 p->global_irq);
     185                 :            :                 }
     186                 :          0 :                 break;
     187                 :            : 
     188                 :            :         case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
     189                 :            :                 {
     190                 :            :                         struct acpi_madt_generic_interrupt *p =
     191                 :            :                                 (struct acpi_madt_generic_interrupt *)header;
     192                 :            :                         pr_debug("GICC (acpi_id[0x%04x] address[%llx] MPIDR[0x%llx] %s)\n",
     193                 :            :                                  p->uid, p->base_address,
     194                 :            :                                  p->arm_mpidr,
     195                 :            :                                  (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
     196                 :            : 
     197                 :            :                 }
     198                 :            :                 break;
     199                 :            : 
     200                 :            :         case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
     201                 :            :                 {
     202                 :            :                         struct acpi_madt_generic_distributor *p =
     203                 :            :                                 (struct acpi_madt_generic_distributor *)header;
     204                 :            :                         pr_debug("GIC Distributor (gic_id[0x%04x] address[%llx] gsi_base[%d])\n",
     205                 :            :                                  p->gic_id, p->base_address,
     206                 :            :                                  p->global_irq_base);
     207                 :            :                 }
     208                 :            :                 break;
     209                 :            : 
     210                 :          0 :         default:
     211                 :          0 :                 pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
     212                 :            :                         header->type);
     213                 :          0 :                 break;
     214                 :            :         }
     215                 :            : }
     216                 :            : 
     217                 :            : static unsigned long __init
     218                 :            : acpi_get_entry_type(struct acpi_subtable_entry *entry)
     219                 :            : {
     220                 :            :         switch (entry->type) {
     221                 :            :         case ACPI_SUBTABLE_COMMON:
     222                 :            :                 return entry->hdr->common.type;
     223                 :            :         case ACPI_SUBTABLE_HMAT:
     224                 :            :                 return entry->hdr->hmat.type;
     225                 :            :         }
     226                 :            :         return 0;
     227                 :            : }
     228                 :            : 
     229                 :            : static unsigned long __init
     230                 :            : acpi_get_entry_length(struct acpi_subtable_entry *entry)
     231                 :            : {
     232                 :            :         switch (entry->type) {
     233                 :            :         case ACPI_SUBTABLE_COMMON:
     234                 :            :                 return entry->hdr->common.length;
     235                 :            :         case ACPI_SUBTABLE_HMAT:
     236                 :            :                 return entry->hdr->hmat.length;
     237                 :            :         }
     238                 :            :         return 0;
     239                 :            : }
     240                 :            : 
     241                 :            : static unsigned long __init
     242                 :            : acpi_get_subtable_header_length(struct acpi_subtable_entry *entry)
     243                 :            : {
     244                 :            :         switch (entry->type) {
     245                 :            :         case ACPI_SUBTABLE_COMMON:
     246                 :            :                 return sizeof(entry->hdr->common);
     247                 :            :         case ACPI_SUBTABLE_HMAT:
     248                 :            :                 return sizeof(entry->hdr->hmat);
     249                 :            :         }
     250                 :            :         return 0;
     251                 :            : }
     252                 :            : 
     253                 :            : static enum acpi_subtable_type __init
     254                 :        168 : acpi_get_subtable_type(char *id)
     255                 :            : {
     256         [ -  + ]:        168 :         if (strncmp(id, ACPI_SIG_HMAT, 4) == 0)
     257                 :          0 :                 return ACPI_SUBTABLE_HMAT;
     258                 :            :         return ACPI_SUBTABLE_COMMON;
     259                 :            : }
     260                 :            : 
     261                 :            : /**
     262                 :            :  * acpi_parse_entries_array - for each proc_num find a suitable subtable
     263                 :            :  *
     264                 :            :  * @id: table id (for debugging purposes)
     265                 :            :  * @table_size: size of the root table
     266                 :            :  * @table_header: where does the table start?
     267                 :            :  * @proc: array of acpi_subtable_proc struct containing entry id
     268                 :            :  *        and associated handler with it
     269                 :            :  * @proc_num: how big proc is?
     270                 :            :  * @max_entries: how many entries can we process?
     271                 :            :  *
     272                 :            :  * For each proc_num find a subtable with proc->id and run proc->handler
     273                 :            :  * on it. Assumption is that there's only single handler for particular
     274                 :            :  * entry id.
     275                 :            :  *
     276                 :            :  * The table_size is not the size of the complete ACPI table (the length
     277                 :            :  * field in the header struct), but only the size of the root table; i.e.,
     278                 :            :  * the offset from the very first byte of the complete ACPI table, to the
     279                 :            :  * first byte of the very first subtable.
     280                 :            :  *
     281                 :            :  * On success returns sum of all matching entries for all proc handlers.
     282                 :            :  * Otherwise, -ENODEV or -EINVAL is returned.
     283                 :            :  */
     284                 :        168 : static int __init acpi_parse_entries_array(char *id, unsigned long table_size,
     285                 :            :                 struct acpi_table_header *table_header,
     286                 :            :                 struct acpi_subtable_proc *proc, int proc_num,
     287                 :            :                 unsigned int max_entries)
     288                 :            : {
     289                 :        168 :         struct acpi_subtable_entry entry;
     290                 :        168 :         unsigned long table_end, subtable_len, entry_len;
     291                 :        168 :         int count = 0;
     292                 :        168 :         int errs = 0;
     293                 :        168 :         int i;
     294                 :            : 
     295         [ +  - ]:        168 :         if (acpi_disabled)
     296                 :            :                 return -ENODEV;
     297                 :            : 
     298         [ +  - ]:        168 :         if (!id)
     299                 :            :                 return -EINVAL;
     300                 :            : 
     301         [ +  - ]:        168 :         if (!table_size)
     302                 :            :                 return -EINVAL;
     303                 :            : 
     304         [ -  + ]:        168 :         if (!table_header) {
     305                 :          0 :                 pr_warn("%4.4s not present\n", id);
     306                 :          0 :                 return -ENODEV;
     307                 :            :         }
     308                 :            : 
     309                 :        168 :         table_end = (unsigned long)table_header + table_header->length;
     310                 :            : 
     311                 :            :         /* Parse all entries looking for a match. */
     312                 :            : 
     313                 :        168 :         entry.type = acpi_get_subtable_type(id);
     314                 :        168 :         entry.hdr = (union acpi_subtable_headers *)
     315                 :        168 :             ((unsigned long)table_header + table_size);
     316                 :        168 :         subtable_len = acpi_get_subtable_header_length(&entry);
     317                 :            : 
     318         [ +  + ]:       1512 :         while (((unsigned long)entry.hdr) + subtable_len  < table_end) {
     319         [ +  - ]:       1344 :                 if (max_entries && count >= max_entries)
     320                 :            :                         break;
     321                 :            : 
     322         [ +  + ]:       2667 :                 for (i = 0; i < proc_num; i++) {
     323         [ +  + ]:       1491 :                         if (acpi_get_entry_type(&entry) != proc[i].id)
     324                 :       1323 :                                 continue;
     325   [ +  -  +  - ]:        168 :                         if (!proc[i].handler ||
     326         [ -  + ]:        168 :                              (!errs && proc[i].handler(entry.hdr, table_end))) {
     327                 :          0 :                                 errs++;
     328                 :          0 :                                 continue;
     329                 :            :                         }
     330                 :            : 
     331                 :        168 :                         proc[i].count++;
     332                 :        168 :                         break;
     333                 :            :                 }
     334         [ +  + ]:       1344 :                 if (i != proc_num)
     335                 :        168 :                         count++;
     336                 :            : 
     337                 :            :                 /*
     338                 :            :                  * If entry->length is 0, break from this loop to avoid
     339                 :            :                  * infinite loop.
     340                 :            :                  */
     341                 :       1344 :                 entry_len = acpi_get_entry_length(&entry);
     342         [ -  + ]:       1344 :                 if (entry_len == 0) {
     343                 :          0 :                         pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
     344                 :          0 :                         return -EINVAL;
     345                 :            :                 }
     346                 :            : 
     347                 :       1344 :                 entry.hdr = (union acpi_subtable_headers *)
     348                 :       1344 :                     ((unsigned long)entry.hdr + entry_len);
     349                 :            :         }
     350                 :            : 
     351         [ -  + ]:        168 :         if (max_entries && count > max_entries) {
     352                 :          0 :                 pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n",
     353                 :            :                         id, proc->id, count);
     354                 :            :         }
     355                 :            : 
     356         [ +  - ]:        168 :         return errs ? -EINVAL : count;
     357                 :            : }
     358                 :            : 
     359                 :        168 : int __init acpi_table_parse_entries_array(char *id,
     360                 :            :                          unsigned long table_size,
     361                 :            :                          struct acpi_subtable_proc *proc, int proc_num,
     362                 :            :                          unsigned int max_entries)
     363                 :            : {
     364                 :        168 :         struct acpi_table_header *table_header = NULL;
     365                 :        168 :         int count;
     366                 :        168 :         u32 instance = 0;
     367                 :            : 
     368         [ +  - ]:        168 :         if (acpi_disabled)
     369                 :            :                 return -ENODEV;
     370                 :            : 
     371         [ +  - ]:        168 :         if (!id)
     372                 :            :                 return -EINVAL;
     373                 :            : 
     374         [ +  - ]:        168 :         if (!strncmp(id, ACPI_SIG_MADT, 4))
     375                 :        168 :                 instance = acpi_apic_instance;
     376                 :            : 
     377                 :        168 :         acpi_get_table(id, instance, &table_header);
     378         [ -  + ]:        168 :         if (!table_header) {
     379                 :          0 :                 pr_warn("%4.4s not present\n", id);
     380                 :          0 :                 return -ENODEV;
     381                 :            :         }
     382                 :            : 
     383                 :        168 :         count = acpi_parse_entries_array(id, table_size, table_header,
     384                 :            :                         proc, proc_num, max_entries);
     385                 :            : 
     386                 :        168 :         acpi_put_table(table_header);
     387                 :        168 :         return count;
     388                 :            : }
     389                 :            : 
     390                 :        147 : int __init acpi_table_parse_entries(char *id,
     391                 :            :                         unsigned long table_size,
     392                 :            :                         int entry_id,
     393                 :            :                         acpi_tbl_entry_handler handler,
     394                 :            :                         unsigned int max_entries)
     395                 :            : {
     396                 :        147 :         struct acpi_subtable_proc proc = {
     397                 :            :                 .id             = entry_id,
     398                 :            :                 .handler        = handler,
     399                 :            :         };
     400                 :            : 
     401                 :        147 :         return acpi_table_parse_entries_array(id, table_size, &proc, 1,
     402                 :            :                                                 max_entries);
     403                 :            : }
     404                 :            : 
     405                 :        147 : int __init acpi_table_parse_madt(enum acpi_madt_type id,
     406                 :            :                       acpi_tbl_entry_handler handler, unsigned int max_entries)
     407                 :            : {
     408                 :        147 :         return acpi_table_parse_entries(ACPI_SIG_MADT,
     409                 :            :                                             sizeof(struct acpi_table_madt), id,
     410                 :            :                                             handler, max_entries);
     411                 :            : }
     412                 :            : 
     413                 :            : /**
     414                 :            :  * acpi_table_parse - find table with @id, run @handler on it
     415                 :            :  * @id: table id to find
     416                 :            :  * @handler: handler to run
     417                 :            :  *
     418                 :            :  * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
     419                 :            :  * run @handler on it.
     420                 :            :  *
     421                 :            :  * Return 0 if table found, -errno if not.
     422                 :            :  */
     423                 :        231 : int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
     424                 :            : {
     425                 :        231 :         struct acpi_table_header *table = NULL;
     426                 :            : 
     427         [ +  - ]:        231 :         if (acpi_disabled)
     428                 :            :                 return -ENODEV;
     429                 :            : 
     430         [ +  - ]:        231 :         if (!id || !handler)
     431                 :            :                 return -EINVAL;
     432                 :            : 
     433         [ +  + ]:        231 :         if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
     434                 :         42 :                 acpi_get_table(id, acpi_apic_instance, &table);
     435                 :            :         else
     436                 :        189 :                 acpi_get_table(id, 0, &table);
     437                 :            : 
     438         [ +  + ]:        231 :         if (table) {
     439                 :         84 :                 handler(table);
     440                 :         84 :                 acpi_put_table(table);
     441                 :         84 :                 return 0;
     442                 :            :         } else
     443                 :            :                 return -ENODEV;
     444                 :            : }
     445                 :            : 
     446                 :            : /*
     447                 :            :  * The BIOS is supposed to supply a single APIC/MADT,
     448                 :            :  * but some report two.  Provide a knob to use either.
     449                 :            :  * (don't you wish instance 0 and 1 were not the same?)
     450                 :            :  */
     451                 :         21 : static void __init check_multiple_madt(void)
     452                 :            : {
     453                 :         21 :         struct acpi_table_header *table = NULL;
     454                 :            : 
     455                 :         21 :         acpi_get_table(ACPI_SIG_MADT, 2, &table);
     456         [ -  + ]:         21 :         if (table) {
     457                 :          0 :                 pr_warn("BIOS bug: multiple APIC/MADT found, using %d\n",
     458                 :            :                         acpi_apic_instance);
     459         [ #  # ]:          0 :                 pr_warn("If \"acpi_apic_instance=%d\" works better, "
     460                 :            :                         "notify linux-acpi@vger.kernel.org\n",
     461                 :            :                         acpi_apic_instance ? 0 : 2);
     462                 :          0 :                 acpi_put_table(table);
     463                 :            : 
     464                 :            :         } else
     465                 :         21 :                 acpi_apic_instance = 0;
     466                 :            : 
     467                 :         21 :         return;
     468                 :            : }
     469                 :            : 
     470                 :            : static void acpi_table_taint(struct acpi_table_header *table)
     471                 :            : {
     472                 :            :         pr_warn("Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
     473                 :            :                 table->signature, table->oem_table_id);
     474                 :            :         add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
     475                 :            : }
     476                 :            : 
     477                 :            : #ifdef CONFIG_ACPI_TABLE_UPGRADE
     478                 :            : static u64 acpi_tables_addr;
     479                 :            : static int all_tables_size;
     480                 :            : 
     481                 :            : /* Copied from acpica/tbutils.c:acpi_tb_checksum() */
     482                 :          0 : static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
     483                 :            : {
     484                 :          0 :         u8 sum = 0;
     485                 :          0 :         u8 *end = buffer + length;
     486                 :            : 
     487         [ #  # ]:          0 :         while (buffer < end)
     488                 :          0 :                 sum = (u8) (sum + *(buffer++));
     489                 :          0 :         return sum;
     490                 :            : }
     491                 :            : 
     492                 :            : /* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
     493                 :            : static const char * const table_sigs[] = {
     494                 :            :         ACPI_SIG_BERT, ACPI_SIG_BGRT, ACPI_SIG_CPEP, ACPI_SIG_ECDT,
     495                 :            :         ACPI_SIG_EINJ, ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT,
     496                 :            :         ACPI_SIG_MSCT, ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT,
     497                 :            :         ACPI_SIG_ASF,  ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR,
     498                 :            :         ACPI_SIG_HPET, ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG,
     499                 :            :         ACPI_SIG_MCHI, ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI,
     500                 :            :         ACPI_SIG_TCPA, ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT,
     501                 :            :         ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT,
     502                 :            :         ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT,
     503                 :            :         ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT,
     504                 :            :         NULL };
     505                 :            : 
     506                 :            : #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)
     507                 :            : 
     508                 :            : #define NR_ACPI_INITRD_TABLES 64
     509                 :            : static struct cpio_data __initdata acpi_initrd_files[NR_ACPI_INITRD_TABLES];
     510                 :            : static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
     511                 :            : 
     512                 :            : #define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)
     513                 :            : 
     514                 :         21 : void __init acpi_table_upgrade(void)
     515                 :            : {
     516                 :         21 :         void *data;
     517                 :         21 :         size_t size;
     518                 :         21 :         int sig, no, table_nr = 0, total_offset = 0;
     519                 :         21 :         long offset = 0;
     520                 :         21 :         struct acpi_table_header *table;
     521                 :         21 :         char cpio_path[32] = "kernel/firmware/acpi/";
     522                 :         21 :         struct cpio_data file;
     523                 :            : 
     524                 :         21 :         if (IS_ENABLED(CONFIG_ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD)) {
     525                 :            :                 data = __initramfs_start;
     526                 :            :                 size = __initramfs_size;
     527                 :            :         } else {
     528                 :         21 :                 data = (void *)initrd_start;
     529                 :         21 :                 size = initrd_end - initrd_start;
     530                 :            :         }
     531                 :            : 
     532         [ -  + ]:         21 :         if (data == NULL || size == 0)
     533                 :         21 :                 return;
     534                 :            : 
     535         [ #  # ]:          0 :         for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) {
     536                 :          0 :                 file = find_cpio_data(cpio_path, data, size, &offset);
     537         [ #  # ]:          0 :                 if (!file.data)
     538                 :            :                         break;
     539                 :            : 
     540                 :          0 :                 data += offset;
     541                 :          0 :                 size -= offset;
     542                 :            : 
     543         [ #  # ]:          0 :                 if (file.size < sizeof(struct acpi_table_header)) {
     544                 :          0 :                         pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
     545                 :            :                                 cpio_path, file.name);
     546                 :          0 :                         continue;
     547                 :            :                 }
     548                 :            : 
     549                 :            :                 table = file.data;
     550                 :            : 
     551         [ #  # ]:          0 :                 for (sig = 0; table_sigs[sig]; sig++)
     552         [ #  # ]:          0 :                         if (!memcmp(table->signature, table_sigs[sig], 4))
     553                 :            :                                 break;
     554                 :            : 
     555         [ #  # ]:          0 :                 if (!table_sigs[sig]) {
     556                 :          0 :                         pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
     557                 :            :                                 cpio_path, file.name);
     558                 :          0 :                         continue;
     559                 :            :                 }
     560         [ #  # ]:          0 :                 if (file.size != table->length) {
     561                 :          0 :                         pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
     562                 :            :                                 cpio_path, file.name);
     563                 :          0 :                         continue;
     564                 :            :                 }
     565         [ #  # ]:          0 :                 if (acpi_table_checksum(file.data, table->length)) {
     566                 :          0 :                         pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
     567                 :            :                                 cpio_path, file.name);
     568                 :          0 :                         continue;
     569                 :            :                 }
     570                 :            : 
     571                 :          0 :                 pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
     572                 :            :                         table->signature, cpio_path, file.name, table->length);
     573                 :            : 
     574                 :          0 :                 all_tables_size += table->length;
     575                 :          0 :                 acpi_initrd_files[table_nr].data = file.data;
     576                 :          0 :                 acpi_initrd_files[table_nr].size = file.size;
     577                 :          0 :                 table_nr++;
     578                 :            :         }
     579         [ #  # ]:          0 :         if (table_nr == 0)
     580                 :            :                 return;
     581                 :            : 
     582         [ #  # ]:          0 :         if (security_locked_down(LOCKDOWN_ACPI_TABLES)) {
     583                 :          0 :                 pr_notice("kernel is locked down, ignoring table override\n");
     584                 :          0 :                 return;
     585                 :            :         }
     586                 :            : 
     587                 :          0 :         acpi_tables_addr =
     588                 :          0 :                 memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS,
     589                 :            :                                        all_tables_size, PAGE_SIZE);
     590         [ #  # ]:          0 :         if (!acpi_tables_addr) {
     591                 :          0 :                 WARN_ON(1);
     592                 :          0 :                 return;
     593                 :            :         }
     594                 :            :         /*
     595                 :            :          * Only calling e820_add_reserve does not work and the
     596                 :            :          * tables are invalid (memory got used) later.
     597                 :            :          * memblock_reserve works as expected and the tables won't get modified.
     598                 :            :          * But it's not enough on X86 because ioremap will
     599                 :            :          * complain later (used by acpi_os_map_memory) that the pages
     600                 :            :          * that should get mapped are not marked "reserved".
     601                 :            :          * Both memblock_reserve and e820__range_add (via arch_reserve_mem_area)
     602                 :            :          * works fine.
     603                 :            :          */
     604                 :          0 :         memblock_reserve(acpi_tables_addr, all_tables_size);
     605                 :          0 :         arch_reserve_mem_area(acpi_tables_addr, all_tables_size);
     606                 :            : 
     607                 :            :         /*
     608                 :            :          * early_ioremap only can remap 256k one time. If we map all
     609                 :            :          * tables one time, we will hit the limit. Need to map chunks
     610                 :            :          * one by one during copying the same as that in relocate_initrd().
     611                 :            :          */
     612         [ #  # ]:          0 :         for (no = 0; no < table_nr; no++) {
     613                 :          0 :                 unsigned char *src_p = acpi_initrd_files[no].data;
     614                 :          0 :                 phys_addr_t size = acpi_initrd_files[no].size;
     615                 :          0 :                 phys_addr_t dest_addr = acpi_tables_addr + total_offset;
     616                 :          0 :                 phys_addr_t slop, clen;
     617                 :          0 :                 char *dest_p;
     618                 :            : 
     619                 :          0 :                 total_offset += size;
     620                 :            : 
     621         [ #  # ]:          0 :                 while (size) {
     622                 :          0 :                         slop = dest_addr & ~PAGE_MASK;
     623                 :          0 :                         clen = size;
     624                 :          0 :                         if (clen > MAP_CHUNK_SIZE - slop)
     625                 :            :                                 clen = MAP_CHUNK_SIZE - slop;
     626                 :          0 :                         dest_p = early_memremap(dest_addr & PAGE_MASK,
     627                 :          0 :                                                 clen + slop);
     628                 :          0 :                         memcpy(dest_p + slop, src_p, clen);
     629                 :          0 :                         early_memunmap(dest_p, clen + slop);
     630                 :          0 :                         src_p += clen;
     631                 :          0 :                         dest_addr += clen;
     632                 :          0 :                         size -= clen;
     633                 :            :                 }
     634                 :            :         }
     635                 :            : }
     636                 :            : 
     637                 :            : static acpi_status
     638                 :        105 : acpi_table_initrd_override(struct acpi_table_header *existing_table,
     639                 :            :                            acpi_physical_address *address, u32 *length)
     640                 :            : {
     641                 :        105 :         int table_offset = 0;
     642                 :        105 :         int table_index = 0;
     643                 :        105 :         struct acpi_table_header *table;
     644                 :        105 :         u32 table_length;
     645                 :            : 
     646                 :        105 :         *length = 0;
     647                 :        105 :         *address = 0;
     648         [ -  + ]:        105 :         if (!acpi_tables_addr)
     649                 :            :                 return AE_OK;
     650                 :            : 
     651         [ #  # ]:          0 :         while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
     652                 :          0 :                 table = acpi_os_map_memory(acpi_tables_addr + table_offset,
     653                 :            :                                            ACPI_HEADER_SIZE);
     654         [ #  # ]:          0 :                 if (table_offset + table->length > all_tables_size) {
     655                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     656                 :          0 :                         WARN_ON(1);
     657                 :          0 :                         return AE_OK;
     658                 :            :                 }
     659                 :            : 
     660                 :          0 :                 table_length = table->length;
     661                 :            : 
     662                 :            :                 /* Only override tables matched */
     663         [ #  # ]:          0 :                 if (memcmp(existing_table->signature, table->signature, 4) ||
     664         [ #  # ]:          0 :                     memcmp(table->oem_id, existing_table->oem_id,
     665                 :          0 :                            ACPI_OEM_ID_SIZE) ||
     666         [ #  # ]:          0 :                     memcmp(table->oem_table_id, existing_table->oem_table_id,
     667                 :            :                            ACPI_OEM_TABLE_ID_SIZE)) {
     668                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     669                 :          0 :                         goto next_table;
     670                 :            :                 }
     671                 :            :                 /*
     672                 :            :                  * Mark the table to avoid being used in
     673                 :            :                  * acpi_table_initrd_scan() and check the revision.
     674                 :            :                  */
     675         [ #  # ]:          0 :                 if (test_and_set_bit(table_index, acpi_initrd_installed) ||
     676         [ #  # ]:          0 :                     existing_table->oem_revision >= table->oem_revision) {
     677                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     678                 :          0 :                         goto next_table;
     679                 :            :                 }
     680                 :            : 
     681                 :          0 :                 *length = table_length;
     682                 :          0 :                 *address = acpi_tables_addr + table_offset;
     683                 :          0 :                 pr_info("Table Upgrade: override [%4.4s-%6.6s-%8.8s]\n",
     684                 :            :                         table->signature, table->oem_id,
     685                 :            :                         table->oem_table_id);
     686                 :          0 :                 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     687                 :          0 :                 break;
     688                 :            : 
     689                 :          0 : next_table:
     690                 :          0 :                 table_offset += table_length;
     691                 :          0 :                 table_index++;
     692                 :            :         }
     693                 :            :         return AE_OK;
     694                 :            : }
     695                 :            : 
     696                 :         21 : static void __init acpi_table_initrd_scan(void)
     697                 :            : {
     698                 :         21 :         int table_offset = 0;
     699                 :         21 :         int table_index = 0;
     700                 :         21 :         u32 table_length;
     701                 :         21 :         struct acpi_table_header *table;
     702                 :            : 
     703         [ -  + ]:         21 :         if (!acpi_tables_addr)
     704                 :            :                 return;
     705                 :            : 
     706         [ #  # ]:          0 :         while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
     707                 :          0 :                 table = acpi_os_map_memory(acpi_tables_addr + table_offset,
     708                 :            :                                            ACPI_HEADER_SIZE);
     709         [ #  # ]:          0 :                 if (table_offset + table->length > all_tables_size) {
     710                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     711                 :          0 :                         WARN_ON(1);
     712                 :          0 :                         return;
     713                 :            :                 }
     714                 :            : 
     715                 :          0 :                 table_length = table->length;
     716                 :            : 
     717                 :            :                 /* Skip RSDT/XSDT which should only be used for override */
     718   [ #  #  #  # ]:          0 :                 if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_RSDT) ||
     719                 :            :                     ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_XSDT)) {
     720                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     721                 :          0 :                         goto next_table;
     722                 :            :                 }
     723                 :            :                 /*
     724                 :            :                  * Mark the table to avoid being used in
     725                 :            :                  * acpi_table_initrd_override(). Though this is not possible
     726                 :            :                  * because override is disabled in acpi_install_table().
     727                 :            :                  */
     728         [ #  # ]:          0 :                 if (test_and_set_bit(table_index, acpi_initrd_installed)) {
     729                 :          0 :                         acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     730                 :          0 :                         goto next_table;
     731                 :            :                 }
     732                 :            : 
     733                 :          0 :                 pr_info("Table Upgrade: install [%4.4s-%6.6s-%8.8s]\n",
     734                 :            :                         table->signature, table->oem_id,
     735                 :            :                         table->oem_table_id);
     736                 :          0 :                 acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
     737                 :          0 :                 acpi_install_table(acpi_tables_addr + table_offset, TRUE);
     738                 :          0 : next_table:
     739                 :          0 :                 table_offset += table_length;
     740                 :          0 :                 table_index++;
     741                 :            :         }
     742                 :            : }
     743                 :            : #else
     744                 :            : static acpi_status
     745                 :            : acpi_table_initrd_override(struct acpi_table_header *existing_table,
     746                 :            :                            acpi_physical_address *address,
     747                 :            :                            u32 *table_length)
     748                 :            : {
     749                 :            :         *table_length = 0;
     750                 :            :         *address = 0;
     751                 :            :         return AE_OK;
     752                 :            : }
     753                 :            : 
     754                 :            : static void __init acpi_table_initrd_scan(void)
     755                 :            : {
     756                 :            : }
     757                 :            : #endif /* CONFIG_ACPI_TABLE_UPGRADE */
     758                 :            : 
     759                 :            : acpi_status
     760                 :        105 : acpi_os_physical_table_override(struct acpi_table_header *existing_table,
     761                 :            :                                 acpi_physical_address *address,
     762                 :            :                                 u32 *table_length)
     763                 :            : {
     764                 :        105 :         return acpi_table_initrd_override(existing_table, address,
     765                 :            :                                           table_length);
     766                 :            : }
     767                 :            : 
     768                 :            : #ifdef CONFIG_ACPI_CUSTOM_DSDT
     769                 :            : static void *amlcode __attribute__ ((weakref("AmlCode")));
     770                 :            : static void *dsdt_amlcode __attribute__ ((weakref("dsdt_aml_code")));
     771                 :            : #endif
     772                 :            : 
     773                 :        105 : acpi_status acpi_os_table_override(struct acpi_table_header *existing_table,
     774                 :            :                        struct acpi_table_header **new_table)
     775                 :            : {
     776         [ +  - ]:        105 :         if (!existing_table || !new_table)
     777                 :            :                 return AE_BAD_PARAMETER;
     778                 :            : 
     779                 :        105 :         *new_table = NULL;
     780                 :            : 
     781                 :            : #ifdef CONFIG_ACPI_CUSTOM_DSDT
     782                 :            :         if (!strncmp(existing_table->signature, "DSDT", 4)) {
     783                 :            :                 *new_table = (struct acpi_table_header *)&amlcode;
     784                 :            :                 if (!(*new_table))
     785                 :            :                         *new_table = (struct acpi_table_header *)&dsdt_amlcode;
     786                 :            :         }
     787                 :            : #endif
     788                 :        105 :         if (*new_table != NULL)
     789                 :            :                 acpi_table_taint(existing_table);
     790                 :        105 :         return AE_OK;
     791                 :            : }
     792                 :            : 
     793                 :            : /*
     794                 :            :  * acpi_table_init()
     795                 :            :  *
     796                 :            :  * find RSDP, find and checksum SDT/XSDT.
     797                 :            :  * checksum all tables, print SDT/XSDT
     798                 :            :  *
     799                 :            :  * result: sdt_entry[] is initialized
     800                 :            :  */
     801                 :            : 
     802                 :         21 : int __init acpi_table_init(void)
     803                 :            : {
     804                 :         21 :         acpi_status status;
     805                 :            : 
     806         [ -  + ]:         21 :         if (acpi_verify_table_checksum) {
     807                 :          0 :                 pr_info("Early table checksum verification enabled\n");
     808                 :          0 :                 acpi_gbl_enable_table_validation = TRUE;
     809                 :            :         } else {
     810                 :         21 :                 pr_info("Early table checksum verification disabled\n");
     811                 :         21 :                 acpi_gbl_enable_table_validation = FALSE;
     812                 :            :         }
     813                 :            : 
     814                 :         21 :         status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
     815         [ +  - ]:         21 :         if (ACPI_FAILURE(status))
     816                 :            :                 return -EINVAL;
     817                 :         21 :         acpi_table_initrd_scan();
     818                 :            : 
     819                 :         21 :         check_multiple_madt();
     820                 :         21 :         return 0;
     821                 :            : }
     822                 :            : 
     823                 :          0 : static int __init acpi_parse_apic_instance(char *str)
     824                 :            : {
     825         [ #  # ]:          0 :         if (!str)
     826                 :            :                 return -EINVAL;
     827                 :            : 
     828         [ #  # ]:          0 :         if (kstrtoint(str, 0, &acpi_apic_instance))
     829                 :            :                 return -EINVAL;
     830                 :            : 
     831                 :          0 :         pr_notice("Shall use APIC/MADT table %d\n", acpi_apic_instance);
     832                 :            : 
     833                 :          0 :         return 0;
     834                 :            : }
     835                 :            : early_param("acpi_apic_instance", acpi_parse_apic_instance);
     836                 :            : 
     837                 :          0 : static int __init acpi_force_table_verification_setup(char *s)
     838                 :            : {
     839                 :          0 :         acpi_verify_table_checksum = true;
     840                 :            : 
     841                 :          0 :         return 0;
     842                 :            : }
     843                 :            : early_param("acpi_force_table_verification", acpi_force_table_verification_setup);
     844                 :            : 
     845                 :          0 : static int __init acpi_force_32bit_fadt_addr(char *s)
     846                 :            : {
     847                 :          0 :         pr_info("Forcing 32 Bit FADT addresses\n");
     848                 :          0 :         acpi_gbl_use32_bit_fadt_addresses = TRUE;
     849                 :            : 
     850                 :          0 :         return 0;
     851                 :            : }
     852                 :            : early_param("acpi_force_32bit_fadt_addr", acpi_force_32bit_fadt_addr);

Generated by: LCOV version 1.14