OpenWrt – Blame information for rev 3
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Yousong Zhou <yszhou4tech@gmail.com> |
2 | Subject: MIPS: kexec: Accept command line parameters from userspace. |
||
3 | |||
4 | Signed-off-by: Yousong Zhou <yszhou4tech@gmail.com> |
||
5 | --- |
||
6 | arch/mips/kernel/machine_kexec.c | 153 +++++++++++++++++++++++++++++++----- |
||
7 | arch/mips/kernel/machine_kexec.h | 20 +++++ |
||
8 | arch/mips/kernel/relocate_kernel.S | 21 +++-- |
||
9 | 3 files changed, 167 insertions(+), 27 deletions(-) |
||
10 | create mode 100644 arch/mips/kernel/machine_kexec.h |
||
11 | |||
12 | --- a/arch/mips/kernel/machine_kexec.c |
||
13 | +++ b/arch/mips/kernel/machine_kexec.c |
||
14 | @@ -10,14 +10,11 @@ |
||
15 | #include <linux/mm.h> |
||
16 | #include <linux/delay.h> |
||
17 | |||
18 | +#include <asm/bootinfo.h> |
||
19 | #include <asm/cacheflush.h> |
||
20 | #include <asm/page.h> |
||
21 | - |
||
22 | -extern const unsigned char relocate_new_kernel[]; |
||
23 | -extern const size_t relocate_new_kernel_size; |
||
24 | - |
||
25 | -extern unsigned long kexec_start_address; |
||
26 | -extern unsigned long kexec_indirection_page; |
||
27 | +#include <linux/uaccess.h> |
||
28 | +#include "machine_kexec.h" |
||
29 | |||
30 | int (*_machine_kexec_prepare)(struct kimage *) = NULL; |
||
31 | void (*_machine_kexec_shutdown)(void) = NULL; |
||
32 | @@ -28,6 +25,99 @@ atomic_t kexec_ready_to_reboot = ATOMIC_ |
||
33 | void (*_crash_smp_send_stop)(void) = NULL; |
||
34 | #endif |
||
35 | |||
36 | +static void machine_kexec_print_args(void) |
||
37 | +{ |
||
38 | + unsigned long argc = (int)kexec_args[0]; |
||
39 | + int i; |
||
40 | + |
||
41 | + pr_info("kexec_args[0] (argc): %lu\n", argc); |
||
42 | + pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]); |
||
43 | + pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]); |
||
44 | + pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]); |
||
45 | + |
||
46 | + for (i = 0; i < argc; i++) { |
||
47 | + pr_info("kexec_argv[%d] = %p, %s\n", |
||
48 | + i, kexec_argv[i], kexec_argv[i]); |
||
49 | + } |
||
50 | +} |
||
51 | + |
||
52 | +static void machine_kexec_init_argv(struct kimage *image) |
||
53 | +{ |
||
54 | + void __user *buf = NULL; |
||
55 | + size_t bufsz; |
||
56 | + size_t size; |
||
57 | + int i; |
||
58 | + |
||
59 | + bufsz = 0; |
||
60 | + for (i = 0; i < image->nr_segments; i++) { |
||
61 | + struct kexec_segment *seg; |
||
62 | + |
||
63 | + seg = &image->segment[i]; |
||
64 | + if (seg->bufsz < 6) |
||
65 | + continue; |
||
66 | + |
||
67 | + if (strncmp((char *) seg->buf, "kexec ", 6)) |
||
68 | + continue; |
||
69 | + |
||
70 | + buf = seg->buf; |
||
71 | + bufsz = seg->bufsz; |
||
72 | + break; |
||
73 | + } |
||
74 | + |
||
75 | + if (!buf) |
||
76 | + return; |
||
77 | + |
||
78 | + size = KEXEC_COMMAND_LINE_SIZE; |
||
79 | + size = min(size, bufsz); |
||
80 | + if (size < bufsz) |
||
81 | + pr_warn("kexec command line truncated to %zd bytes\n", size); |
||
82 | + |
||
83 | + /* Copy to kernel space */ |
||
84 | + copy_from_user(kexec_argv_buf, buf, size); |
||
85 | + kexec_argv_buf[size - 1] = 0; |
||
86 | +} |
||
87 | + |
||
88 | +static void machine_kexec_parse_argv(struct kimage *image) |
||
89 | +{ |
||
90 | + char *reboot_code_buffer; |
||
91 | + int reloc_delta; |
||
92 | + char *ptr; |
||
93 | + int argc; |
||
94 | + int i; |
||
95 | + |
||
96 | + ptr = kexec_argv_buf; |
||
97 | + argc = 0; |
||
98 | + |
||
99 | + /* |
||
100 | + * convert command line string to array of parameters |
||
101 | + * (as bootloader does). |
||
102 | + */ |
||
103 | + while (ptr && *ptr && (KEXEC_MAX_ARGC > argc)) { |
||
104 | + if (*ptr == ' ') { |
||
105 | + *ptr++ = '\0'; |
||
106 | + continue; |
||
107 | + } |
||
108 | + |
||
109 | + kexec_argv[argc++] = ptr; |
||
110 | + ptr = strchr(ptr, ' '); |
||
111 | + } |
||
112 | + |
||
113 | + if (!argc) |
||
114 | + return; |
||
115 | + |
||
116 | + kexec_args[0] = argc; |
||
117 | + kexec_args[1] = (unsigned long)kexec_argv; |
||
118 | + kexec_args[2] = 0; |
||
119 | + kexec_args[3] = 0; |
||
120 | + |
||
121 | + reboot_code_buffer = page_address(image->control_code_page); |
||
122 | + reloc_delta = reboot_code_buffer - (char *)kexec_relocate_new_kernel; |
||
123 | + |
||
124 | + kexec_args[1] += reloc_delta; |
||
125 | + for (i = 0; i < argc; i++) |
||
126 | + kexec_argv[i] += reloc_delta; |
||
127 | +} |
||
128 | + |
||
129 | static void kexec_image_info(const struct kimage *kimage) |
||
130 | { |
||
131 | unsigned long i; |
||
132 | @@ -52,6 +142,18 @@ int |
||
133 | machine_kexec_prepare(struct kimage *kimage) |
||
134 | { |
||
135 | kexec_image_info(kimage); |
||
136 | + /* |
||
137 | + * Whenever arguments passed from kexec-tools, Init the arguments as |
||
138 | + * the original ones to try avoiding booting failure. |
||
139 | + */ |
||
140 | + |
||
141 | + kexec_args[0] = fw_arg0; |
||
142 | + kexec_args[1] = fw_arg1; |
||
143 | + kexec_args[2] = fw_arg2; |
||
144 | + kexec_args[3] = fw_arg3; |
||
145 | + |
||
146 | + machine_kexec_init_argv(kimage); |
||
147 | + machine_kexec_parse_argv(kimage); |
||
148 | |||
149 | if (_machine_kexec_prepare) |
||
150 | return _machine_kexec_prepare(kimage); |
||
151 | @@ -89,10 +191,12 @@ machine_kexec(struct kimage *image) |
||
152 | unsigned long *ptr; |
||
153 | |||
154 | reboot_code_buffer = |
||
155 | - (unsigned long)page_address(image->control_code_page); |
||
156 | + (unsigned long)page_address(image->control_code_page); |
||
157 | + pr_info("reboot_code_buffer = %p\n", (void *)reboot_code_buffer); |
||
158 | |||
159 | kexec_start_address = |
||
160 | (unsigned long) phys_to_virt(image->start); |
||
161 | + pr_info("kexec_start_address = %p\n", (void *)kexec_start_address); |
||
162 | |||
163 | if (image->type == KEXEC_TYPE_DEFAULT) { |
||
164 | kexec_indirection_page = |
||
165 | @@ -100,9 +204,19 @@ machine_kexec(struct kimage *image) |
||
166 | } else { |
||
167 | kexec_indirection_page = (unsigned long)&image->head; |
||
168 | } |
||
169 | + pr_info("kexec_indirection_page = %p\n", (void *)kexec_indirection_page); |
||
170 | |||
171 | - memcpy((void*)reboot_code_buffer, relocate_new_kernel, |
||
172 | - relocate_new_kernel_size); |
||
173 | + pr_info("Where is memcpy: %p\n", memcpy); |
||
174 | + pr_info("kexec_relocate_new_kernel = %p, kexec_relocate_new_kernel_end = %p\n", |
||
175 | + (void *)kexec_relocate_new_kernel, &kexec_relocate_new_kernel_end); |
||
176 | + pr_info("Copy %lu bytes from %p to %p\n", KEXEC_RELOCATE_NEW_KERNEL_SIZE, |
||
177 | + (void *)kexec_relocate_new_kernel, (void *)reboot_code_buffer); |
||
178 | + memcpy((void*)reboot_code_buffer, kexec_relocate_new_kernel, |
||
179 | + KEXEC_RELOCATE_NEW_KERNEL_SIZE); |
||
180 | + |
||
181 | + pr_info("Before _print_args().\n"); |
||
182 | + machine_kexec_print_args(); |
||
183 | + pr_info("Before eval loop.\n"); |
||
184 | |||
185 | /* |
||
186 | * The generic kexec code builds a page list with physical |
||
3 | office | 187 | @@ -121,15 +235,16 @@ machine_kexec(struct kimage *image) |
1 | office | 188 | /* |
189 | * we do not want to be bothered. |
||
190 | */ |
||
191 | + pr_info("Before irq_disable.\n"); |
||
192 | local_irq_disable(); |
||
193 | |||
194 | - printk("Will call new kernel at %08lx\n", image->start); |
||
195 | - printk("Bye ...\n"); |
||
196 | + pr_info("Will call new kernel at %08lx\n", image->start); |
||
197 | + pr_info("Bye ...\n"); |
||
198 | __flush_cache_all(); |
||
199 | #ifdef CONFIG_SMP |
||
200 | /* All secondary cpus now may jump to kexec_wait cycle */ |
||
201 | relocated_kexec_smp_wait = reboot_code_buffer + |
||
202 | - (void *)(kexec_smp_wait - relocate_new_kernel); |
||
203 | + (void *)(kexec_smp_wait - kexec_relocate_new_kernel); |
||
204 | smp_wmb(); |
||
205 | atomic_set(&kexec_ready_to_reboot, 1); |
||
206 | #endif |
||
207 | --- /dev/null |
||
208 | +++ b/arch/mips/kernel/machine_kexec.h |
||
209 | @@ -0,0 +1,20 @@ |
||
210 | +#ifndef _MACHINE_KEXEC_H |
||
211 | +#define _MACHINE_KEXEC_H |
||
212 | + |
||
213 | +#ifndef __ASSEMBLY__ |
||
214 | +extern const unsigned char kexec_relocate_new_kernel[]; |
||
215 | +extern unsigned long kexec_relocate_new_kernel_end; |
||
216 | +extern unsigned long kexec_start_address; |
||
217 | +extern unsigned long kexec_indirection_page; |
||
218 | + |
||
219 | +extern char kexec_argv_buf[]; |
||
220 | +extern char *kexec_argv[]; |
||
221 | + |
||
222 | +#define KEXEC_RELOCATE_NEW_KERNEL_SIZE ((unsigned long)&kexec_relocate_new_kernel_end - (unsigned long)kexec_relocate_new_kernel) |
||
223 | +#endif /* !__ASSEMBLY__ */ |
||
224 | + |
||
225 | +#define KEXEC_COMMAND_LINE_SIZE 256 |
||
226 | +#define KEXEC_ARGV_SIZE (KEXEC_COMMAND_LINE_SIZE / 16) |
||
227 | +#define KEXEC_MAX_ARGC (KEXEC_ARGV_SIZE / sizeof(long)) |
||
228 | + |
||
229 | +#endif |
||
230 | --- a/arch/mips/kernel/relocate_kernel.S |
||
231 | +++ b/arch/mips/kernel/relocate_kernel.S |
||
232 | @@ -12,8 +12,9 @@ |
||
233 | #include <asm/mipsregs.h> |
||
234 | #include <asm/stackframe.h> |
||
235 | #include <asm/addrspace.h> |
||
236 | +#include "machine_kexec.h" |
||
237 | |||
238 | -LEAF(relocate_new_kernel) |
||
239 | +LEAF(kexec_relocate_new_kernel) |
||
240 | PTR_L a0, arg0 |
||
241 | PTR_L a1, arg1 |
||
242 | PTR_L a2, arg2 |
||
243 | @@ -98,7 +99,7 @@ done: |
||
244 | #endif |
||
245 | /* jump to kexec_start_address */ |
||
246 | j s1 |
||
247 | - END(relocate_new_kernel) |
||
248 | + END(kexec_relocate_new_kernel) |
||
249 | |||
250 | #ifdef CONFIG_SMP |
||
251 | /* |
||
252 | @@ -184,9 +185,15 @@ kexec_indirection_page: |
||
253 | PTR 0 |
||
254 | .size kexec_indirection_page, PTRSIZE |
||
255 | |||
256 | -relocate_new_kernel_end: |
||
257 | +kexec_argv_buf: |
||
258 | + EXPORT(kexec_argv_buf) |
||
259 | + .skip KEXEC_COMMAND_LINE_SIZE |
||
260 | + .size kexec_argv_buf, KEXEC_COMMAND_LINE_SIZE |
||
261 | + |
||
262 | +kexec_argv: |
||
263 | + EXPORT(kexec_argv) |
||
264 | + .skip KEXEC_ARGV_SIZE |
||
265 | + .size kexec_argv, KEXEC_ARGV_SIZE |
||
266 | |||
267 | -relocate_new_kernel_size: |
||
268 | - EXPORT(relocate_new_kernel_size) |
||
269 | - PTR relocate_new_kernel_end - relocate_new_kernel |
||
270 | - .size relocate_new_kernel_size, PTRSIZE |
||
271 | +kexec_relocate_new_kernel_end: |
||
272 | + EXPORT(kexec_relocate_new_kernel_end) |