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

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