335-mips-kexec-cleanup-kexec-tools-parameter-handling.patch 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. --- a/arch/mips/kernel/machine_kexec.c
  2. +++ b/arch/mips/kernel/machine_kexec.c
  3. @@ -23,67 +23,104 @@ void (*relocated_kexec_smp_wait) (void *
  4. atomic_t kexec_ready_to_reboot = ATOMIC_INIT(0);
  5. #endif
  6. -static void machine_kexec_init_args(void)
  7. +#define KEXEC_MIPS_ARGV_BUF_SIZE COMMAND_LINE_SIZE
  8. +#define KEXEC_MIPS_ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15)
  9. +
  10. +char kexec_argv_buf[KEXEC_MIPS_ARGV_BUF_SIZE] __kexec;
  11. +char *kexec_argv[KEXEC_MIPS_ARGV_MAX_ARGS] __kexec;
  12. +
  13. +static void
  14. +machine_kexec_print_args(void)
  15. {
  16. - kexec_args[0] = fw_arg0;
  17. - kexec_args[1] = fw_arg1;
  18. - kexec_args[2] = fw_arg2;
  19. - kexec_args[3] = fw_arg3;
  20. + int i;
  21. pr_info("kexec_args[0] (argc): %lu\n", kexec_args[0]);
  22. pr_info("kexec_args[1] (argv): %p\n", (void *)kexec_args[1]);
  23. pr_info("kexec_args[2] (env ): %p\n", (void *)kexec_args[2]);
  24. pr_info("kexec_args[3] (desc): %p\n", (void *)kexec_args[3]);
  25. -}
  26. -#define ARGV_MAX_ARGS (COMMAND_LINE_SIZE / 15)
  27. + for (i = 0; i < kexec_args[0]; i++)
  28. + pr_info("kexec_argv[%d] = %p, %s\n", i,
  29. + (char *)kexec_argv[i], (char *)kexec_argv[i]);
  30. +}
  31. -int machine_kexec_pass_args(struct kimage *image)
  32. +static void
  33. +machine_kexec_init_argv(struct kimage *image)
  34. {
  35. - int i, argc = 0;
  36. - char *bootloader = "kexec";
  37. - int *kexec_argv = (int *)kexec_args[1];
  38. + void __user *buf = NULL;
  39. + size_t bufsz;
  40. + size_t size;
  41. + int i;
  42. + bufsz = 0;
  43. for (i = 0; i < image->nr_segments; i++) {
  44. - if (!strncmp(bootloader, (char *)image->segment[i].buf,
  45. - strlen(bootloader))) {
  46. - /*
  47. - * convert command line string to array
  48. - * of parameters (as bootloader does).
  49. - */
  50. - /*
  51. - * Note: we do treat the 1st string "kexec" as an
  52. - * argument ;-) so, argc here is 1.
  53. - */
  54. - char *str = (char *)image->segment[i].buf;
  55. - char *ptr = strchr(str, ' ');
  56. - char *kbuf = (char *)kexec_argv[0];
  57. - /* Whenever --command-line or --append used, "kexec" is copied */
  58. - argc = 1;
  59. - /* Parse the offset */
  60. - while (ptr && (ARGV_MAX_ARGS > argc)) {
  61. - *ptr = '\0';
  62. - if (ptr[1] != ' ' && ptr[1] != '\0') {
  63. - int offt = (int)(ptr - str + 1);
  64. - kexec_argv[argc] = (int)kbuf + offt;
  65. - argc++;
  66. - }
  67. - ptr = strchr(ptr + 1, ' ');
  68. - }
  69. - if (argc > 1) {
  70. - /* Copy to kernel space */
  71. - copy_from_user(kbuf, (char *)image->segment[i].buf, image->segment[i].bufsz);
  72. - fw_arg0 = kexec_args[0] = argc;
  73. - }
  74. - break;
  75. + struct kexec_segment *seg;
  76. +
  77. + seg = &image->segment[i];
  78. + if (seg->bufsz < 6)
  79. + continue;
  80. +
  81. + if (strncmp((char *) seg->buf, "kexec", 5))
  82. + continue;
  83. +
  84. + /* don't copy "kexec" */
  85. + buf = seg->buf + 5;
  86. + bufsz = seg->bufsz - 5;
  87. + break;
  88. + }
  89. +
  90. + if (!buf)
  91. + return;
  92. +
  93. + size = KEXEC_MIPS_ARGV_BUF_SIZE - 1;
  94. + size = min(size, bufsz);
  95. + if (size < bufsz)
  96. + pr_warn("kexec command line truncated to %zd bytes\n", size);
  97. +
  98. + /* Copy to kernel space */
  99. + copy_from_user(kexec_argv_buf, buf, size);
  100. +}
  101. +
  102. +static void
  103. +machine_kexec_parse_argv(struct kimage *image)
  104. +{
  105. + char *reboot_code_buffer;
  106. + int reloc_delta;
  107. + char *ptr;
  108. + int argc;
  109. + int i;
  110. +
  111. + ptr = kexec_argv_buf;
  112. + argc = 0;
  113. +
  114. + /*
  115. + * convert command line string to array of parameters
  116. + * (as bootloader does).
  117. + */
  118. + while (ptr && *ptr && (KEXEC_MIPS_ARGV_MAX_ARGS > argc)) {
  119. + if (*ptr == ' ') {
  120. + *ptr++ = '\0';
  121. + continue;
  122. }
  123. +
  124. + kexec_argv[argc++] = ptr;
  125. + ptr = strchr(ptr, ' ');
  126. }
  127. - pr_info("argc = %lu\n", kexec_args[0]);
  128. - for (i = 0; i < kexec_args[0]; i++)
  129. - pr_info("argv[%d] = %p, %s\n", i, (char *)kexec_argv[i], (char *)kexec_argv[i]);
  130. + if (!argc)
  131. + return;
  132. - return 0;
  133. + kexec_args[0] = argc;
  134. + kexec_args[1] = (unsigned long)kexec_argv;
  135. + kexec_args[2] = 0;
  136. + kexec_args[3] = 0;
  137. +
  138. + reboot_code_buffer = page_address(image->control_code_page);
  139. + reloc_delta = reboot_code_buffer - (char *) &__start___kexec_relocate;
  140. +
  141. + kexec_args[1] += reloc_delta;
  142. + for (i = 0; i < argc; i++)
  143. + kexec_argv[i] += reloc_delta;
  144. }
  145. int
  146. @@ -95,8 +132,14 @@ machine_kexec_prepare(struct kimage *kim
  147. *
  148. * This can be overrided by _machine_kexec_prepare().
  149. */
  150. - machine_kexec_init_args();
  151. - machine_kexec_pass_args(kimage);
  152. +
  153. + kexec_args[0] = fw_arg0;
  154. + kexec_args[1] = fw_arg1;
  155. + kexec_args[2] = fw_arg2;
  156. + kexec_args[3] = fw_arg3;
  157. +
  158. + machine_kexec_init_argv(kimage);
  159. + machine_kexec_parse_argv(kimage);
  160. if (_machine_kexec_prepare)
  161. return _machine_kexec_prepare(kimage);
  162. @@ -152,11 +195,13 @@ machine_kexec(struct kimage *image)
  163. pr_info("kexec_indirection_page = %p\n",
  164. (void *)kexec_indirection_page);
  165. + pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
  166. + &__start___kexec_relocate, (void *)reboot_code_buffer);
  167. +
  168. memcpy((void *)reboot_code_buffer, &__start___kexec_relocate,
  169. kexec_relocate_size);
  170. - pr_info("Copy kexec_relocate section from %p to reboot_code_buffer: %p\n",
  171. - &__start___kexec_relocate, (void *)reboot_code_buffer);
  172. + machine_kexec_print_args();
  173. /*
  174. * The generic kexec code builds a page list with physical