summaryrefslogtreecommitdiff
path: root/patches/acpi-dsdt-2.6.30.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/acpi-dsdt-2.6.30.patch')
-rw-r--r--patches/acpi-dsdt-2.6.30.patch439
1 files changed, 439 insertions, 0 deletions
diff --git a/patches/acpi-dsdt-2.6.30.patch b/patches/acpi-dsdt-2.6.30.patch
new file mode 100644
index 0000000..cfc8d49
--- /dev/null
+++ b/patches/acpi-dsdt-2.6.30.patch
@@ -0,0 +1,439 @@
+ACPI: initramfs DSDT override support
+
+Permits to load of DSDT (the main ACPI table) from initramfs. In case this
+option is selected, the initramfs is parsed at ACPI initialization (very early
+boot time) to look for a file called "DSDT.aml". This aims at allowing users to
+override the DSDT without recompiling the kernel.
+
+Version 0.9 uses a different approach for reading the initramfs which avoids
+using the filesystem infrastructure. It leverages the initramfs unpack code to find
+and unpack the DSDT directly into the memory.
+
+v0.9a: Fix compilation on non-ACPI platforms by René Rebe <rene@exactcode.de>
+v0.9b: Declare more functions __init by Jan Beulich <jbeulich@novell.com>
+v0.9c: Allow root to be / instead of nothing, bug reported by Robert Hampovcan
+
+mandriva kernel version: diff is changed from patch present at
+http://gaugusch.at/acpi-dsdt-initrd-patches/acpi-dsdt-initrd-v0.9c-2.6.28.patch
+I adapted/fixed the patch for linux 2.6.30, and don't include acpi.h in
+initramfs.c if ACPI_CUSTOM_DSDT_INITRD is disabled -- herton
+
+Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
+---
+ Documentation/acpi/dsdt-override.txt | 12 +++
+ Documentation/acpi/initramfs-add-dsdt.sh | 43 +++++++++++++
+ Documentation/kernel-parameters.txt | 3
+ drivers/acpi/Kconfig | 11 +++
+ drivers/acpi/osl.c | 24 +++++++
+ init/initramfs.c | 99 +++++++++++++++++++++++++++++++
+ 6 files changed, 190 insertions(+), 2 deletions(-)
+ create mode 100644 Documentation/acpi/initramfs-add-dsdt.sh
+
+--- a/Documentation/acpi/dsdt-override.txt
++++ b/Documentation/acpi/dsdt-override.txt
+@@ -1,7 +1,15 @@
+-Linux supports a method of overriding the BIOS DSDT:
++Linux supports two methods of overriding the BIOS DSDT:
+
+ CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
+
+-When to use this method is described in detail on the
++CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd.
++
++When to use these methods is described in detail on the
+ Linux/ACPI home page:
+ http://www.lesswatts.org/projects/acpi/overridingDSDT.php
++
++Note that if both options are used, the DSDT supplied
++by the INITRD method takes precedence.
++
++Documentation/initramfs-add-dsdt.sh is provided for convenience
++for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method.
+--- /dev/null
++++ b/Documentation/acpi/initramfs-add-dsdt.sh
+@@ -0,0 +1,43 @@
++#!/bin/bash
++# Adds a DSDT file to the initrd (if it's an initramfs)
++# first argument is the name of archive
++# second argument is the name of the file to add
++# The file will be copied as /DSDT.aml
++
++# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
++# 20060205: this time it should really work
++
++# check the arguments
++if [ $# -ne 2 ]; then
++ program_name=$(basename $0)
++ echo "\
++$program_name: too few arguments
++Usage: $program_name initrd-name.img DSDT-to-add.aml
++Adds a DSDT file to an initrd (in initramfs format)
++
++ initrd-name.img: filename of the initrd in initramfs format
++ DSDT-to-add.aml: filename of the DSDT file to add
++ " 1>&2
++ exit 1
++fi
++
++# we should check it's an initramfs
++
++tempcpio=$(mktemp -d)
++# cleanup on exit, hangup, interrupt, quit, termination
++trap 'rm -rf $tempcpio' 0 1 2 3 15
++
++# extract the archive
++gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
++
++# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
++cp -f "$2" "$tempcpio"/DSDT.aml
++
++# add the file
++cd "$tempcpio"
++(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
++cd "$OLDPWD"
++
++# re-compress the archive
++gzip -c "$tempcpio"/initramfs.cpio > "$1"
++
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -216,6 +216,9 @@ and is between 256 and 4096 characters.
+
+ acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT
+
++ acpi_no_initrd_override [KNL,ACPI]
++ Disable loading custom ACPI tables from the initramfs
++
+ acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
+ Format: To spoof as Windows 98: ="Microsoft Windows"
+
+--- a/drivers/acpi/Kconfig
++++ b/drivers/acpi/Kconfig
+@@ -233,6 +233,17 @@ config ACPI_CUSTOM_DSDT
+ bool
+ default ACPI_CUSTOM_DSDT_FILE != ""
+
++config ACPI_CUSTOM_DSDT_INITRD
++ bool "Read Custom DSDT from initramfs"
++ depends on BLK_DEV_INITRD
++ default n
++ help
++ This option supports a custom DSDT by optionally loading it from initrd.
++ See Documentation/acpi/dsdt-override.txt
++
++ If you are not using this feature now, but may use it later,
++ it is safe to say Y here.
++
+ config ACPI_BLACKLIST_YEAR
+ int "Disable ACPI for systems before Jan 1st this year" if X86_32
+ default 0
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -95,6 +95,11 @@ static DEFINE_SPINLOCK(acpi_res_lock);
+ #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
+ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++static __initdata int acpi_no_initrd_override;
++extern struct acpi_table_header *acpi_find_dsdt_initrd(void);
++#endif
++
+ /*
+ * The story of _OSI(Linux)
+ *
+@@ -334,6 +339,16 @@ acpi_os_table_override(struct acpi_table
+ if (strncmp(existing_table->signature, "DSDT", 4) == 0)
+ *new_table = (struct acpi_table_header *)AmlCode;
+ #endif
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++ if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
++ !acpi_no_initrd_override) {
++ struct acpi_table_header *initrd_table;
++
++ initrd_table = acpi_find_dsdt_initrd();
++ if (initrd_table)
++ *new_table = initrd_table;
++ }
++#endif
+ if (*new_table != NULL) {
+ printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
+ "this is unsafe: tainting kernel\n",
+@@ -344,6 +359,15 @@ acpi_os_table_override(struct acpi_table
+ return AE_OK;
+ }
+
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++static int __init acpi_no_initrd_override_setup(char *s)
++{
++ acpi_no_initrd_override = 1;
++ return 1;
++}
++__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
++#endif
++
+ static irqreturn_t acpi_irq(int irq, void *dev_id)
+ {
+ u32 handled;
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -8,6 +8,9 @@
+ #include <linux/dirent.h>
+ #include <linux/syscalls.h>
+ #include <linux/utime.h>
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++#include <acpi/acpi.h>
++#endif
+
+ static __initdata char *message;
+ static void __init error(char *x)
+@@ -125,6 +128,14 @@ static __initdata unsigned long body_len
+ static __initdata uid_t uid;
+ static __initdata gid_t gid;
+ static __initdata unsigned rdev;
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++static __initdata char *file_looked_for;
++static __initdata struct acpi_table_header *file_mem;
++static __initdata int find_dsdt;
++#else
++const char *file_looked_for = NULL;
++const int find_dsdt = 0;
++#endif
+
+ static void __init parse_header(char *s)
+ {
+@@ -159,6 +170,7 @@ static __initdata enum state {
+ SkipIt,
+ GotName,
+ CopyFile,
++ CopyFileMem,
+ GotSymlink,
+ Reset
+ } state, next_state;
+@@ -228,6 +240,10 @@ static int __init do_header(void)
+ parse_header(collected);
+ next_header = this_header + N_ALIGN(name_len) + body_len;
+ next_header = (next_header + 3) & ~3;
++ if (find_dsdt) {
++ read_into(name_buf, N_ALIGN(name_len), GotName);
++ return 0;
++ }
+ state = SkipIt;
+ if (name_len <= 0 || name_len > PATH_MAX)
+ return 0;
+@@ -290,6 +306,54 @@ static void __init clean_path(char *path
+
+ static __initdata int wfd;
+
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++static __init int is_file_looked_for(char *filename)
++{
++ char *tmp_collected = collected;
++ if (file_looked_for == NULL)
++ return 0;
++ if (!S_ISREG(mode))
++ return 0;
++ /* remove the leading / */
++ while (*tmp_collected == '/')
++ tmp_collected++;
++ return (strcmp(tmp_collected, file_looked_for) == 0);
++}
++
++static int __init do_copy_mem(void)
++{
++ static void *file_current; /* current position in the memory */
++ if (file_mem == NULL) {
++ if (body_len < 4) { /* check especially against empty files */
++ error("file is less than 4 bytes");
++ return 1;
++ }
++ file_mem = kmalloc(body_len, GFP_ATOMIC);
++ if (!file_mem) {
++ error("failed to allocate enough memory");
++ return 1;
++ }
++ file_current = file_mem;
++ }
++ if (count >= body_len) {
++ memcpy(file_current, victim, body_len);
++ eat(body_len);
++ file_looked_for = NULL; /* don't find files with same name */
++ state = SkipIt;
++ return 0;
++ } else {
++ memcpy(file_current, victim, count);
++ file_current += count;
++ body_len -= count;
++ eat(count);
++ return 1;
++ }
++}
++#else
++static inline int is_file_looked_for(char *filename) {return 0;}
++#define do_copy_mem NULL /* because it is used as a pointer */
++#endif
++
+ static int __init do_name(void)
+ {
+ state = SkipIt;
+@@ -298,6 +362,10 @@ static int __init do_name(void)
+ free_hash();
+ return 0;
+ }
++ if (is_file_looked_for(file_looked_for))
++ state = CopyFileMem;
++ if (find_dsdt)
++ return 0;
+ clean_path(collected, mode);
+ if (S_ISREG(mode)) {
+ int ml = maybe_link();
+@@ -370,6 +438,7 @@ static __initdata int (*actions[])(void)
+ [SkipIt] = do_skip,
+ [GotName] = do_name,
+ [CopyFile] = do_copy,
++ [CopyFileMem] = do_copy_mem,
+ [GotSymlink] = do_symlink,
+ [Reset] = do_reset,
+ };
+@@ -606,3 +675,33 @@ static int __init populate_rootfs(void)
+ return 0;
+ }
+ rootfs_initcall(populate_rootfs);
++
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++struct __init acpi_table_header *acpi_find_dsdt_initrd(void)
++{
++ char *err, *ramfs_dsdt_name = "DSDT.aml";
++
++ printk(KERN_INFO "ACPI: Checking initramfs for custom DSDT\n");
++ file_mem = NULL;
++ find_dsdt = 1;
++ file_looked_for = ramfs_dsdt_name;
++ err = unpack_to_rootfs((char *)initrd_start,
++ initrd_end - initrd_start);
++ file_looked_for = NULL;
++ find_dsdt = 0;
++
++ if (err) {
++ /*
++ * Even if reading the DSDT file was successful,
++ * we give up if the initramfs cannot be entirely read.
++ */
++ kfree(file_mem);
++ printk(KERN_ERR "ACPI: Aborted because %s.\n", err);
++ return NULL;
++ }
++ if (file_mem)
++ printk(KERN_INFO "ACPI: Found DSDT in %s.\n", ramfs_dsdt_name);
++
++ return file_mem;
++}
++#endif
+Fix to some problems in acpi-dsdt-initrd-v0.9c-2.6.28.patch:
+* acpi_os_table_override isn't an __init function, so looks wrong it to
+ reference an __initdata variable, remove __initdata annotation from
+ acpi_no_initrd_override
+* The __init annotation from acpi_find_dsdt_initrd wasn't being taken
+ into account, as can be verified when building with
+ CONFIG_DEBUG_SECTION_MISMATCH=y. Changing
+ "struct __init acpi_table_header *acpi_find_dsdt_initrd(void)"
+ to
+ "struct acpi_table_header __init *acpi_find_dsdt_initrd(void)"
+ would fix the problem, but then debug section mismatch checker would
+ complain about non __init acpi_os_table_override using
+ acpi_find_dsdt_initrd, and it's right. We can't annotate
+ acpi_os_table_override with __init, thus change code to save the
+ loaded dsdt from initrd into global acpi_dsdt_initrd.
+* We must check for initrd_start before trying to load DSDT from initrd.
+
+Signed-off-by: Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+---
+ drivers/acpi/osl.c | 13 ++++---------
+ init/initramfs.c | 7 ++++---
+ init/main.c | 7 +++++++
+ 3 files changed, 15 insertions(+), 12 deletions(-)
+
+--- a/drivers/acpi/osl.c
++++ b/drivers/acpi/osl.c
+@@ -96,8 +96,8 @@ static DEFINE_SPINLOCK(acpi_res_lock);
+ static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+
+ #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
+-static __initdata int acpi_no_initrd_override;
+-extern struct acpi_table_header *acpi_find_dsdt_initrd(void);
++static int acpi_no_initrd_override;
++struct acpi_table_header *acpi_dsdt_initrd = NULL;
+ #endif
+
+ /*
+@@ -341,13 +341,8 @@ acpi_os_table_override(struct acpi_table
+ #endif
+ #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
+ if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
+- !acpi_no_initrd_override) {
+- struct acpi_table_header *initrd_table;
+-
+- initrd_table = acpi_find_dsdt_initrd();
+- if (initrd_table)
+- *new_table = initrd_table;
+- }
++ !acpi_no_initrd_override && acpi_dsdt_initrd)
++ *new_table = acpi_dsdt_initrd;
+ #endif
+ if (*new_table != NULL) {
+ printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
+--- a/init/initramfs.c
++++ b/init/initramfs.c
+@@ -132,6 +132,7 @@ static __initdata unsigned rdev;
+ static __initdata char *file_looked_for;
+ static __initdata struct acpi_table_header *file_mem;
+ static __initdata int find_dsdt;
++extern struct acpi_table_header *acpi_dsdt_initrd;
+ #else
+ const char *file_looked_for = NULL;
+ const int find_dsdt = 0;
+@@ -677,7 +678,7 @@ static int __init populate_rootfs(void)
+ rootfs_initcall(populate_rootfs);
+
+ #ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
+-struct __init acpi_table_header *acpi_find_dsdt_initrd(void)
++void __init acpi_find_dsdt_initrd(void)
+ {
+ char *err, *ramfs_dsdt_name = "DSDT.aml";
+
+@@ -697,11 +698,11 @@ struct __init acpi_table_header *acpi_fi
+ */
+ kfree(file_mem);
+ printk(KERN_ERR "ACPI: Aborted because %s.\n", err);
+- return NULL;
++ return;
+ }
+ if (file_mem)
+ printk(KERN_INFO "ACPI: Found DSDT in %s.\n", ramfs_dsdt_name);
+
+- return file_mem;
++ acpi_dsdt_initrd = file_mem;
+ }
+ #endif
+--- a/init/main.c
++++ b/init/main.c
+@@ -91,6 +91,11 @@ extern void acpi_early_init(void);
+ #else
+ static inline void acpi_early_init(void) { }
+ #endif
++#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
++extern void acpi_find_dsdt_initrd(void);
++#else
++static inline void acpi_find_dsdt_initrd(void) { }
++#endif
+ #ifndef CONFIG_DEBUG_RODATA
+ static inline void mark_rodata_ro(void) { }
+ #endif
+@@ -692,6 +697,8 @@ asmlinkage void __init start_kernel(void
+
+ check_bugs();
+
++ if (initrd_start)
++ acpi_find_dsdt_initrd();
+ acpi_early_init(); /* before LAPIC and SMP init */
+
+ ftrace_init();