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

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