2
0

330-MIPS-kexec-Accept-command-line-parameters-from-users.patch 7.8 KB

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