Magellan Linux

Annotation of /trunk/kernel26-magellan/patches-2.6.29-r8/0157-2.6.29-acpi-dsdt-initrd-0.9c.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1114 - (hide annotations) (download)
Sun Aug 22 17:59:15 2010 UTC (13 years, 8 months ago) by niro
File size: 9992 byte(s)
-added

1 niro 1114 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