Magellan Linux

Annotation of /trunk/kernel26-magellan-server/patches-2.6.27-r2/0157-2.6.27-acpi-dsdt-initrd-0.9c.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 728 - (hide annotations) (download)
Tue Dec 23 09:41:15 2008 UTC (15 years, 4 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 niro 728 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