diff options
Diffstat (limited to 'patches/acpi-dsdt-2.6.30.patch')
-rw-r--r-- | patches/acpi-dsdt-2.6.30.patch | 439 |
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(); |