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