]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/acpi-dsdt-initrd-v0.9a-2.6.25.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / acpi-dsdt-initrd-v0.9a-2.6.25.patch
1 From: Eric Piel <piel@localhost.(none)>
2 Subject: [PATCH 1/1] ACPI: initramfs DSDT override support
3 Patch-mainline: not yet
4
5
6 Permits to load of DSDT (the main ACPI table) from initramfs. In case this
7 option is selected, the initramfs is parsed at ACPI initialization (very early
8 boot time) to look for a file DSDT.aml . This aims at allowing users to
9 override the DSDT without recompiling the kernel. This is done by adding a new
10 feature to the initramfs parser so that one specific file can be directly
11 copied into memory.
12
13 This is derived from the patch v0.8 from http://gaugusch.at/kernel.shtml but
14 with kernel inclusion in mind: some clean-up's in the documentation, default
15 set to No, a kernel parameter to disable it at runtime, and most important, a
16 different approach for reading the initramfs which avoids using the filesystem
17 infrastructure.
18
19 It also contains a fix for compilation on non-ACPI platforms provided by Rene Rebe.
20
21 Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
22 Signed-off-by: Thomas Renninger <trenn@suse.de>
23 Signed-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