Contents of /trunk/kernel26-magellan/patches-2.6.27-r2/0157-2.6.27-acpi-dsdt-initrd-0.9c.patch
Parent Directory | Revision Log
Revision 726 -
(show annotations)
(download)
Tue Dec 23 00:16:32 2008 UTC (15 years, 9 months ago) by niro
File size: 10058 byte(s)
Tue Dec 23 00:16:32 2008 UTC (15 years, 9 months ago) by niro
File size: 10058 byte(s)
-ver bump to 2.6.27-r2: - updated to linux-2.6.27.10 - using tuxonice current-20081025 - adjusted kernel-configs to use tuxonice and enabled ufs filesystem support
1 | Date: Wed, 19 Mar 2008 23:00:04 +0100 |
2 | Subject: [PATCH] ACPI: initramfs DSDT override support |
3 | |
4 | Permits to load of DSDT (the main ACPI table) from initramfs. In case this |
5 | option is selected, the initramfs is parsed at ACPI initialization (very early |
6 | boot time) to look for a file called "DSDT.aml". This aims at allowing users to |
7 | override the DSDT without recompiling the kernel. |
8 | |
9 | Version 0.9 uses a different approach for reading the initramfs which avoids |
10 | using the filesystem infrastructure. It leverages the initramfs unpack code to find |
11 | and unpack the DSDT directly into the memory. |
12 | |
13 | v0.9a: Fix compilation on non-ACPI platforms by René Rebe <rene@exactcode.de> |
14 | v0.9b: Declare more functions __init by Jan Beulich <jbeulich@novell.com> |
15 | v0.9c: Allow root to be / instead of nothing, bug reported by Robert Hampovcan |
16 | |
17 | Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net> |
18 | --- |
19 | Documentation/acpi/dsdt-override.txt | 12 +++- |
20 | Documentation/acpi/initramfs-add-dsdt.sh | 43 ++++++++++++++ |
21 | Documentation/kernel-parameters.txt | 3 + |
22 | drivers/acpi/Kconfig | 11 ++++ |
23 | drivers/acpi/osl.c | 24 ++++++++ |
24 | init/initramfs.c | 89 ++++++++++++++++++++++++++++++ |
25 | 6 files changed, 180 insertions(+), 2 deletions(-) |
26 | create mode 100644 Documentation/acpi/initramfs-add-dsdt.sh |
27 | |
28 | diff --git a/Documentation/acpi/dsdt-override.txt b/Documentation/acpi/dsdt-override.txt |
29 | index febbb1b..5008f25 100644 |
30 | --- a/Documentation/acpi/dsdt-override.txt |
31 | +++ b/Documentation/acpi/dsdt-override.txt |
32 | @@ -1,7 +1,15 @@ |
33 | -Linux supports a method of overriding the BIOS DSDT: |
34 | +Linux supports two methods of overriding the BIOS DSDT: |
35 | |
36 | CONFIG_ACPI_CUSTOM_DSDT builds the image into the kernel. |
37 | |
38 | -When to use this method is described in detail on the |
39 | +CONFIG_ACPI_CUSTOM_DSDT_INITRD adds the image to the initrd. |
40 | + |
41 | +When to use these methods is described in detail on the |
42 | Linux/ACPI home page: |
43 | http://www.lesswatts.org/projects/acpi/overridingDSDT.php |
44 | + |
45 | +Note that if both options are used, the DSDT supplied |
46 | +by the INITRD method takes precedence. |
47 | + |
48 | +Documentation/initramfs-add-dsdt.sh is provided for convenience |
49 | +for use with the CONFIG_ACPI_CUSTOM_DSDT_INITRD method. |
50 | diff --git a/Documentation/acpi/initramfs-add-dsdt.sh b/Documentation/acpi/initramfs-add-dsdt.sh |
51 | new file mode 100644 |
52 | index 0000000..17ef6e8 |
53 | --- /dev/null |
54 | +++ b/Documentation/acpi/initramfs-add-dsdt.sh |
55 | @@ -0,0 +1,43 @@ |
56 | +#!/bin/bash |
57 | +# Adds a DSDT file to the initrd (if it's an initramfs) |
58 | +# first argument is the name of archive |
59 | +# second argument is the name of the file to add |
60 | +# The file will be copied as /DSDT.aml |
61 | + |
62 | +# 20060126: fix "Premature end of file" with some old cpio (Roland Robic) |
63 | +# 20060205: this time it should really work |
64 | + |
65 | +# check the arguments |
66 | +if [ $# -ne 2 ]; then |
67 | + program_name=$(basename $0) |
68 | + echo "\ |
69 | +$program_name: too few arguments |
70 | +Usage: $program_name initrd-name.img DSDT-to-add.aml |
71 | +Adds a DSDT file to an initrd (in initramfs format) |
72 | + |
73 | + initrd-name.img: filename of the initrd in initramfs format |
74 | + DSDT-to-add.aml: filename of the DSDT file to add |
75 | + " 1>&2 |
76 | + exit 1 |
77 | +fi |
78 | + |
79 | +# we should check it's an initramfs |
80 | + |
81 | +tempcpio=$(mktemp -d) |
82 | +# cleanup on exit, hangup, interrupt, quit, termination |
83 | +trap 'rm -rf $tempcpio' 0 1 2 3 15 |
84 | + |
85 | +# extract the archive |
86 | +gunzip -c "$1" > "$tempcpio"/initramfs.cpio || exit 1 |
87 | + |
88 | +# copy the DSDT file at the root of the directory so that we can call it "/DSDT.aml" |
89 | +cp -f "$2" "$tempcpio"/DSDT.aml |
90 | + |
91 | +# add the file |
92 | +cd "$tempcpio" |
93 | +(echo DSDT.aml | cpio --quiet -H newc -o -A -O "$tempcpio"/initramfs.cpio) || exit 1 |
94 | +cd "$OLDPWD" |
95 | + |
96 | +# re-compress the archive |
97 | +gzip -c "$tempcpio"/initramfs.cpio > "$1" |
98 | + |
99 | diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt |
100 | index e07c432..6849df2 100644 |
101 | --- a/Documentation/kernel-parameters.txt |
102 | +++ b/Documentation/kernel-parameters.txt |
103 | @@ -172,6 +172,9 @@ and is between 256 and 4096 characters. It is defined in the file |
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 | diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig |
114 | index c52fca8..8df213e 100644 |
115 | --- a/drivers/acpi/Kconfig |
116 | +++ b/drivers/acpi/Kconfig |
117 | @@ -303,6 +303,17 @@ config ACPI_CUSTOM_DSDT |
118 | bool |
119 | default ACPI_CUSTOM_DSDT_FILE != "" |
120 | |
121 | +config ACPI_CUSTOM_DSDT_INITRD |
122 | + bool "Read Custom DSDT from initramfs" |
123 | + depends on BLK_DEV_INITRD |
124 | + default n |
125 | + help |
126 | + This option supports a custom DSDT by optionally loading it from initrd. |
127 | + See Documentation/acpi/dsdt-override.txt |
128 | + |
129 | + If you are not using this feature now, but may use it later, |
130 | + it is safe to say Y here. |
131 | + |
132 | config ACPI_BLACKLIST_YEAR |
133 | int "Disable ACPI for systems before Jan 1st this year" if X86_32 |
134 | default 0 |
135 | diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c |
136 | index 235a138..c75f285 100644 |
137 | --- a/drivers/acpi/osl.c |
138 | +++ b/drivers/acpi/osl.c |
139 | @@ -96,6 +96,11 @@ static DEFINE_SPINLOCK(acpi_res_lock); |
140 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
141 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; |
142 | |
143 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
144 | +static __initdata int acpi_no_initrd_override; |
145 | +extern struct acpi_table_header *acpi_find_dsdt_initrd(void); |
146 | +#endif |
147 | + |
148 | /* |
149 | * "Ode to _OSI(Linux)" |
150 | * |
151 | @@ -338,6 +343,16 @@ acpi_os_table_override(struct acpi_table_header * existing_table, |
152 | if (strncmp(existing_table->signature, "DSDT", 4) == 0) |
153 | *new_table = (struct acpi_table_header *)AmlCode; |
154 | #endif |
155 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
156 | + if ((strncmp(existing_table->signature, "DSDT", 4) == 0) && |
157 | + !acpi_no_initrd_override) { |
158 | + struct acpi_table_header *initrd_table; |
159 | + |
160 | + initrd_table = acpi_find_dsdt_initrd(); |
161 | + if (initrd_table) |
162 | + *new_table = initrd_table; |
163 | + } |
164 | +#endif |
165 | if (*new_table != NULL) { |
166 | printk(KERN_WARNING PREFIX "Override [%4.4s-%8.8s], " |
167 | "this is unsafe: tainting kernel\n", |
168 | @@ -348,6 +363,15 @@ acpi_os_table_override(struct acpi_table_header * existing_table, |
169 | return AE_OK; |
170 | } |
171 | |
172 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
173 | +static int __init acpi_no_initrd_override_setup(char *s) |
174 | +{ |
175 | + acpi_no_initrd_override = 1; |
176 | + return 1; |
177 | +} |
178 | +__setup("acpi_no_initrd_override", acpi_no_initrd_override_setup); |
179 | +#endif |
180 | + |
181 | static irqreturn_t acpi_irq(int irq, void *dev_id) |
182 | { |
183 | u32 handled; |
184 | diff --git a/init/initramfs.c b/init/initramfs.c |
185 | index 8eeeccb..84f9a01 100644 |
186 | --- a/init/initramfs.c |
187 | +++ b/init/initramfs.c |
188 | @@ -6,6 +6,9 @@ |
189 | #include <linux/delay.h> |
190 | #include <linux/string.h> |
191 | #include <linux/syscalls.h> |
192 | +#ifdef ACPI_CONFIG |
193 | +#include <acpi/acpi.h> |
194 | +#endif |
195 | |
196 | static __initdata char *message; |
197 | static void __init error(char *x) |
198 | @@ -90,6 +93,12 @@ static __initdata unsigned long body_len, name_len; |
199 | static __initdata uid_t uid; |
200 | static __initdata gid_t gid; |
201 | static __initdata unsigned rdev; |
202 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
203 | +static __initdata char *file_looked_for; |
204 | +static __initdata struct acpi_table_header *file_mem; |
205 | +#else |
206 | +const char *file_looked_for = NULL; |
207 | +#endif |
208 | |
209 | static void __init parse_header(char *s) |
210 | { |
211 | @@ -123,6 +132,7 @@ static __initdata enum state { |
212 | SkipIt, |
213 | GotName, |
214 | CopyFile, |
215 | + CopyFileMem, |
216 | GotSymlink, |
217 | Reset |
218 | } state, next_state; |
219 | @@ -259,6 +269,54 @@ static void __init clean_path(char *path, mode_t mode) |
220 | |
221 | static __initdata int wfd; |
222 | |
223 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
224 | +static __init int is_file_looked_for(char *filename) |
225 | +{ |
226 | + char *tmp_collected = collected; |
227 | + if (file_looked_for == NULL) |
228 | + return 0; |
229 | + if (!S_ISREG(mode)) |
230 | + return 0; |
231 | + /* remove the leading / */ |
232 | + while (*tmp_collected == '/') |
233 | + tmp_collected++; |
234 | + return (strcmp(tmp_collected, file_looked_for) == 0); |
235 | +} |
236 | + |
237 | +static int __init do_copy_mem(void) |
238 | +{ |
239 | + static void *file_current; /* current position in the memory */ |
240 | + if (file_mem == NULL) { |
241 | + if (body_len < 4) { /* check especially against empty files */ |
242 | + error("file is less than 4 bytes"); |
243 | + return 1; |
244 | + } |
245 | + file_mem = kmalloc(body_len, GFP_ATOMIC); |
246 | + if (!file_mem) { |
247 | + error("failed to allocate enough memory"); |
248 | + return 1; |
249 | + } |
250 | + file_current = file_mem; |
251 | + } |
252 | + if (count >= body_len) { |
253 | + memcpy(file_current, victim, body_len); |
254 | + eat(body_len); |
255 | + file_looked_for = NULL; /* don't find files with same name */ |
256 | + state = SkipIt; |
257 | + return 0; |
258 | + } else { |
259 | + memcpy(file_current, victim, count); |
260 | + file_current += count; |
261 | + body_len -= count; |
262 | + eat(count); |
263 | + return 1; |
264 | + } |
265 | +} |
266 | +#else |
267 | +static inline int is_file_looked_for(char *filename) {return 0;} |
268 | +#define do_copy_mem NULL /* because it is used as a pointer */ |
269 | +#endif |
270 | + |
271 | static int __init do_name(void) |
272 | { |
273 | state = SkipIt; |
274 | @@ -267,6 +325,8 @@ static int __init do_name(void) |
275 | free_hash(); |
276 | return 0; |
277 | } |
278 | + if (is_file_looked_for(file_looked_for)) |
279 | + state = CopyFileMem; |
280 | if (dry_run) |
281 | return 0; |
282 | clean_path(collected, mode); |
283 | @@ -333,6 +393,7 @@ static __initdata int (*actions[])(void) = { |
284 | [SkipIt] = do_skip, |
285 | [GotName] = do_name, |
286 | [CopyFile] = do_copy, |
287 | + [CopyFileMem] = do_copy_mem, |
288 | [GotSymlink] = do_symlink, |
289 | [Reset] = do_reset, |
290 | }; |
291 | @@ -578,3 +639,31 @@ static int __init populate_rootfs(void) |
292 | return 0; |
293 | } |
294 | rootfs_initcall(populate_rootfs); |
295 | + |
296 | +#ifdef CONFIG_ACPI_CUSTOM_DSDT_INITRD |
297 | +struct __init acpi_table_header *acpi_find_dsdt_initrd(void) |
298 | +{ |
299 | + char *err, *ramfs_dsdt_name = "DSDT.aml"; |
300 | + |
301 | + printk(KERN_INFO "ACPI: Checking initramfs for custom DSDT\n"); |
302 | + file_mem = NULL; |
303 | + file_looked_for = ramfs_dsdt_name; |
304 | + err = unpack_to_rootfs((char *)initrd_start, |
305 | + initrd_end - initrd_start, 1); |
306 | + file_looked_for = NULL; |
307 | + |
308 | + if (err) { |
309 | + /* |
310 | + * Even if reading the DSDT file was successful, |
311 | + * we give up if the initramfs cannot be entirely read. |
312 | + */ |
313 | + kfree(file_mem); |
314 | + printk(KERN_ERR "ACPI: Aborded because %s.\n", err); |
315 | + return NULL; |
316 | + } |
317 | + if (file_mem) |
318 | + printk(KERN_INFO "ACPI: Found DSDT in %s.\n", ramfs_dsdt_name); |
319 | + |
320 | + return file_mem; |
321 | +} |
322 | +#endif |
323 | -- |
324 | 1.5.6.4 |
325 |