[PATCH] ext2: prevent div-by-zero on corrupted fs
[linux-2.6] / drivers / acpi / tables.c
1 /*
2  *  acpi_tables.c - ACPI Boot-Time Table Parsing
3  *
4  *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
5  *
6  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23  *
24  */
25
26 #include <linux/init.h>
27 #include <linux/kernel.h>
28 #include <linux/sched.h>
29 #include <linux/smp.h>
30 #include <linux/string.h>
31 #include <linux/types.h>
32 #include <linux/irq.h>
33 #include <linux/errno.h>
34 #include <linux/acpi.h>
35 #include <linux/bootmem.h>
36
37 #define PREFIX                  "ACPI: "
38
39 #define ACPI_MAX_TABLES         128
40
41 static char *acpi_table_signatures[ACPI_TABLE_COUNT] = {
42         [ACPI_TABLE_UNKNOWN] = "????",
43         [ACPI_APIC] = "APIC",
44         [ACPI_BOOT] = "BOOT",
45         [ACPI_DBGP] = "DBGP",
46         [ACPI_DSDT] = "DSDT",
47         [ACPI_ECDT] = "ECDT",
48         [ACPI_ETDT] = "ETDT",
49         [ACPI_FADT] = "FACP",
50         [ACPI_FACS] = "FACS",
51         [ACPI_OEMX] = "OEM",
52         [ACPI_PSDT] = "PSDT",
53         [ACPI_SBST] = "SBST",
54         [ACPI_SLIT] = "SLIT",
55         [ACPI_SPCR] = "SPCR",
56         [ACPI_SRAT] = "SRAT",
57         [ACPI_SSDT] = "SSDT",
58         [ACPI_SPMI] = "SPMI",
59         [ACPI_HPET] = "HPET",
60         [ACPI_MCFG] = "MCFG",
61 };
62
63 static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
64 static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };
65
66 /* System Description Table (RSDT/XSDT) */
67 struct acpi_table_sdt {
68         unsigned long pa;
69         enum acpi_table_id id;
70         unsigned long size;
71 } __attribute__ ((packed));
72
73 static unsigned long sdt_pa;    /* Physical Address */
74 static unsigned long sdt_count; /* Table count */
75
76 static struct acpi_table_sdt sdt_entry[ACPI_MAX_TABLES] __initdata;
77
78 void acpi_table_print(struct acpi_table_header *header, unsigned long phys_addr)
79 {
80         char *name = NULL;
81
82         if (!header)
83                 return;
84
85         /* Some table signatures aren't good table names */
86
87         if (!strncmp((char *)&header->signature,
88                      acpi_table_signatures[ACPI_APIC],
89                      sizeof(header->signature))) {
90                 name = "MADT";
91         } else if (!strncmp((char *)&header->signature,
92                             acpi_table_signatures[ACPI_FADT],
93                             sizeof(header->signature))) {
94                 name = "FADT";
95         } else
96                 name = header->signature;
97
98         printk(KERN_DEBUG PREFIX
99                "%.4s (v%3.3d %6.6s %8.8s 0x%08x %.4s 0x%08x) @ 0x%p\n", name,
100                header->revision, header->oem_id, header->oem_table_id,
101                header->oem_revision, header->asl_compiler_id,
102                header->asl_compiler_revision, (void *)phys_addr);
103 }
104
105 void acpi_table_print_madt_entry(acpi_table_entry_header * header)
106 {
107         if (!header)
108                 return;
109
110         switch (header->type) {
111
112         case ACPI_MADT_LAPIC:
113                 {
114                         struct acpi_table_lapic *p =
115                             (struct acpi_table_lapic *)header;
116                         printk(KERN_INFO PREFIX
117                                "LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
118                                p->acpi_id, p->id,
119                                p->flags.enabled ? "enabled" : "disabled");
120                 }
121                 break;
122
123         case ACPI_MADT_IOAPIC:
124                 {
125                         struct acpi_table_ioapic *p =
126                             (struct acpi_table_ioapic *)header;
127                         printk(KERN_INFO PREFIX
128                                "IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
129                                p->id, p->address, p->global_irq_base);
130                 }
131                 break;
132
133         case ACPI_MADT_INT_SRC_OVR:
134                 {
135                         struct acpi_table_int_src_ovr *p =
136                             (struct acpi_table_int_src_ovr *)header;
137                         printk(KERN_INFO PREFIX
138                                "INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
139                                p->bus, p->bus_irq, p->global_irq,
140                                mps_inti_flags_polarity[p->flags.polarity],
141                                mps_inti_flags_trigger[p->flags.trigger]);
142                         if (p->flags.reserved)
143                                 printk(KERN_INFO PREFIX
144                                        "INT_SRC_OVR unexpected reserved flags: 0x%x\n",
145                                        p->flags.reserved);
146
147                 }
148                 break;
149
150         case ACPI_MADT_NMI_SRC:
151                 {
152                         struct acpi_table_nmi_src *p =
153                             (struct acpi_table_nmi_src *)header;
154                         printk(KERN_INFO PREFIX
155                                "NMI_SRC (%s %s global_irq %d)\n",
156                                mps_inti_flags_polarity[p->flags.polarity],
157                                mps_inti_flags_trigger[p->flags.trigger],
158                                p->global_irq);
159                 }
160                 break;
161
162         case ACPI_MADT_LAPIC_NMI:
163                 {
164                         struct acpi_table_lapic_nmi *p =
165                             (struct acpi_table_lapic_nmi *)header;
166                         printk(KERN_INFO PREFIX
167                                "LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
168                                p->acpi_id,
169                                mps_inti_flags_polarity[p->flags.polarity],
170                                mps_inti_flags_trigger[p->flags.trigger],
171                                p->lint);
172                 }
173                 break;
174
175         case ACPI_MADT_LAPIC_ADDR_OVR:
176                 {
177                         struct acpi_table_lapic_addr_ovr *p =
178                             (struct acpi_table_lapic_addr_ovr *)header;
179                         printk(KERN_INFO PREFIX
180                                "LAPIC_ADDR_OVR (address[%p])\n",
181                                (void *)(unsigned long)p->address);
182                 }
183                 break;
184
185         case ACPI_MADT_IOSAPIC:
186                 {
187                         struct acpi_table_iosapic *p =
188                             (struct acpi_table_iosapic *)header;
189                         printk(KERN_INFO PREFIX
190                                "IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
191                                p->id, (void *)(unsigned long)p->address,
192                                p->global_irq_base);
193                 }
194                 break;
195
196         case ACPI_MADT_LSAPIC:
197                 {
198                         struct acpi_table_lsapic *p =
199                             (struct acpi_table_lsapic *)header;
200                         printk(KERN_INFO PREFIX
201                                "LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
202                                p->acpi_id, p->id, p->eid,
203                                p->flags.enabled ? "enabled" : "disabled");
204                 }
205                 break;
206
207         case ACPI_MADT_PLAT_INT_SRC:
208                 {
209                         struct acpi_table_plat_int_src *p =
210                             (struct acpi_table_plat_int_src *)header;
211                         printk(KERN_INFO PREFIX
212                                "PLAT_INT_SRC (%s %s type[0x%x] id[0x%04x] eid[0x%x] iosapic_vector[0x%x] global_irq[0x%x]\n",
213                                mps_inti_flags_polarity[p->flags.polarity],
214                                mps_inti_flags_trigger[p->flags.trigger],
215                                p->type, p->id, p->eid, p->iosapic_vector,
216                                p->global_irq);
217                 }
218                 break;
219
220         default:
221                 printk(KERN_WARNING PREFIX
222                        "Found unsupported MADT entry (type = 0x%x)\n",
223                        header->type);
224                 break;
225         }
226 }
227
228 static int
229 acpi_table_compute_checksum(void *table_pointer, unsigned long length)
230 {
231         u8 *p = (u8 *) table_pointer;
232         unsigned long remains = length;
233         unsigned long sum = 0;
234
235         if (!p || !length)
236                 return -EINVAL;
237
238         while (remains--)
239                 sum += *p++;
240
241         return (sum & 0xFF);
242 }
243
244 /*
245  * acpi_get_table_header_early()
246  * for acpi_blacklisted(), acpi_table_get_sdt()
247  */
248 int __init
249 acpi_get_table_header_early(enum acpi_table_id id,
250                             struct acpi_table_header **header)
251 {
252         unsigned int i;
253         enum acpi_table_id temp_id;
254
255         /* DSDT is different from the rest */
256         if (id == ACPI_DSDT)
257                 temp_id = ACPI_FADT;
258         else
259                 temp_id = id;
260
261         /* Locate the table. */
262
263         for (i = 0; i < sdt_count; i++) {
264                 if (sdt_entry[i].id != temp_id)
265                         continue;
266                 *header = (void *)
267                     __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
268                 if (!*header) {
269                         printk(KERN_WARNING PREFIX "Unable to map %s\n",
270                                acpi_table_signatures[temp_id]);
271                         return -ENODEV;
272                 }
273                 break;
274         }
275
276         if (!*header) {
277                 printk(KERN_WARNING PREFIX "%s not present\n",
278                        acpi_table_signatures[id]);
279                 return -ENODEV;
280         }
281
282         /* Map the DSDT header via the pointer in the FADT */
283         if (id == ACPI_DSDT) {
284                 struct fadt_descriptor *fadt =
285                     (struct fadt_descriptor *)*header;
286
287                 if (fadt->revision == 3 && fadt->Xdsdt) {
288                         *header = (void *)__acpi_map_table(fadt->Xdsdt,
289                                                            sizeof(struct
290                                                                   acpi_table_header));
291                 } else if (fadt->V1_dsdt) {
292                         *header = (void *)__acpi_map_table(fadt->V1_dsdt,
293                                                            sizeof(struct
294                                                                   acpi_table_header));
295                 } else
296                         *header = NULL;
297
298                 if (!*header) {
299                         printk(KERN_WARNING PREFIX "Unable to map DSDT\n");
300                         return -ENODEV;
301                 }
302         }
303
304         return 0;
305 }
306
307 int __init
308 acpi_table_parse_madt_family(enum acpi_table_id id,
309                              unsigned long madt_size,
310                              int entry_id,
311                              acpi_madt_entry_handler handler,
312                              unsigned int max_entries)
313 {
314         void *madt = NULL;
315         acpi_table_entry_header *entry;
316         unsigned int count = 0;
317         unsigned long madt_end;
318         unsigned int i;
319
320         if (!handler)
321                 return -EINVAL;
322
323         /* Locate the MADT (if exists). There should only be one. */
324
325         for (i = 0; i < sdt_count; i++) {
326                 if (sdt_entry[i].id != id)
327                         continue;
328                 madt = (void *)
329                     __acpi_map_table(sdt_entry[i].pa, sdt_entry[i].size);
330                 if (!madt) {
331                         printk(KERN_WARNING PREFIX "Unable to map %s\n",
332                                acpi_table_signatures[id]);
333                         return -ENODEV;
334                 }
335                 break;
336         }
337
338         if (!madt) {
339                 printk(KERN_WARNING PREFIX "%s not present\n",
340                        acpi_table_signatures[id]);
341                 return -ENODEV;
342         }
343
344         madt_end = (unsigned long)madt + sdt_entry[i].size;
345
346         /* Parse all entries looking for a match. */
347
348         entry = (acpi_table_entry_header *)
349             ((unsigned long)madt + madt_size);
350
351         while (((unsigned long)entry) + sizeof(acpi_table_entry_header) <
352                madt_end) {
353                 if (entry->type == entry_id
354                     && (!max_entries || count++ < max_entries))
355                         if (handler(entry, madt_end))
356                                 return -EINVAL;
357
358                 entry = (acpi_table_entry_header *)
359                     ((unsigned long)entry + entry->length);
360         }
361         if (max_entries && count > max_entries) {
362                 printk(KERN_WARNING PREFIX "[%s:0x%02x] ignored %i entries of "
363                        "%i found\n", acpi_table_signatures[id], entry_id,
364                        count - max_entries, count);
365         }
366
367         return count;
368 }
369
370 int __init
371 acpi_table_parse_madt(enum acpi_madt_entry_id id,
372                       acpi_madt_entry_handler handler, unsigned int max_entries)
373 {
374         return acpi_table_parse_madt_family(ACPI_APIC,
375                                             sizeof(struct acpi_table_madt), id,
376                                             handler, max_entries);
377 }
378
379 int __init acpi_table_parse(enum acpi_table_id id, acpi_table_handler handler)
380 {
381         int count = 0;
382         unsigned int i = 0;
383
384         if (!handler)
385                 return -EINVAL;
386
387         for (i = 0; i < sdt_count; i++) {
388                 if (sdt_entry[i].id != id)
389                         continue;
390                 count++;
391                 if (count == 1)
392                         handler(sdt_entry[i].pa, sdt_entry[i].size);
393
394                 else
395                         printk(KERN_WARNING PREFIX
396                                "%d duplicate %s table ignored.\n", count,
397                                acpi_table_signatures[id]);
398         }
399
400         return count;
401 }
402
403 static int __init acpi_table_get_sdt(struct acpi_table_rsdp *rsdp)
404 {
405         struct acpi_table_header *header = NULL;
406         unsigned int i, id = 0;
407
408         if (!rsdp)
409                 return -EINVAL;
410
411         /* First check XSDT (but only on ACPI 2.0-compatible systems) */
412
413         if ((rsdp->revision >= 2) &&
414             (((struct acpi20_table_rsdp *)rsdp)->xsdt_address)) {
415
416                 struct acpi_table_xsdt *mapped_xsdt = NULL;
417
418                 sdt_pa = ((struct acpi20_table_rsdp *)rsdp)->xsdt_address;
419
420                 /* map in just the header */
421                 header = (struct acpi_table_header *)
422                     __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
423
424                 if (!header) {
425                         printk(KERN_WARNING PREFIX
426                                "Unable to map XSDT header\n");
427                         return -ENODEV;
428                 }
429
430                 /* remap in the entire table before processing */
431                 mapped_xsdt = (struct acpi_table_xsdt *)
432                     __acpi_map_table(sdt_pa, header->length);
433                 if (!mapped_xsdt) {
434                         printk(KERN_WARNING PREFIX "Unable to map XSDT\n");
435                         return -ENODEV;
436                 }
437                 header = &mapped_xsdt->header;
438
439                 if (strncmp(header->signature, "XSDT", 4)) {
440                         printk(KERN_WARNING PREFIX
441                                "XSDT signature incorrect\n");
442                         return -ENODEV;
443                 }
444
445                 if (acpi_table_compute_checksum(header, header->length)) {
446                         printk(KERN_WARNING PREFIX "Invalid XSDT checksum\n");
447                         return -ENODEV;
448                 }
449
450                 sdt_count =
451                     (header->length - sizeof(struct acpi_table_header)) >> 3;
452                 if (sdt_count > ACPI_MAX_TABLES) {
453                         printk(KERN_WARNING PREFIX
454                                "Truncated %lu XSDT entries\n",
455                                (sdt_count - ACPI_MAX_TABLES));
456                         sdt_count = ACPI_MAX_TABLES;
457                 }
458
459                 for (i = 0; i < sdt_count; i++)
460                         sdt_entry[i].pa = (unsigned long)mapped_xsdt->entry[i];
461         }
462
463         /* Then check RSDT */
464
465         else if (rsdp->rsdt_address) {
466
467                 struct acpi_table_rsdt *mapped_rsdt = NULL;
468
469                 sdt_pa = rsdp->rsdt_address;
470
471                 /* map in just the header */
472                 header = (struct acpi_table_header *)
473                     __acpi_map_table(sdt_pa, sizeof(struct acpi_table_header));
474                 if (!header) {
475                         printk(KERN_WARNING PREFIX
476                                "Unable to map RSDT header\n");
477                         return -ENODEV;
478                 }
479
480                 /* remap in the entire table before processing */
481                 mapped_rsdt = (struct acpi_table_rsdt *)
482                     __acpi_map_table(sdt_pa, header->length);
483                 if (!mapped_rsdt) {
484                         printk(KERN_WARNING PREFIX "Unable to map RSDT\n");
485                         return -ENODEV;
486                 }
487                 header = &mapped_rsdt->header;
488
489                 if (strncmp(header->signature, "RSDT", 4)) {
490                         printk(KERN_WARNING PREFIX
491                                "RSDT signature incorrect\n");
492                         return -ENODEV;
493                 }
494
495                 if (acpi_table_compute_checksum(header, header->length)) {
496                         printk(KERN_WARNING PREFIX "Invalid RSDT checksum\n");
497                         return -ENODEV;
498                 }
499
500                 sdt_count =
501                     (header->length - sizeof(struct acpi_table_header)) >> 2;
502                 if (sdt_count > ACPI_MAX_TABLES) {
503                         printk(KERN_WARNING PREFIX
504                                "Truncated %lu RSDT entries\n",
505                                (sdt_count - ACPI_MAX_TABLES));
506                         sdt_count = ACPI_MAX_TABLES;
507                 }
508
509                 for (i = 0; i < sdt_count; i++)
510                         sdt_entry[i].pa = (unsigned long)mapped_rsdt->entry[i];
511         }
512
513         else {
514                 printk(KERN_WARNING PREFIX
515                        "No System Description Table (RSDT/XSDT) specified in RSDP\n");
516                 return -ENODEV;
517         }
518
519         acpi_table_print(header, sdt_pa);
520
521         for (i = 0; i < sdt_count; i++) {
522
523                 /* map in just the header */
524                 header = (struct acpi_table_header *)
525                     __acpi_map_table(sdt_entry[i].pa,
526                                      sizeof(struct acpi_table_header));
527                 if (!header)
528                         continue;
529
530                 /* remap in the entire table before processing */
531                 header = (struct acpi_table_header *)
532                     __acpi_map_table(sdt_entry[i].pa, header->length);
533                 if (!header)
534                         continue;
535
536                 acpi_table_print(header, sdt_entry[i].pa);
537
538                 if (acpi_table_compute_checksum(header, header->length)) {
539                         printk(KERN_WARNING "  >>> ERROR: Invalid checksum\n");
540                         continue;
541                 }
542
543                 sdt_entry[i].size = header->length;
544
545                 for (id = 0; id < ACPI_TABLE_COUNT; id++) {
546                         if (!strncmp((char *)&header->signature,
547                                      acpi_table_signatures[id],
548                                      sizeof(header->signature))) {
549                                 sdt_entry[i].id = id;
550                         }
551                 }
552         }
553
554         /* 
555          * The DSDT is *not* in the RSDT (why not? no idea.) but we want
556          * to print its info, because this is what people usually blacklist
557          * against. Unfortunately, we don't know the phys_addr, so just
558          * print 0. Maybe no one will notice.
559          */
560         if (!acpi_get_table_header_early(ACPI_DSDT, &header))
561                 acpi_table_print(header, 0);
562
563         return 0;
564 }
565
566 /*
567  * acpi_table_init()
568  *
569  * find RSDP, find and checksum SDT/XSDT.
570  * checksum all tables, print SDT/XSDT
571  * 
572  * result: sdt_entry[] is initialized
573  */
574
575 int __init acpi_table_init(void)
576 {
577         struct acpi_table_rsdp *rsdp = NULL;
578         unsigned long rsdp_phys = 0;
579         int result = 0;
580
581         /* Locate and map the Root System Description Table (RSDP) */
582
583         rsdp_phys = acpi_find_rsdp();
584         if (!rsdp_phys) {
585                 printk(KERN_ERR PREFIX "Unable to locate RSDP\n");
586                 return -ENODEV;
587         }
588
589         rsdp = (struct acpi_table_rsdp *)__acpi_map_table(rsdp_phys,
590                 sizeof(struct acpi_table_rsdp));
591         if (!rsdp) {
592                 printk(KERN_WARNING PREFIX "Unable to map RSDP\n");
593                 return -ENODEV;
594         }
595
596         printk(KERN_DEBUG PREFIX
597                "RSDP (v%3.3d %6.6s                                ) @ 0x%p\n",
598                rsdp->revision, rsdp->oem_id, (void *)rsdp_phys);
599
600         if (rsdp->revision < 2)
601                 result =
602                     acpi_table_compute_checksum(rsdp,
603                                                 sizeof(struct acpi_table_rsdp));
604         else
605                 result =
606                     acpi_table_compute_checksum(rsdp,
607                                                 ((struct acpi20_table_rsdp *)
608                                                  rsdp)->length);
609
610         if (result) {
611                 printk(KERN_WARNING "  >>> ERROR: Invalid checksum\n");
612                 return -ENODEV;
613         }
614
615         /* Locate and map the System Description table (RSDT/XSDT) */
616
617         if (acpi_table_get_sdt(rsdp))
618                 return -ENODEV;
619
620         return 0;
621 }