aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/dsdt-override.txt15
-rwxr-xr-xDocumentation/acpi/initramfs-add-dsdt.sh43
-rw-r--r--Documentation/kernel-parameters.txt3
-rw-r--r--drivers/acpi/Kconfig17
-rw-r--r--drivers/acpi/osl.c97
-rw-r--r--include/linux/kernel.h1
-rw-r--r--init/initramfs.c8
-rw-r--r--init/main.c7
-rw-r--r--kernel/panic.c5
9 files changed, 187 insertions, 9 deletions
diff --git a/Documentation/acpi/dsdt-override.txt b/Documentation/acpi/dsdt-override.txt
new file mode 100644
index 000000000000..5008f256a2db
--- /dev/null
+++ b/Documentation/acpi/dsdt-override.txt
@@ -0,0 +1,15 @@
1Linux supports two methods of overriding the BIOS DSDT:
2
3CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
4
5CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd.
6
7When to use these methods is described in detail on the
8Linux/ACPI home page:
9http://www.lesswatts.org/projects/acpi/overridingDSDT.php
10
11Note that if both options are used, the DSDT supplied
12by the INITRD method takes precedence.
13
14Documentation/initramfs-add-dsdt.sh is provided for convenience
15for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method.
diff --git a/Documentation/acpi/initramfs-add-dsdt.sh b/Documentation/acpi/initramfs-add-dsdt.sh
new file mode 100755
index 000000000000..17ef6e838e14
--- /dev/null
+++ b/Documentation/acpi/initramfs-add-dsdt.sh
@@ -0,0 +1,43 @@
1#!/bin/bash
2# Adds a DSDT file to the initrd (if it's an initramfs)
3# first argument is the name of archive
4# second argument is the name of the file to add
5# The file will be copied as /DSDT.aml
6
7# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
8# 20060205: this time it should really work
9
10# check the arguments
11if [ $# -ne 2 ]; then
12 program_name=$(basename $0)
13 echo "\
14$program_name: too few arguments
15Usage: $program_name initrd-name.img DSDT-to-add.aml
16Adds a DSDT file to an initrd (in initramfs format)
17
18 initrd-name.img: filename of the initrd in initramfs format
19 DSDT-to-add.aml: filename of the DSDT file to add
20 " 1>&2
21 exit 1
22fi
23
24# we should check it's an initramfs
25
26tempcpio=$(mktemp -d)
27# cleanup on exit, hangup, interrupt, quit, termination
28trap 'rm -rf $tempcpio' 0 1 2 3 15
29
30# extract the archive
31gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
32
33# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
34cp -f "$2" "$tempcpio"/DSDT.aml
35
36# add the file
37cd "$tempcpio"
38(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
39cd "$OLDPWD"
40
41# re-compress the archive
42gzip -c "$tempcpio"/initramfs.cpio > "$1"
43
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 8ea41b6e6a85..0dcbd266b442 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -177,6 +177,9 @@ and is between 256 and 4096 characters. It is defined in the file
177 177
178 acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT 178 acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT
179 179
180 acpi_no_initrd_override [KNL,ACPI]
181 Disable loading custom ACPI tables from the initramfs
182
180 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS 183 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
181 Format: To spoof as Windows 98: ="Microsoft Windows" 184 Format: To spoof as Windows 98: ="Microsoft Windows"
182 185
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index d141bdb3a7d4..7ef172c2a1d6 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -276,8 +276,10 @@ config ACPI_CUSTOM_DSDT
276 depends on !STANDALONE 276 depends on !STANDALONE
277 default n 277 default n
278 help 278 help
279 This option is to load a custom ACPI DSDT 279 This option supports a custom DSDT by linking it into the kernel.
280 If you don't know what that is, say N. 280 See Documentation/acpi/dsdt-override.txt
281
282 If unsure, say N.
281 283
282config ACPI_CUSTOM_DSDT_FILE 284config ACPI_CUSTOM_DSDT_FILE
283 string "Custom DSDT Table file to include" 285 string "Custom DSDT Table file to include"
@@ -287,6 +289,17 @@ config ACPI_CUSTOM_DSDT_FILE
287 Enter the full path name to the file which includes the AmlCode 289 Enter the full path name to the file which includes the AmlCode
288 declaration. 290 declaration.
289 291
292config ACPI_CUSTOM_DSDT_INITRD
293 bool "Read Custom DSDT from initramfs"
294 depends on BLK_DEV_INITRD
295 default n
296 help
297 This option supports a custom DSDT by optionally loading it from initrd.
298 See Documentation/acpi/dsdt-override.txt
299
300 If you are not using this feature now, but may use it later,
301 it is safe to say Y here.
302
290config ACPI_BLACKLIST_YEAR 303config ACPI_BLACKLIST_YEAR
291 int "Disable ACPI for systems before Jan 1st this year" if X86_32 304 int "Disable ACPI for systems before Jan 1st this year" if X86_32
292 default 0 305 default 0
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index c2c585366fa6..27ccd68b8f46 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -91,6 +91,10 @@ static DEFINE_SPINLOCK(acpi_res_lock);
91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 91#define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
92static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 92static char osi_additional_string[OSI_STRING_LENGTH_MAX];
93 93
94#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
95static int acpi_no_initrd_override;
96#endif
97
94/* 98/*
95 * "Ode to _OSI(Linux)" 99 * "Ode to _OSI(Linux)"
96 * 100 *
@@ -329,6 +333,67 @@ acpi_os_predefined_override(const struct acpi_predefined_names *init_val,
329 return AE_OK; 333 return AE_OK;
330} 334}
331 335
336#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
337struct acpi_table_header *acpi_find_dsdt_initrd(void)
338{
339 struct file *firmware_file;
340 mm_segment_t oldfs;
341 unsigned long len, len2;
342 struct acpi_table_header *dsdt_buffer, *ret = NULL;
343 struct kstat stat;
344 char *ramfs_dsdt_name = "/DSDT.aml";
345
346 printk(KERN_INFO PREFIX "Checking initramfs for custom DSDT");
347
348 /*
349 * Never do this at home, only the user-space is allowed to open a file.
350 * The clean way would be to use the firmware loader.
351 * But this code must be run before there is any userspace available.
352 * A static/init firmware infrastructure doesn't exist yet...
353 */
354 if (vfs_stat(ramfs_dsdt_name, &stat) < 0)
355 return ret;
356
357 len = stat.size;
358 /* check especially against empty files */
359 if (len <= 4) {
360 printk(KERN_ERR PREFIX "Failed: DSDT only %lu bytes.\n", len);
361 return ret;
362 }
363
364 firmware_file = filp_open(ramfs_dsdt_name, O_RDONLY, 0);
365 if (IS_ERR(firmware_file)) {
366 printk(KERN_ERR PREFIX "Failed to open %s.\n", ramfs_dsdt_name);
367 return ret;
368 }
369
370 dsdt_buffer = kmalloc(len, GFP_ATOMIC);
371 if (!dsdt_buffer) {
372 printk(KERN_ERR PREFIX "Failed to allocate %lu bytes.\n", len);
373 goto err;
374 }
375
376 oldfs = get_fs();
377 set_fs(KERNEL_DS);
378 len2 = vfs_read(firmware_file, (char __user *)dsdt_buffer, len,
379 &firmware_file->f_pos);
380 set_fs(oldfs);
381 if (len2 < len) {
382 printk(KERN_ERR PREFIX "Failed to read %lu bytes from %s.\n",
383 len, ramfs_dsdt_name);
384 ACPI_FREE(dsdt_buffer);
385 goto err;
386 }
387
388 printk(KERN_INFO PREFIX "Found %lu byte DSDT in %s.\n",
389 len, ramfs_dsdt_name);
390 ret = dsdt_buffer;
391err:
392 filp_close(firmware_file, NULL);
393 return ret;
394}
395#endif
396
332acpi_status 397acpi_status
333acpi_os_table_override(struct acpi_table_header * existing_table, 398acpi_os_table_override(struct acpi_table_header * existing_table,
334 struct acpi_table_header ** new_table) 399 struct acpi_table_header ** new_table)
@@ -336,17 +401,41 @@ acpi_os_table_override(struct acpi_table_header * existing_table,
336 if (!existing_table || !new_table) 401 if (!existing_table || !new_table)
337 return AE_BAD_PARAMETER; 402 return AE_BAD_PARAMETER;
338 403
404 *new_table = NULL;
405
339#ifdef CONFIG_ACPI_CUSTOM_DSDT 406#ifdef CONFIG_ACPI_CUSTOM_DSDT
340 if (strncmp(existing_table->signature, "DSDT", 4) == 0) 407 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
341 *new_table = (struct acpi_table_header *)AmlCode; 408 *new_table = (struct acpi_table_header *)AmlCode;
342 else
343 *new_table = NULL;
344#else
345 *new_table = NULL;
346#endif 409#endif
410#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
411 if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
412 !acpi_no_initrd_override) {
413 struct acpi_table_header *initrd_table;
414
415 initrd_table = acpi_find_dsdt_initrd();
416 if (initrd_table)
417 *new_table = initrd_table;
418 }
419#endif
420 if (*new_table != NULL) {
421 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
422 "this is unsafe: tainting kernel\n",
423 existing_table->signature,
424 existing_table->oem_table_id);
425 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
426 }
347 return AE_OK; 427 return AE_OK;
348} 428}
349 429
430#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
431int __init acpi_no_initrd_override_setup(char *s)
432{
433 acpi_no_initrd_override = 1;
434 return 1;
435}
436__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
437#endif
438
350static irqreturn_t acpi_irq(int irq, void *dev_id) 439static irqreturn_t acpi_irq(int irq, void *dev_id)
351{ 440{
352 u32 handled; 441 u32 handled;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 18222f267bc4..9e01f376840a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -243,6 +243,7 @@ extern enum system_states {
243#define TAINT_BAD_PAGE (1<<5) 243#define TAINT_BAD_PAGE (1<<5)
244#define TAINT_USER (1<<6) 244#define TAINT_USER (1<<6)
245#define TAINT_DIE (1<<7) 245#define TAINT_DIE (1<<7)
246#define TAINT_OVERRIDDEN_ACPI_TABLE (1<<8)
246 247
247extern void dump_stack(void) __cold; 248extern void dump_stack(void) __cold;
248 249
diff --git a/init/initramfs.c b/init/initramfs.c
index d53fee8d8604..c0b1e0533d80 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -538,7 +538,7 @@ skip:
538 initrd_end = 0; 538 initrd_end = 0;
539} 539}
540 540
541static int __init populate_rootfs(void) 541int __init populate_rootfs(void)
542{ 542{
543 char *err = unpack_to_rootfs(__initramfs_start, 543 char *err = unpack_to_rootfs(__initramfs_start,
544 __initramfs_end - __initramfs_start, 0); 544 __initramfs_end - __initramfs_start, 0);
@@ -577,4 +577,10 @@ static int __init populate_rootfs(void)
577 } 577 }
578 return 0; 578 return 0;
579} 579}
580#ifndef CONFIG_ACPI_CUSTOM_DSDT_INITRD
581/*
582 * if this option is enabled, populate_rootfs() is called _earlier_ in the
583 * boot sequence. This insures that the ACPI initialisation can find the file.
584 */
580rootfs_initcall(populate_rootfs); 585rootfs_initcall(populate_rootfs);
586#endif
diff --git a/init/main.c b/init/main.c
index c691f5f7fc27..2a78932f6c07 100644
--- a/init/main.c
+++ b/init/main.c
@@ -102,6 +102,12 @@ static inline void mark_rodata_ro(void) { }
102extern void tc_init(void); 102extern void tc_init(void);
103#endif 103#endif
104 104
105#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
106extern int populate_rootfs(void);
107#else
108static inline void populate_rootfs(void) {}
109#endif
110
105enum system_states system_state; 111enum system_states system_state;
106EXPORT_SYMBOL(system_state); 112EXPORT_SYMBOL(system_state);
107 113
@@ -648,6 +654,7 @@ asmlinkage void __init start_kernel(void)
648 654
649 check_bugs(); 655 check_bugs();
650 656
657 populate_rootfs(); /* For DSDT override from initramfs */
651 acpi_early_init(); /* before LAPIC and SMP init */ 658 acpi_early_init(); /* before LAPIC and SMP init */
652 659
653 /* Do the rest non-__init'ed, we're now alive */ 660 /* Do the rest non-__init'ed, we're now alive */
diff --git a/kernel/panic.c b/kernel/panic.c
index d9e90cfe3298..24af9f8bac99 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -161,7 +161,7 @@ const char *print_tainted(void)
161{ 161{
162 static char buf[20]; 162 static char buf[20];
163 if (tainted) { 163 if (tainted) {
164 snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c", 164 snprintf(buf, sizeof(buf), "Tainted: %c%c%c%c%c%c%c%c%c",
165 tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G', 165 tainted & TAINT_PROPRIETARY_MODULE ? 'P' : 'G',
166 tainted & TAINT_FORCED_MODULE ? 'F' : ' ', 166 tainted & TAINT_FORCED_MODULE ? 'F' : ' ',
167 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ', 167 tainted & TAINT_UNSAFE_SMP ? 'S' : ' ',
@@ -169,7 +169,8 @@ const char *print_tainted(void)
169 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ', 169 tainted & TAINT_MACHINE_CHECK ? 'M' : ' ',
170 tainted & TAINT_BAD_PAGE ? 'B' : ' ', 170 tainted & TAINT_BAD_PAGE ? 'B' : ' ',
171 tainted & TAINT_USER ? 'U' : ' ', 171 tainted & TAINT_USER ? 'U' : ' ',
172 tainted & TAINT_DIE ? 'D' : ' '); 172 tainted & TAINT_DIE ? 'D' : ' ',
173 tainted & TAINT_OVERRIDDEN_ACPI_TABLE ? 'A' : ' ');
173 } 174 }
174 else 175 else
175 snprintf(buf, sizeof(buf), "Not tainted"); 176 snprintf(buf, sizeof(buf), "Not tainted");