Magellan Linux

Contents 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 - (show 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 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