]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/acpi-dsdt-initrd-v0.9a-2.6.25.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / acpi-dsdt-initrd-v0.9a-2.6.25.patch
CommitLineData
2cb7cef9
BS
1From: Eric Piel <piel@localhost.(none)>
2Subject: [PATCH 1/1] ACPI: initramfs DSDT override support
3Patch-mainline: not yet
4
5
6Permits to load of DSDT (the main ACPI table) from initramfs. In case this
7option is selected, the initramfs is parsed at ACPI initialization (very early
8boot time) to look for a file DSDT.aml . This aims at allowing users to
9override the DSDT without recompiling the kernel. This is done by adding a new
10feature to the initramfs parser so that one specific file can be directly
11copied into memory.
12
13This is derived from the patch v0.8 from http://gaugusch.at/kernel.shtml but
14with kernel inclusion in mind: some clean-up's in the documentation, default
15set to No, a kernel parameter to disable it at runtime, and most important, a
16different approach for reading the initramfs which avoids using the filesystem
17infrastructure.
18
19It also contains a fix for compilation on non-ACPI platforms provided by Rene Rebe.
20
21Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
22Signed-off-by: Thomas Renninger <trenn@suse.de>
23Signed-off-by: Len Brown <len.brown@intel.com>
24---
25 Documentation/acpi/dsdt-override.txt | 12 ++++
26 Documentation/acpi/initramfs-add-dsdt.sh | 43 +++++++++++++++++
27 Documentation/kernel-parameters.txt | 3 +
28 drivers/acpi/Kconfig | 11 ++++
29 drivers/acpi/osl.c | 26 ++++++++++
30 drivers/acpi/tables/tbxface.c | 7 --
31 init/initramfs.c | 76 +++++++++++++++++++++++++++++++
32 7 files changed, 170 insertions(+), 8 deletions(-)
33 create mode 100644 Documentation/acpi/initramfs-add-dsdt.sh
34
35--- a/Documentation/acpi/dsdt-override.txt
36+++ b/Documentation/acpi/dsdt-override.txt
37@@ -1,7 +1,15 @@
38-Linux supports a method of overriding the BIOS DSDT:
39+Linux supports two methods of overriding the BIOS DSDT:
40
41 CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel.
42
43-When to use this method is described in detail on the
44+CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd.
45+
46+When to use these methods is described in detail on the
47 Linux/ACPI home page:
48 http://www.lesswatts.org/projects/acpi/overridingDSDT.php
49+
50+Note that if both options are used, the DSDT supplied
51+by the INITRD method takes precedence.
52+
53+Documentation/initramfs-add-dsdt.sh is provided for convenience
54+for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method.
55--- /dev/null
56+++ b/Documentation/acpi/initramfs-add-dsdt.sh
57@@ -0,0 +1,43 @@
58+#!/bin/bash
59+# Adds a DSDT file to the initrd (if it's an initramfs)
60+# first argument is the name of archive
61+# second argument is the name of the file to add
62+# The file will be copied as /DSDT.aml
63+
64+# 20060126: fix "Premature end of file" with some old cpio (Roland Robic)
65+# 20060205: this time it should really work
66+
67+# check the arguments
68+if [ $# -ne 2 ]; then
69+ program_name=$(basename $0)
70+ echo "\
71+$program_name: too few arguments
72+Usage: $program_name initrd-name.img DSDT-to-add.aml
73+Adds a DSDT file to an initrd (in initramfs format)
74+
75+ initrd-name.img: filename of the initrd in initramfs format
76+ DSDT-to-add.aml: filename of the DSDT file to add
77+ " 1>&2
78+ exit 1
79+fi
80+
81+# we should check it's an initramfs
82+
83+tempcpio=$(mktemp -d)
84+# cleanup on exit, hangup, interrupt, quit, termination
85+trap 'rm -rf $tempcpio' 0 1 2 3 15
86+
87+# extract the archive
88+gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1
89+
90+# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml"
91+cp -f "$2" "$tempcpio"/DSDT.aml
92+
93+# add the file
94+cd "$tempcpio"
95+(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1
96+cd "$OLDPWD"
97+
98+# re-compress the archive
99+gzip -c "$tempcpio"/initramfs.cpio > "$1"
100+
101--- a/Documentation/kernel-parameters.txt
102+++ b/Documentation/kernel-parameters.txt
103@@ -179,6 +179,9 @@ and is between 256 and 4096 characters.
104
105 acpi_no_auto_ssdt [HW,ACPI] Disable automatic loading of SSDT
106
107+ acpi_no_initrd_override [KNL,ACPI]
108+ Disable loading custom ACPI tables from the initramfs
109+
110 acpi_os_name= [HW,ACPI] Tell ACPI BIOS the name of the OS
111 Format: To spoof as Windows 98: ="Microsoft Windows"
112
113--- a/drivers/acpi/Kconfig
114+++ b/drivers/acpi/Kconfig
115@@ -301,6 +301,17 @@ config ACPI_CUSTOM_DSDT
116 bool
117 default ACPI_CUSTOM_DSDT_FILE != ""
118
119+config ACPI_CUSTOM_DSDT_INITRD
120+ bool "Read Custom DSDT from initramfs"
121+ depends on BLK_DEV_INITRD
122+ default n
123+ help
124+ This option supports a custom DSDT by optionally loading it from initrd.
125+ See Documentation/acpi/dsdt-override.txt
126+
127+ If you are not using this feature now, but may use it later,
128+ it is safe to say Y here.
129+
130 config ACPI_BLACKLIST_YEAR
131 int "Disable ACPI for systems before Jan 1st this year" if X86_32
132 default 0
133--- a/drivers/acpi/osl.c
134+++ b/drivers/acpi/osl.c
135@@ -96,6 +96,11 @@ static DEFINE_SPINLOCK(acpi_res_lock);
136 #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */
137 static char osi_additional_string[OSI_STRING_LENGTH_MAX];
138
139+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
140+static int acpi_no_initrd_override;
141+extern struct acpi_table_header *acpi_find_dsdt_initrd(void);
142+#endif
143+
144 /*
145 * "Ode to _OSI(Linux)"
146 *
147@@ -325,7 +330,7 @@ acpi_os_predefined_override(const struct
148 return AE_OK;
149 }
150
151-acpi_status
152+acpi_status __init
153 acpi_os_table_override(struct acpi_table_header * existing_table,
154 struct acpi_table_header ** new_table)
155 {
156@@ -338,6 +343,16 @@ acpi_os_table_override(struct acpi_table
157 if (strncmp(existing_table->signature, "DSDT", 4) == 0)
158 *new_table = (struct acpi_table_header *)AmlCode;
159 #endif
160+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
161+ if ((strncmp(existing_table->signature, "DSDT", 4) == 0) &&
162+ !acpi_no_initrd_override) {
163+ struct acpi_table_header *initrd_table;
164+
165+ initrd_table = acpi_find_dsdt_initrd();
166+ if (initrd_table)
167+ *new_table = initrd_table;
168+ }
169+#endif
170 if (*new_table != NULL) {
171 printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], "
172 "this is unsafe: tainting kernel\n",
173@@ -348,6 +363,15 @@ acpi_os_table_override(struct acpi_table
174 return AE_OK;
175 }
176
177+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
178+static int __init acpi_no_initrd_override_setup(char *s)
179+{
180+ acpi_no_initrd_override = 1;
181+ return 1;
182+}
183+__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup);
184+#endif
185+
186 static irqreturn_t acpi_irq(int irq, void *dev_id)
187 {
188 u32 handled;
189--- a/drivers/acpi/tables/tbxface.c
190+++ b/drivers/acpi/tables/tbxface.c
191@@ -487,7 +487,7 @@ ACPI_EXPORT_SYMBOL(acpi_get_table_by_ind
192 * the RSDT/XSDT.
193 *
194 ******************************************************************************/
195-static acpi_status acpi_tb_load_namespace(void)
196+static acpi_status __init acpi_tb_load_namespace(void)
197 {
198 acpi_status status;
199 struct acpi_table_header *table;
200@@ -612,7 +612,7 @@ static acpi_status acpi_tb_load_namespac
201 *
202 ******************************************************************************/
203
204-acpi_status acpi_load_tables(void)
205+acpi_status __init acpi_load_tables(void)
206 {
207 acpi_status status;
208
209@@ -630,9 +630,6 @@ acpi_status acpi_load_tables(void)
210 return_ACPI_STATUS(status);
211 }
212
213-ACPI_EXPORT_SYMBOL(acpi_load_tables)
214-
215-
216 /*******************************************************************************
217 *
218 * FUNCTION: acpi_install_table_handler
219--- a/init/initramfs.c
220+++ b/init/initramfs.c
221@@ -6,6 +6,9 @@
222 #include <linux/delay.h>
223 #include <linux/string.h>
224 #include <linux/syscalls.h>
225+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
226+#include <acpi/acpi.h>
227+#endif
228
229 static __initdata char *message;
230 static void __init error(char *x)
231@@ -80,6 +83,12 @@ static __initdata unsigned long body_len
232 static __initdata uid_t uid;
233 static __initdata gid_t gid;
234 static __initdata unsigned rdev;
235+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
236+static __initdata char *file_looked_for;
237+static __initdata struct acpi_table_header *file_mem;
238+#else
239+const char *file_looked_for = NULL;
240+#endif
241
242 static void __init parse_header(char *s)
243 {
244@@ -113,6 +122,7 @@ static __initdata enum state {
245 SkipIt,
246 GotName,
247 CopyFile,
248+ CopyFileMem,
249 GotSymlink,
250 Reset
251 } state, next_state;
252@@ -257,6 +267,9 @@ static int __init do_name(void)
253 free_hash();
254 return 0;
255 }
256+ if (file_looked_for && S_ISREG(mode) &&
257+ (strcmp(collected, file_looked_for) == 0))
258+ state = CopyFileMem;
259 if (dry_run)
260 return 0;
261 clean_path(collected, mode);
262@@ -289,6 +302,40 @@ static int __init do_name(void)
263 return 0;
264 }
265
266+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
267+static int __init do_copy_mem(void)
268+{
269+ static void *file_current; /* current position in the memory */
270+ if (file_mem == NULL) {
271+ if (body_len < 4) { /* check especially against empty files */
272+ error("file is less than 4 bytes");
273+ return 1;
274+ }
275+ file_mem = kmalloc(body_len, GFP_ATOMIC);
276+ if (!file_mem) {
277+ error("failed to allocate enough memory");
278+ return 1;
279+ }
280+ file_current = file_mem;
281+ }
282+ if (count >= body_len) {
283+ memcpy(file_current, victim, body_len);
284+ eat(body_len);
285+ file_looked_for = NULL; /* don't find files with same name */
286+ state = SkipIt;
287+ return 0;
288+ } else {
289+ memcpy(file_current, victim, count);
290+ file_current += count;
291+ body_len -= count;
292+ eat(count);
293+ return 1;
294+ }
295+}
296+#else
297+#define do_copy_mem NULL
298+#endif
299+
300 static int __init do_copy(void)
301 {
302 if (count >= body_len) {
303@@ -323,6 +370,7 @@ static __initdata int (*actions[])(void)
304 [SkipIt] = do_skip,
305 [GotName] = do_name,
306 [CopyFile] = do_copy,
307+ [CopyFileMem] = do_copy_mem,
308 [GotSymlink] = do_symlink,
309 [Reset] = do_reset,
310 };
311@@ -560,3 +608,31 @@ static int __init populate_rootfs(void)
312 return 0;
313 }
314 rootfs_initcall(populate_rootfs);
315+
316+#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD
317+struct acpi_table_header * __init acpi_find_dsdt_initrd(void)
318+{
319+ char *err, *ramfs_dsdt_name = "DSDT.aml";
320+
321+ printk(KERN_INFO "ACPI: Checking initramfs for custom DSDT\n");
322+ file_mem = NULL;
323+ file_looked_for = ramfs_dsdt_name;
324+ err = unpack_to_rootfs((char *)initrd_start,
325+ initrd_end - initrd_start, 1);
326+ file_looked_for = NULL;
327+
328+ if (err) {
329+ /*
330+ * Even if reading the DSDT file was successful,
331+ * we give up if the initramfs cannot be entirely read.
332+ */
333+ kfree(file_mem);
334+ printk(KERN_ERR "ACPI: Aborded because %s.\n", err);
335+ return NULL;
336+ }
337+ if (file_mem)
338+ printk(KERN_INFO "ACPI: Found DSDT in %s.\n", ramfs_dsdt_name);
339+
340+ return file_mem;
341+}
342+#endif