tables.c 20.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 *  acpi_tables.c - ACPI Boot-Time Table Parsing
 *
 *  Copyright (C) 2001 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *
 */

22 23
/* Uncomment next line to get verbose printout */
/* #define DEBUG */
24 25
#define pr_fmt(fmt) "ACPI: " fmt

L
Linus Torvalds 已提交
26 27 28 29 30 31 32 33 34
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/smp.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/irq.h>
#include <linux/errno.h>
#include <linux/acpi.h>
#include <linux/bootmem.h>
35 36
#include <linux/earlycpio.h>
#include <linux/memblock.h>
37
#include <linux/initrd.h>
38
#include "internal.h"
L
Linus Torvalds 已提交
39

40 41 42 43
#ifdef CONFIG_ACPI_CUSTOM_DSDT
#include CONFIG_ACPI_CUSTOM_DSDT_FILE
#endif

44
#define ACPI_MAX_TABLES		128
L
Linus Torvalds 已提交
45 46 47 48

static char *mps_inti_flags_polarity[] = { "dfl", "high", "res", "low" };
static char *mps_inti_flags_trigger[] = { "dfl", "edge", "res", "level" };

49
static struct acpi_table_desc initial_tables[ACPI_MAX_TABLES] __initdata;
L
Linus Torvalds 已提交
50

51
static int acpi_apic_instance __initdata;
L
Len Brown 已提交
52

53 54 55 56 57 58
/*
 * Disable table checksum verification for the early stage due to the size
 * limitation of the current x86 early mapping implementation.
 */
static bool acpi_verify_table_checksum __initdata = false;

L
Len Brown 已提交
59
void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
L
Linus Torvalds 已提交
60 61 62 63 64 65
{
	if (!header)
		return;

	switch (header->type) {

66
	case ACPI_MADT_TYPE_LOCAL_APIC:
L
Len Brown 已提交
67
		{
68 69
			struct acpi_madt_local_apic *p =
			    (struct acpi_madt_local_apic *)header;
70 71 72
			pr_debug("LAPIC (acpi_id[0x%02x] lapic_id[0x%02x] %s)\n",
				 p->processor_id, p->id,
				 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
L
Len Brown 已提交
73
		}
L
Linus Torvalds 已提交
74 75
		break;

76 77 78 79
	case ACPI_MADT_TYPE_LOCAL_X2APIC:
		{
			struct acpi_madt_local_x2apic *p =
			    (struct acpi_madt_local_x2apic *)header;
80 81 82
			pr_debug("X2APIC (apic_id[0x%02x] uid[0x%02x] %s)\n",
				 p->local_apic_id, p->uid,
				 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
83 84 85
		}
		break;

86
	case ACPI_MADT_TYPE_IO_APIC:
L
Len Brown 已提交
87
		{
88 89
			struct acpi_madt_io_apic *p =
			    (struct acpi_madt_io_apic *)header;
90 91
			pr_debug("IOAPIC (id[0x%02x] address[0x%08x] gsi_base[%d])\n",
				 p->id, p->address, p->global_irq_base);
L
Len Brown 已提交
92
		}
L
Linus Torvalds 已提交
93 94
		break;

95
	case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
L
Len Brown 已提交
96
		{
97 98
			struct acpi_madt_interrupt_override *p =
			    (struct acpi_madt_interrupt_override *)header;
99 100 101 102
			pr_info("INT_SRC_OVR (bus %d bus_irq %d global_irq %d %s %s)\n",
				p->bus, p->source_irq, p->global_irq,
				mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
				mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2]);
103 104
			if (p->inti_flags  &
			    ~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK))
105 106
				pr_info("INT_SRC_OVR unexpected reserved flags: 0x%x\n",
					p->inti_flags  &
107
					~(ACPI_MADT_POLARITY_MASK | ACPI_MADT_TRIGGER_MASK));
L
Len Brown 已提交
108
		}
L
Linus Torvalds 已提交
109 110
		break;

111
	case ACPI_MADT_TYPE_NMI_SOURCE:
L
Len Brown 已提交
112
		{
113 114
			struct acpi_madt_nmi_source *p =
			    (struct acpi_madt_nmi_source *)header;
115 116 117 118
			pr_info("NMI_SRC (%s %s global_irq %d)\n",
				mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
				mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
				p->global_irq);
L
Len Brown 已提交
119
		}
L
Linus Torvalds 已提交
120 121
		break;

122
	case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
L
Len Brown 已提交
123
		{
124 125
			struct acpi_madt_local_apic_nmi *p =
			    (struct acpi_madt_local_apic_nmi *)header;
126 127 128 129 130
			pr_info("LAPIC_NMI (acpi_id[0x%02x] %s %s lint[0x%x])\n",
				p->processor_id,
				mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK	],
				mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
				p->lint);
131 132 133 134 135 136 137 138 139 140 141 142
		}
		break;

	case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
		{
			u16 polarity, trigger;
			struct acpi_madt_local_x2apic_nmi *p =
			    (struct acpi_madt_local_x2apic_nmi *)header;

			polarity = p->inti_flags & ACPI_MADT_POLARITY_MASK;
			trigger = (p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2;

143 144 145 146 147
			pr_info("X2APIC_NMI (uid[0x%02x] %s %s lint[0x%x])\n",
				p->uid,
				mps_inti_flags_polarity[polarity],
				mps_inti_flags_trigger[trigger],
				p->lint);
L
Len Brown 已提交
148
		}
L
Linus Torvalds 已提交
149 150
		break;

151
	case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
L
Len Brown 已提交
152
		{
153 154
			struct acpi_madt_local_apic_override *p =
			    (struct acpi_madt_local_apic_override *)header;
155 156
			pr_info("LAPIC_ADDR_OVR (address[%p])\n",
				(void *)(unsigned long)p->address);
L
Len Brown 已提交
157
		}
L
Linus Torvalds 已提交
158 159
		break;

160
	case ACPI_MADT_TYPE_IO_SAPIC:
L
Len Brown 已提交
161
		{
162 163
			struct acpi_madt_io_sapic *p =
			    (struct acpi_madt_io_sapic *)header;
164 165 166
			pr_debug("IOSAPIC (id[0x%x] address[%p] gsi_base[%d])\n",
				 p->id, (void *)(unsigned long)p->address,
				 p->global_irq_base);
L
Len Brown 已提交
167
		}
L
Linus Torvalds 已提交
168 169
		break;

170
	case ACPI_MADT_TYPE_LOCAL_SAPIC:
L
Len Brown 已提交
171
		{
172 173
			struct acpi_madt_local_sapic *p =
			    (struct acpi_madt_local_sapic *)header;
174 175 176
			pr_debug("LSAPIC (acpi_id[0x%02x] lsapic_id[0x%02x] lsapic_eid[0x%02x] %s)\n",
				 p->processor_id, p->id, p->eid,
				 (p->lapic_flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
L
Len Brown 已提交
177
		}
L
Linus Torvalds 已提交
178 179
		break;

180
	case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
L
Len Brown 已提交
181
		{
182 183
			struct acpi_madt_interrupt_source *p =
			    (struct acpi_madt_interrupt_source *)header;
184 185 186 187 188
			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",
				mps_inti_flags_polarity[p->inti_flags & ACPI_MADT_POLARITY_MASK],
				mps_inti_flags_trigger[(p->inti_flags & ACPI_MADT_TRIGGER_MASK) >> 2],
				p->type, p->id, p->eid, p->io_sapic_vector,
				p->global_irq);
L
Len Brown 已提交
189
		}
L
Linus Torvalds 已提交
190 191
		break;

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
	case ACPI_MADT_TYPE_GENERIC_INTERRUPT:
		{
			struct acpi_madt_generic_interrupt *p =
				(struct acpi_madt_generic_interrupt *)header;
			pr_debug("GICC (acpi_id[0x%04x] address[%llx] MPIDR[0x%llx] %s)\n",
				 p->uid, p->base_address,
				 p->arm_mpidr,
				 (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");

		}
		break;

	case ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR:
		{
			struct acpi_madt_generic_distributor *p =
				(struct acpi_madt_generic_distributor *)header;
			pr_debug("GIC Distributor (gic_id[0x%04x] address[%llx] gsi_base[%d])\n",
				 p->gic_id, p->base_address,
				 p->global_irq_base);
		}
		break;

L
Linus Torvalds 已提交
214
	default:
215 216
		pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
			header->type);
L
Linus Torvalds 已提交
217 218 219 220
		break;
	}
}

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
/**
 * acpi_parse_entries_array - for each proc_num find a suitable subtable
 *
 * @id: table id (for debugging purposes)
 * @table_size: single entry size
 * @table_header: where does the table start?
 * @proc: array of acpi_subtable_proc struct containing entry id
 *        and associated handler with it
 * @proc_num: how big proc is?
 * @max_entries: how many entries can we process?
 *
 * For each proc_num find a subtable with proc->id and run proc->handler
 * on it. Assumption is that there's only single handler for particular
 * entry id.
 *
 * On success returns sum of all matching entries for all proc handlers.
 * Otherwise, -ENODEV or -EINVAL is returned.
 */
static int __init
acpi_parse_entries_array(char *id, unsigned long table_size,
241
		struct acpi_table_header *table_header,
242 243
		struct acpi_subtable_proc *proc, int proc_num,
		unsigned int max_entries)
L
Linus Torvalds 已提交
244
{
245
	struct acpi_subtable_header *entry;
246
	unsigned long table_end;
247
	int count = 0;
248
	int errs = 0;
249
	int i;
L
Linus Torvalds 已提交
250

251
	if (acpi_disabled)
252 253
		return -ENODEV;

254
	if (!id)
L
Linus Torvalds 已提交
255 256
		return -EINVAL;

257 258
	if (!table_size)
		return -EINVAL;
L
Linus Torvalds 已提交
259

260
	if (!table_header) {
261
		pr_warn("%4.4s not present\n", id);
L
Linus Torvalds 已提交
262 263 264
		return -ENODEV;
	}

265
	table_end = (unsigned long)table_header + table_header->length;
L
Linus Torvalds 已提交
266 267 268

	/* Parse all entries looking for a match. */

269
	entry = (struct acpi_subtable_header *)
270
	    ((unsigned long)table_header + table_size);
L
Linus Torvalds 已提交
271

272
	while (((unsigned long)entry) + sizeof(struct acpi_subtable_header) <
273
	       table_end) {
274 275 276 277 278 279
		if (max_entries && count >= max_entries)
			break;

		for (i = 0; i < proc_num; i++) {
			if (entry->type != proc[i].id)
				continue;
280
			if (!proc[i].handler ||
281 282 283 284
			     (!errs && proc[i].handler(entry, table_end))) {
				errs++;
				continue;
			}
285

286
			proc[i].count++;
287
			break;
288
		}
289 290
		if (i != proc_num)
			count++;
291

292 293 294 295 296
		/*
		 * If entry->length is 0, break from this loop to avoid
		 * infinite loop.
		 */
		if (entry->length == 0) {
297
			pr_err("[%4.4s:0x%02x] Invalid zero length\n", id, proc->id);
298
			return -EINVAL;
299
		}
L
Linus Torvalds 已提交
300

301
		entry = (struct acpi_subtable_header *)
L
Len Brown 已提交
302
		    ((unsigned long)entry + entry->length);
L
Linus Torvalds 已提交
303
	}
304

L
Linus Torvalds 已提交
305
	if (max_entries && count > max_entries) {
306 307
		pr_warn("[%4.4s:0x%02x] found the maximum %i entries\n",
			id, proc->id, count);
L
Linus Torvalds 已提交
308 309
	}

310
	return errs ? -EINVAL : count;
311 312
}

313 314
int __init
acpi_table_parse_entries_array(char *id,
315
			 unsigned long table_size,
316
			 struct acpi_subtable_proc *proc, int proc_num,
317 318 319 320 321 322 323 324 325
			 unsigned int max_entries)
{
	struct acpi_table_header *table_header = NULL;
	int count;
	u32 instance = 0;

	if (acpi_disabled)
		return -ENODEV;

326
	if (!id)
327 328 329 330 331
		return -EINVAL;

	if (!strncmp(id, ACPI_SIG_MADT, 4))
		instance = acpi_apic_instance;

332
	acpi_get_table(id, instance, &table_header);
333 334 335 336 337
	if (!table_header) {
		pr_warn("%4.4s not present\n", id);
		return -ENODEV;
	}

338 339
	count = acpi_parse_entries_array(id, table_size, table_header,
			proc, proc_num, max_entries);
340

341
	acpi_put_table(table_header);
342
	return count;
L
Linus Torvalds 已提交
343 344
}

345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
int __init
acpi_table_parse_entries(char *id,
			unsigned long table_size,
			int entry_id,
			acpi_tbl_entry_handler handler,
			unsigned int max_entries)
{
	struct acpi_subtable_proc proc = {
		.id		= entry_id,
		.handler	= handler,
	};

	return acpi_table_parse_entries_array(id, table_size, &proc, 1,
						max_entries);
}

L
Linus Torvalds 已提交
361
int __init
362
acpi_table_parse_madt(enum acpi_madt_type id,
363
		      acpi_tbl_entry_handler handler, unsigned int max_entries)
L
Linus Torvalds 已提交
364
{
365
	return acpi_table_parse_entries(ACPI_SIG_MADT,
L
Len Brown 已提交
366 367
					    sizeof(struct acpi_table_madt), id,
					    handler, max_entries);
L
Linus Torvalds 已提交
368 369
}

370 371 372 373 374 375
/**
 * acpi_table_parse - find table with @id, run @handler on it
 * @id: table id to find
 * @handler: handler to run
 *
 * Scan the ACPI System Descriptor Table (STD) for a table matching @id,
376 377 378
 * run @handler on it.
 *
 * Return 0 if table found, -errno if not.
379
 */
380
int __init acpi_table_parse(char *id, acpi_tbl_table_handler handler)
L
Linus Torvalds 已提交
381
{
382
	struct acpi_table_header *table = NULL;
L
Len Brown 已提交
383

384
	if (acpi_disabled)
385 386
		return -ENODEV;

387
	if (!id || !handler)
L
Linus Torvalds 已提交
388 389
		return -EINVAL;

L
Len Brown 已提交
390
	if (strncmp(id, ACPI_SIG_MADT, 4) == 0)
391
		acpi_get_table(id, acpi_apic_instance, &table);
L
Len Brown 已提交
392
	else
393
		acpi_get_table(id, 0, &table);
L
Len Brown 已提交
394

395 396
	if (table) {
		handler(table);
397
		acpi_put_table(table);
398
		return 0;
399
	} else
400
		return -ENODEV;
L
Linus Torvalds 已提交
401 402
}

L
Len Brown 已提交
403 404 405 406 407 408 409 410 411
/* 
 * The BIOS is supposed to supply a single APIC/MADT,
 * but some report two.  Provide a knob to use either.
 * (don't you wish instance 0 and 1 were not the same?)
 */
static void __init check_multiple_madt(void)
{
	struct acpi_table_header *table = NULL;

412
	acpi_get_table(ACPI_SIG_MADT, 2, &table);
L
Len Brown 已提交
413
	if (table) {
414 415 416 417 418
		pr_warn("BIOS bug: multiple APIC/MADT found, using %d\n",
			acpi_apic_instance);
		pr_warn("If \"acpi_apic_instance=%d\" works better, "
			"notify linux-acpi@vger.kernel.org\n",
			acpi_apic_instance ? 0 : 2);
419
		acpi_put_table(table);
L
Len Brown 已提交
420 421 422 423 424 425 426

	} else
		acpi_apic_instance = 0;

	return;
}

427 428 429 430 431 432 433
static void acpi_table_taint(struct acpi_table_header *table)
{
	pr_warn("Override [%4.4s-%8.8s], this is unsafe: tainting kernel\n",
		table->signature, table->oem_table_id);
	add_taint(TAINT_OVERRIDDEN_ACPI_TABLE, LOCKDEP_NOW_UNRELIABLE);
}

434
#ifdef CONFIG_ACPI_TABLE_UPGRADE
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
static u64 acpi_tables_addr;
static int all_tables_size;

/* Copied from acpica/tbutils.c:acpi_tb_checksum() */
static u8 __init acpi_table_checksum(u8 *buffer, u32 length)
{
	u8 sum = 0;
	u8 *end = buffer + length;

	while (buffer < end)
		sum = (u8) (sum + *(buffer++));
	return sum;
}

/* All but ACPI_SIG_RSDP and ACPI_SIG_FACS: */
static const char * const table_sigs[] = {
	ACPI_SIG_BERT, ACPI_SIG_CPEP, ACPI_SIG_ECDT, ACPI_SIG_EINJ,
	ACPI_SIG_ERST, ACPI_SIG_HEST, ACPI_SIG_MADT, ACPI_SIG_MSCT,
	ACPI_SIG_SBST, ACPI_SIG_SLIT, ACPI_SIG_SRAT, ACPI_SIG_ASF,
	ACPI_SIG_BOOT, ACPI_SIG_DBGP, ACPI_SIG_DMAR, ACPI_SIG_HPET,
	ACPI_SIG_IBFT, ACPI_SIG_IVRS, ACPI_SIG_MCFG, ACPI_SIG_MCHI,
	ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA,
	ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT,
	ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT,
	ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL };

#define ACPI_HEADER_SIZE sizeof(struct acpi_table_header)

463 464 465
#define NR_ACPI_INITRD_TABLES 64
static struct cpio_data __initdata acpi_initrd_files[NR_ACPI_INITRD_TABLES];
static DECLARE_BITMAP(acpi_initrd_installed, NR_ACPI_INITRD_TABLES);
466 467 468

#define MAP_CHUNK_SIZE   (NR_FIX_BTMAPS << PAGE_SHIFT)

469
void __init acpi_table_upgrade(void)
470
{
471 472
	void *data = (void *)initrd_start;
	size_t size = initrd_end - initrd_start;
473 474 475 476 477 478 479 480 481
	int sig, no, table_nr = 0, total_offset = 0;
	long offset = 0;
	struct acpi_table_header *table;
	char cpio_path[32] = "kernel/firmware/acpi/";
	struct cpio_data file;

	if (data == NULL || size == 0)
		return;

482
	for (no = 0; no < NR_ACPI_INITRD_TABLES; no++) {
483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
		file = find_cpio_data(cpio_path, data, size, &offset);
		if (!file.data)
			break;

		data += offset;
		size -= offset;

		if (file.size < sizeof(struct acpi_table_header)) {
			pr_err("ACPI OVERRIDE: Table smaller than ACPI header [%s%s]\n",
				cpio_path, file.name);
			continue;
		}

		table = file.data;

		for (sig = 0; table_sigs[sig]; sig++)
			if (!memcmp(table->signature, table_sigs[sig], 4))
				break;

		if (!table_sigs[sig]) {
			pr_err("ACPI OVERRIDE: Unknown signature [%s%s]\n",
				cpio_path, file.name);
			continue;
		}
		if (file.size != table->length) {
			pr_err("ACPI OVERRIDE: File length does not match table length [%s%s]\n",
				cpio_path, file.name);
			continue;
		}
		if (acpi_table_checksum(file.data, table->length)) {
			pr_err("ACPI OVERRIDE: Bad table checksum [%s%s]\n",
				cpio_path, file.name);
			continue;
		}

		pr_info("%4.4s ACPI table found in initrd [%s%s][0x%x]\n",
			table->signature, cpio_path, file.name, table->length);

		all_tables_size += table->length;
		acpi_initrd_files[table_nr].data = file.data;
		acpi_initrd_files[table_nr].size = file.size;
		table_nr++;
	}
	if (table_nr == 0)
		return;

	acpi_tables_addr =
530
		memblock_find_in_range(0, ACPI_TABLE_UPGRADE_MAX_PHYS,
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
				       all_tables_size, PAGE_SIZE);
	if (!acpi_tables_addr) {
		WARN_ON(1);
		return;
	}
	/*
	 * Only calling e820_add_reserve does not work and the
	 * tables are invalid (memory got used) later.
	 * memblock_reserve works as expected and the tables won't get modified.
	 * But it's not enough on X86 because ioremap will
	 * complain later (used by acpi_os_map_memory) that the pages
	 * that should get mapped are not marked "reserved".
	 * Both memblock_reserve and e820_add_region (via arch_reserve_mem_area)
	 * works fine.
	 */
	memblock_reserve(acpi_tables_addr, all_tables_size);
	arch_reserve_mem_area(acpi_tables_addr, all_tables_size);

	/*
	 * early_ioremap only can remap 256k one time. If we map all
	 * tables one time, we will hit the limit. Need to map chunks
	 * one by one during copying the same as that in relocate_initrd().
	 */
	for (no = 0; no < table_nr; no++) {
		unsigned char *src_p = acpi_initrd_files[no].data;
		phys_addr_t size = acpi_initrd_files[no].size;
		phys_addr_t dest_addr = acpi_tables_addr + total_offset;
		phys_addr_t slop, clen;
		char *dest_p;

		total_offset += size;

		while (size) {
			slop = dest_addr & ~PAGE_MASK;
			clen = size;
			if (clen > MAP_CHUNK_SIZE - slop)
				clen = MAP_CHUNK_SIZE - slop;
568 569
			dest_p = early_memremap(dest_addr & PAGE_MASK,
						clen + slop);
570
			memcpy(dest_p + slop, src_p, clen);
571
			early_memunmap(dest_p, clen + slop);
572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
			src_p += clen;
			dest_addr += clen;
			size -= clen;
		}
	}
}

static acpi_status
acpi_table_initrd_override(struct acpi_table_header *existing_table,
			   acpi_physical_address *address, u32 *length)
{
	int table_offset = 0;
	int table_index = 0;
	struct acpi_table_header *table;
	u32 table_length;

	*length = 0;
	*address = 0;
	if (!acpi_tables_addr)
		return AE_OK;

	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
					   ACPI_HEADER_SIZE);
		if (table_offset + table->length > all_tables_size) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			WARN_ON(1);
			return AE_OK;
		}

		table_length = table->length;

		/* Only override tables matched */
605 606 607
		if (memcmp(existing_table->signature, table->signature, 4) ||
		    memcmp(table->oem_id, existing_table->oem_id,
			   ACPI_OEM_ID_SIZE) ||
608 609 610 611 612
		    memcmp(table->oem_table_id, existing_table->oem_table_id,
			   ACPI_OEM_TABLE_ID_SIZE)) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			goto next_table;
		}
613 614 615 616 617 618 619 620 621
		/*
		 * Mark the table to avoid being used in
		 * acpi_table_initrd_scan() and check the revision.
		 */
		if (test_and_set_bit(table_index, acpi_initrd_installed) ||
		    existing_table->oem_revision >= table->oem_revision) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			goto next_table;
		}
622 623 624

		*length = table_length;
		*address = acpi_tables_addr + table_offset;
625 626 627
		pr_info("Table Upgrade: override [%4.4s-%6.6s-%8.8s]\n",
			table->signature, table->oem_id,
			table->oem_table_id);
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
		break;

next_table:
		table_offset += table_length;
		table_index++;
	}
	return AE_OK;
}

static void __init acpi_table_initrd_scan(void)
{
	int table_offset = 0;
	int table_index = 0;
	u32 table_length;
	struct acpi_table_header *table;

	if (!acpi_tables_addr)
		return;

	while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) {
		table = acpi_os_map_memory(acpi_tables_addr + table_offset,
					   ACPI_HEADER_SIZE);
		if (table_offset + table->length > all_tables_size) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			WARN_ON(1);
			return;
		}

		table_length = table->length;

		/* Skip RSDT/XSDT which should only be used for override */
660
		if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_RSDT) ||
661 662 663 664
		    ACPI_COMPARE_NAME(table->signature, ACPI_SIG_XSDT)) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			goto next_table;
		}
665 666 667 668 669 670 671 672 673
		/*
		 * Mark the table to avoid being used in
		 * acpi_table_initrd_override(). Though this is not possible
		 * because override is disabled in acpi_install_table().
		 */
		if (test_and_set_bit(table_index, acpi_initrd_installed)) {
			acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
			goto next_table;
		}
674

675 676 677
		pr_info("Table Upgrade: install [%4.4s-%6.6s-%8.8s]\n",
			table->signature, table->oem_id,
			table->oem_table_id);
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
		acpi_os_unmap_memory(table, ACPI_HEADER_SIZE);
		acpi_install_table(acpi_tables_addr + table_offset, TRUE);
next_table:
		table_offset += table_length;
		table_index++;
	}
}
#else
static acpi_status
acpi_table_initrd_override(struct acpi_table_header *existing_table,
			   acpi_physical_address *address,
			   u32 *table_length)
{
	*table_length = 0;
	*address = 0;
	return AE_OK;
}

static void __init acpi_table_initrd_scan(void)
{
}
699
#endif /* CONFIG_ACPI_TABLE_UPGRADE */
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727

acpi_status
acpi_os_physical_table_override(struct acpi_table_header *existing_table,
				acpi_physical_address *address,
				u32 *table_length)
{
	return acpi_table_initrd_override(existing_table, address,
					  table_length);
}

acpi_status
acpi_os_table_override(struct acpi_table_header *existing_table,
		       struct acpi_table_header **new_table)
{
	if (!existing_table || !new_table)
		return AE_BAD_PARAMETER;

	*new_table = NULL;

#ifdef CONFIG_ACPI_CUSTOM_DSDT
	if (strncmp(existing_table->signature, "DSDT", 4) == 0)
		*new_table = (struct acpi_table_header *)AmlCode;
#endif
	if (*new_table != NULL)
		acpi_table_taint(existing_table);
	return AE_OK;
}

L
Linus Torvalds 已提交
728 729 730 731 732
/*
 * acpi_table_init()
 *
 * find RSDP, find and checksum SDT/XSDT.
 * checksum all tables, print SDT/XSDT
733
 *
L
Linus Torvalds 已提交
734 735 736
 * result: sdt_entry[] is initialized
 */

L
Len Brown 已提交
737
int __init acpi_table_init(void)
L
Linus Torvalds 已提交
738
{
739 740
	acpi_status status;

741 742 743 744 745 746 747 748
	if (acpi_verify_table_checksum) {
		pr_info("Early table checksum verification enabled\n");
		acpi_gbl_verify_table_checksum = TRUE;
	} else {
		pr_info("Early table checksum verification disabled\n");
		acpi_gbl_verify_table_checksum = FALSE;
	}

749 750
	status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0);
	if (ACPI_FAILURE(status))
751
		return -EINVAL;
752
	acpi_table_initrd_scan();
753

L
Len Brown 已提交
754 755 756 757 758 759
	check_multiple_madt();
	return 0;
}

static int __init acpi_parse_apic_instance(char *str)
{
760 761
	if (!str)
		return -EINVAL;
L
Len Brown 已提交
762

763 764
	if (kstrtoint(str, 0, &acpi_apic_instance))
		return -EINVAL;
L
Len Brown 已提交
765

766
	pr_notice("Shall use APIC/MADT table %d\n", acpi_apic_instance);
L
Len Brown 已提交
767

L
Linus Torvalds 已提交
768 769
	return 0;
}
L
Len Brown 已提交
770 771

early_param("acpi_apic_instance", acpi_parse_apic_instance);
772 773 774 775 776 777 778 779 780

static int __init acpi_force_table_verification_setup(char *s)
{
	acpi_verify_table_checksum = true;

	return 0;
}

early_param("acpi_force_table_verification", acpi_force_table_verification_setup);
781 782 783 784 785 786 787 788 789 790

static int __init acpi_force_32bit_fadt_addr(char *s)
{
	pr_info("Forcing 32 Bit FADT addresses\n");
	acpi_gbl_use32_bit_fadt_addresses = TRUE;

	return 0;
}

early_param("acpi_force_32bit_fadt_addr", acpi_force_32bit_fadt_addr);