* upgrade ixp4xx to 2.6.23.12 * upgrade to the new ethernet driver (temporary breaks...
[openwrt/openwrt.git] / target / linux / ixp4xx / patches-2.6.23 / 096-kexec_cmdline.patch
1 diff -uprN linux-2.6.23.orig/kernel/ksysfs.c linux-2.6.23/kernel/ksysfs.c
2 --- linux-2.6.23.orig/kernel/ksysfs.c 2007-10-09 15:31:38.000000000 -0500
3 +++ linux-2.6.23/kernel/ksysfs.c 2007-10-11 01:10:26.000000000 -0500
4 @@ -49,6 +49,165 @@ KERNEL_ATTR_RW(uevent_helper);
5 #endif
6
7 #ifdef CONFIG_KEXEC
8 +
9 +#include <asm/setup.h>
10 +
11 +extern unsigned long kexec_boot_params;
12 +
13 +char kexec_cmdline[COMMAND_LINE_SIZE] = "";
14 +
15 +static void
16 +replace_cmdline_tag(void)
17 +{
18 + char *t;
19 + struct tag *real;
20 + struct tag *copy;
21 + struct tag *rend;
22 + int i;
23 +
24 +/* TODO: check the return params */
25 + t = kmalloc(KEXEC_BOOT_PARAMS_SIZE + COMMAND_LINE_SIZE, GFP_KERNEL);
26 + memset((void *)t, 0, KEXEC_BOOT_PARAMS_SIZE + COMMAND_LINE_SIZE);
27 +
28 +/* TODO: validate that the boot params are ATAGS, in fact */
29 +
30 + copy = (struct tag *)t;
31 + real = (struct tag *)kexec_boot_params;
32 + rend = (struct tag *)(kexec_boot_params + KEXEC_BOOT_PARAMS_SIZE);
33 + while ((real->hdr.size) && (real < rend)) {
34 + if (real->hdr.tag != ATAG_CMDLINE) {
35 + memcpy((void *)copy, (void *)real, real->hdr.size * 4);
36 + copy = tag_next(copy);
37 + }
38 + real = tag_next(real);
39 + }
40 +
41 +/* TODO: validate that we have enough space in the buffer */
42 +
43 + i = strlen(kexec_cmdline);
44 + if (i) {
45 + copy->hdr.tag = ATAG_CMDLINE;
46 + copy->hdr.size = (sizeof(struct tag_header) + i + 1 + 4) >> 2;
47 + strcpy(copy->u.cmdline.cmdline, kexec_cmdline);
48 + copy = tag_next(copy);
49 + }
50 +
51 + copy->hdr.tag = ATAG_NONE; /* Empty tag ends list */
52 + copy->hdr.size = 0; /* zero length */
53 +
54 +/* TODO: validate that the temporary buffer isn't too full */
55 +
56 + memcpy((void *)kexec_boot_params, (void *)t, KEXEC_BOOT_PARAMS_SIZE);
57 +
58 + kfree(t); /* Don't forget to free the big buffer we used */
59 +}
60 +
61 +static ssize_t kexec_cmdline_show(struct kset *kset, char *page)
62 +{
63 + return sprintf(page, "%s\n", kexec_cmdline);
64 +}
65 +
66 +static ssize_t kexec_cmdline_store(struct kset *kset, const char *page,
67 + size_t count)
68 +{
69 + if ((count + 1) > COMMAND_LINE_SIZE)
70 + count = COMMAND_LINE_SIZE;
71 + memcpy(kexec_cmdline, page, count);
72 + kexec_cmdline[count] = '\0';
73 + if (count && (kexec_cmdline[count - 1] == '\n'))
74 + kexec_cmdline[count - 1] = '\0';
75 + replace_cmdline_tag();
76 + return count;
77 +}
78 +KERNEL_ATTR_RW(kexec_cmdline);
79 +
80 +static ssize_t kexec_boot_params_show(struct kset *kset, char *page)
81 +{
82 + unsigned long *p;
83 + char buf[PAGE_SIZE];
84 + int keep_doing;
85 +
86 + p = (unsigned long *)kexec_boot_params;
87 +
88 + /* if this doesn't look like atags, just print first few words */
89 + if (p[1] != ATAG_CORE)
90 + return sprintf(page, "0x%lx 0x%lx 0x%lx 0x%lx\n",
91 + p[0], p[1], p[2], p[3]);
92 +
93 + /* carefully walk the atag list, and print out the structure */
94 + keep_doing = 1;
95 + do {
96 + switch (p[1]) {
97 + case ATAG_CORE:
98 + /* watch out, core tag is permitted to be empty */
99 + if (p[0] == 5)
100 + sprintf(buf,
101 + "CORE flg=%ld pgsz=%ld rdev=0x%lx\n",
102 + p[2], p[3], p[4]);
103 + else
104 + sprintf(buf,"CORE\n");
105 + break;
106 + case ATAG_MEM:
107 + sprintf(buf,"MEM %ldM@0x%lx\n", p[2] / (1024 * 1024),
108 + p[3]);
109 + break;
110 + case ATAG_VIDEOTEXT:
111 + sprintf(buf,"VIDEOTEXT sz=%ld\n", p[0]);
112 + break;
113 + case ATAG_RAMDISK:
114 + sprintf(buf,"RAMDISK prmpt=%ld %ldK@0x%lx\n",
115 + p[2], p[3], p[4]);
116 + break;
117 + case ATAG_INITRD2:
118 + sprintf(buf,"INITRD2 %ldK@0x%lx\n", p[3] / 1024, p[2]);
119 + break;
120 + case ATAG_SERIAL:
121 + sprintf(buf,"SERIAL high=0x%08lx low=0x%08lx\n",
122 + p[3], p[2]);
123 + break;
124 + case ATAG_REVISION:
125 + sprintf(buf,"REVISION rev=%ld\n", p[2]);
126 + break;
127 + case ATAG_VIDEOLFB:
128 + sprintf(buf,"VIDEOLFB sz=%ld\n", p[0]);
129 + break;
130 + case ATAG_CMDLINE:
131 + sprintf(buf,"CMD \"%s\"\n", (char *)&p[2]);
132 + break;
133 + case ATAG_NONE:
134 + sprintf(buf,"NONE\n");
135 + keep_doing = 0;
136 + break;
137 + default:
138 + sprintf(buf,"-unknown- sz=%ld\n", p[0]);
139 + break;
140 + }
141 +
142 + /* carefully add to page */
143 + if ((strlen(buf) + strlen(page)) < PAGE_SIZE) {
144 + strcat(page, buf);
145 + } else {
146 + keep_doing = 0;
147 + }
148 +
149 + /* stop when we encounter a header length of 0 */
150 + if (p[0] == 0)
151 + keep_doing = 0;
152 +
153 + /* go to the next tag */
154 + p += p[0];
155 +
156 + /* stop if we walked off the end of the buffer */
157 + if (p > (unsigned long *)(kexec_boot_params +
158 + KEXEC_BOOT_PARAMS_SIZE))
159 + keep_doing = 0;
160 +
161 + } while (keep_doing);
162 +
163 + return (strlen(page));
164 +}
165 +KERNEL_ATTR_RO(kexec_boot_params);
166 +
167 static ssize_t kexec_loaded_show(struct kset *kset, char *page)
168 {
169 return sprintf(page, "%d\n", !!kexec_image);
170 @@ -95,6 +254,8 @@ static struct attribute * kernel_attrs[]
171 #ifdef CONFIG_KEXEC
172 &kexec_loaded_attr.attr,
173 &kexec_crash_loaded_attr.attr,
174 + &kexec_cmdline_attr.attr,
175 + &kexec_boot_params_attr.attr,
176 #endif
177 NULL
178 };