Magellan Linux

Contents of /trunk/kernel26-alx/patches-2.6.26-r1/0157-2.6.26-acpi-dsdt-initrd-0.9a.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 682 - (show annotations) (download)
Wed Sep 17 19:47:46 2008 UTC (15 years, 7 months ago) by niro
File size: 9961 byte(s)
-2.6.26-alx-r1

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