start.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2011-2012 The Chromium OS Authors.
  4. */
  5. #include <common.h>
  6. #include <command.h>
  7. #include <dm/root.h>
  8. #include <errno.h>
  9. #include <init.h>
  10. #include <os.h>
  11. #include <cli.h>
  12. #include <sort.h>
  13. #include <asm/getopt.h>
  14. #include <asm/io.h>
  15. #include <asm/malloc.h>
  16. #include <asm/sections.h>
  17. #include <asm/state.h>
  18. #include <linux/ctype.h>
  19. DECLARE_GLOBAL_DATA_PTR;
  20. static char **os_argv;
  21. /* Compare two options so that they can be sorted into alphabetical order */
  22. static int h_compare_opt(const void *p1, const void *p2)
  23. {
  24. const struct sandbox_cmdline_option *opt1 = p1;
  25. const struct sandbox_cmdline_option *opt2 = p2;
  26. const char *str1, *str2;
  27. char flag1[2], flag2[2];
  28. opt1 = *(struct sandbox_cmdline_option **)p1;
  29. opt2 = *(struct sandbox_cmdline_option **)p2;
  30. flag1[1] = '\0';
  31. flag2[1] = '\0';
  32. *flag1 = opt1->flag_short < 0x100 ? opt1->flag_short : '\0';
  33. *flag2 = opt2->flag_short < 0x100 ? opt2->flag_short : '\0';
  34. str1 = *flag1 ? flag1 : opt1->flag;
  35. str2 = *flag2 ? flag2 : opt2->flag;
  36. /*
  37. * Force lower-case flags to come before upper-case ones. We only
  38. * support upper-case for short flags.
  39. */
  40. if (isalpha(*str1) && isalpha(*str2) &&
  41. tolower(*str1) == tolower(*str2))
  42. return isupper(*str1) - isupper(*str2);
  43. return strcasecmp(str1, str2);
  44. }
  45. int sandbox_early_getopt_check(void)
  46. {
  47. struct sandbox_state *state = state_get_current();
  48. struct sandbox_cmdline_option **sb_opt = __u_boot_sandbox_option_start;
  49. size_t num_options = __u_boot_sandbox_option_count();
  50. size_t i;
  51. int max_arg_len, max_noarg_len;
  52. struct sandbox_cmdline_option **sorted_opt;
  53. int size;
  54. /* parse_err will be a string of the faulting option */
  55. if (!state->parse_err)
  56. return 0;
  57. if (strcmp(state->parse_err, "help")) {
  58. printf("u-boot: error: failed while parsing option: %s\n"
  59. "\ttry running with --help for more information.\n",
  60. state->parse_err);
  61. os_exit(1);
  62. }
  63. printf(
  64. "u-boot, a command line test interface to U-Boot\n\n"
  65. "Usage: u-boot [options]\n"
  66. "Options:\n");
  67. max_arg_len = 0;
  68. for (i = 0; i < num_options; ++i)
  69. max_arg_len = max((int)strlen(sb_opt[i]->flag), max_arg_len);
  70. max_noarg_len = max_arg_len + 7;
  71. /* Sort the options */
  72. size = sizeof(*sorted_opt) * num_options;
  73. sorted_opt = malloc(size);
  74. if (!sorted_opt) {
  75. printf("No memory to sort options\n");
  76. os_exit(1);
  77. }
  78. memcpy(sorted_opt, sb_opt, size);
  79. qsort(sorted_opt, num_options, sizeof(*sorted_opt), h_compare_opt);
  80. for (i = 0; i < num_options; ++i) {
  81. struct sandbox_cmdline_option *opt = sorted_opt[i];
  82. /* first output the short flag if it has one */
  83. if (opt->flag_short >= 0x100)
  84. printf(" ");
  85. else
  86. printf(" -%c, ", opt->flag_short);
  87. /* then the long flag */
  88. if (opt->has_arg)
  89. printf("--%-*s <arg> ", max_arg_len, opt->flag);
  90. else
  91. printf("--%-*s", max_noarg_len, opt->flag);
  92. /* finally the help text */
  93. printf(" %s\n", opt->help);
  94. }
  95. os_exit(0);
  96. }
  97. int misc_init_f(void)
  98. {
  99. return sandbox_early_getopt_check();
  100. }
  101. static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg)
  102. {
  103. /* just flag to sandbox_early_getopt_check to show usage */
  104. return 1;
  105. }
  106. SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help");
  107. #ifndef CONFIG_SPL_BUILD
  108. int sandbox_main_loop_init(void)
  109. {
  110. struct sandbox_state *state = state_get_current();
  111. /* Execute command if required */
  112. if (state->cmd || state->run_distro_boot) {
  113. int retval = 0;
  114. cli_init();
  115. #ifdef CONFIG_CMDLINE
  116. if (state->cmd)
  117. retval = run_command_list(state->cmd, -1, 0);
  118. if (state->run_distro_boot)
  119. retval = cli_simple_run_command("run distro_bootcmd",
  120. 0);
  121. #endif
  122. if (!state->interactive)
  123. os_exit(retval);
  124. }
  125. return 0;
  126. }
  127. #endif
  128. static int sandbox_cmdline_cb_boot(struct sandbox_state *state,
  129. const char *arg)
  130. {
  131. state->run_distro_boot = true;
  132. return 0;
  133. }
  134. SANDBOX_CMDLINE_OPT_SHORT(boot, 'b', 0, "Run distro boot commands");
  135. static int sandbox_cmdline_cb_command(struct sandbox_state *state,
  136. const char *arg)
  137. {
  138. state->cmd = arg;
  139. return 0;
  140. }
  141. SANDBOX_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command");
  142. static int sandbox_cmdline_cb_fdt(struct sandbox_state *state, const char *arg)
  143. {
  144. state->fdt_fname = arg;
  145. return 0;
  146. }
  147. SANDBOX_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT");
  148. static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state,
  149. const char *arg)
  150. {
  151. const char *fmt = "%s.dtb";
  152. char *fname;
  153. int len;
  154. len = strlen(state->argv[0]) + strlen(fmt) + 1;
  155. fname = malloc(len);
  156. if (!fname)
  157. return -ENOMEM;
  158. snprintf(fname, len, fmt, state->argv[0]);
  159. state->fdt_fname = fname;
  160. return 0;
  161. }
  162. SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0,
  163. "Use the default u-boot.dtb control FDT in U-Boot directory");
  164. static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state,
  165. const char *arg)
  166. {
  167. const char *fmt = "/arch/sandbox/dts/test.dtb";
  168. char *p;
  169. char *fname;
  170. int len;
  171. len = strlen(state->argv[0]) + strlen(fmt) + 1;
  172. fname = malloc(len);
  173. if (!fname)
  174. return -ENOMEM;
  175. strcpy(fname, state->argv[0]);
  176. p = strrchr(fname, '/');
  177. if (!p)
  178. p = fname + strlen(fname);
  179. len -= p - fname;
  180. snprintf(p, len, fmt, p);
  181. state->fdt_fname = fname;
  182. return 0;
  183. }
  184. SANDBOX_CMDLINE_OPT_SHORT(test_fdt, 'T', 0,
  185. "Use the test.dtb control FDT in U-Boot directory");
  186. static int sandbox_cmdline_cb_interactive(struct sandbox_state *state,
  187. const char *arg)
  188. {
  189. state->interactive = true;
  190. return 0;
  191. }
  192. SANDBOX_CMDLINE_OPT_SHORT(interactive, 'i', 0, "Enter interactive mode");
  193. static int sandbox_cmdline_cb_jump(struct sandbox_state *state,
  194. const char *arg)
  195. {
  196. /* Remember to delete this U-Boot image later */
  197. state->jumped_fname = arg;
  198. return 0;
  199. }
  200. SANDBOX_CMDLINE_OPT_SHORT(jump, 'j', 1, "Jumped from previous U-Boot");
  201. static int sandbox_cmdline_cb_memory(struct sandbox_state *state,
  202. const char *arg)
  203. {
  204. int err;
  205. /* For now assume we always want to write it */
  206. state->write_ram_buf = true;
  207. state->ram_buf_fname = arg;
  208. err = os_read_ram_buf(arg);
  209. if (err) {
  210. printf("Failed to read RAM buffer '%s': %d\n", arg, err);
  211. return err;
  212. }
  213. state->ram_buf_read = true;
  214. return 0;
  215. }
  216. SANDBOX_CMDLINE_OPT_SHORT(memory, 'm', 1,
  217. "Read/write ram_buf memory contents from file");
  218. static int sandbox_cmdline_cb_rm_memory(struct sandbox_state *state,
  219. const char *arg)
  220. {
  221. state->ram_buf_rm = true;
  222. return 0;
  223. }
  224. SANDBOX_CMDLINE_OPT(rm_memory, 0, "Remove memory file after reading");
  225. static int sandbox_cmdline_cb_state(struct sandbox_state *state,
  226. const char *arg)
  227. {
  228. state->state_fname = arg;
  229. return 0;
  230. }
  231. SANDBOX_CMDLINE_OPT_SHORT(state, 's', 1, "Specify the sandbox state FDT");
  232. static int sandbox_cmdline_cb_read(struct sandbox_state *state,
  233. const char *arg)
  234. {
  235. state->read_state = true;
  236. return 0;
  237. }
  238. SANDBOX_CMDLINE_OPT_SHORT(read, 'r', 0, "Read the state FDT on startup");
  239. static int sandbox_cmdline_cb_write(struct sandbox_state *state,
  240. const char *arg)
  241. {
  242. state->write_state = true;
  243. return 0;
  244. }
  245. SANDBOX_CMDLINE_OPT_SHORT(write, 'w', 0, "Write state FDT on exit");
  246. static int sandbox_cmdline_cb_ignore_missing(struct sandbox_state *state,
  247. const char *arg)
  248. {
  249. state->ignore_missing_state_on_read = true;
  250. return 0;
  251. }
  252. SANDBOX_CMDLINE_OPT_SHORT(ignore_missing, 'n', 0,
  253. "Ignore missing state on read");
  254. static int sandbox_cmdline_cb_show_lcd(struct sandbox_state *state,
  255. const char *arg)
  256. {
  257. state->show_lcd = true;
  258. return 0;
  259. }
  260. SANDBOX_CMDLINE_OPT_SHORT(show_lcd, 'l', 0,
  261. "Show the sandbox LCD display");
  262. static int sandbox_cmdline_cb_double_lcd(struct sandbox_state *state,
  263. const char *arg)
  264. {
  265. state->double_lcd = true;
  266. return 0;
  267. }
  268. SANDBOX_CMDLINE_OPT_SHORT(double_lcd, 'K', 0,
  269. "Double the LCD display size in each direction");
  270. static const char *term_args[STATE_TERM_COUNT] = {
  271. "raw-with-sigs",
  272. "raw",
  273. "cooked",
  274. };
  275. static int sandbox_cmdline_cb_terminal(struct sandbox_state *state,
  276. const char *arg)
  277. {
  278. int i;
  279. for (i = 0; i < STATE_TERM_COUNT; i++) {
  280. if (!strcmp(arg, term_args[i])) {
  281. state->term_raw = i;
  282. return 0;
  283. }
  284. }
  285. printf("Unknown terminal setting '%s' (", arg);
  286. for (i = 0; i < STATE_TERM_COUNT; i++)
  287. printf("%s%s", i ? ", " : "", term_args[i]);
  288. puts(")\n");
  289. return 1;
  290. }
  291. SANDBOX_CMDLINE_OPT_SHORT(terminal, 't', 1,
  292. "Set terminal to raw/cooked mode");
  293. static int sandbox_cmdline_cb_verbose(struct sandbox_state *state,
  294. const char *arg)
  295. {
  296. state->show_test_output = true;
  297. return 0;
  298. }
  299. SANDBOX_CMDLINE_OPT_SHORT(verbose, 'v', 0, "Show test output");
  300. static int sandbox_cmdline_cb_log_level(struct sandbox_state *state,
  301. const char *arg)
  302. {
  303. state->default_log_level = simple_strtol(arg, NULL, 10);
  304. return 0;
  305. }
  306. SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1,
  307. "Set log level (0=panic, 7=debug)");
  308. static int sandbox_cmdline_cb_unittests(struct sandbox_state *state,
  309. const char *arg)
  310. {
  311. state->run_unittests = true;
  312. return 0;
  313. }
  314. SANDBOX_CMDLINE_OPT_SHORT(unittests, 'u', 0, "Run unit tests");
  315. static int sandbox_cmdline_cb_select_unittests(struct sandbox_state *state,
  316. const char *arg)
  317. {
  318. state->select_unittests = arg;
  319. return 0;
  320. }
  321. SANDBOX_CMDLINE_OPT_SHORT(select_unittests, 'k', 1, "Select unit tests to run");
  322. static void setup_ram_buf(struct sandbox_state *state)
  323. {
  324. /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */
  325. if (!state->ram_buf_read)
  326. memset(state->ram_buf, '\0', state->ram_size);
  327. gd->arch.ram_buf = state->ram_buf;
  328. gd->ram_size = state->ram_size;
  329. }
  330. void state_show(struct sandbox_state *state)
  331. {
  332. char **p;
  333. printf("Arguments:\n");
  334. for (p = state->argv; *p; p++)
  335. printf("%s ", *p);
  336. printf("\n");
  337. }
  338. void sandbox_reset(void)
  339. {
  340. /* Do this here while it still has an effect */
  341. os_fd_restore();
  342. if (state_uninit())
  343. os_exit(2);
  344. if (dm_uninit())
  345. os_exit(2);
  346. /* Restart U-Boot */
  347. os_relaunch(os_argv);
  348. }
  349. int main(int argc, char *argv[])
  350. {
  351. struct sandbox_state *state;
  352. gd_t data;
  353. int ret;
  354. /*
  355. * Copy argv[] so that we can pass the arguments in the original
  356. * sequence when resetting the sandbox.
  357. */
  358. os_argv = calloc(argc + 1, sizeof(char *));
  359. if (!os_argv)
  360. os_exit(1);
  361. memcpy(os_argv, argv, sizeof(char *) * (argc + 1));
  362. memset(&data, '\0', sizeof(data));
  363. gd = &data;
  364. gd->arch.text_base = os_find_text_base();
  365. ret = state_init();
  366. if (ret)
  367. goto err;
  368. state = state_get_current();
  369. if (os_parse_args(state, argc, argv))
  370. return 1;
  371. ret = sandbox_read_state(state, state->state_fname);
  372. if (ret)
  373. goto err;
  374. ret = os_setup_signal_handlers();
  375. if (ret)
  376. goto err;
  377. #if CONFIG_VAL(SYS_MALLOC_F_LEN)
  378. gd->malloc_base = CONFIG_MALLOC_F_ADDR;
  379. #endif
  380. #if CONFIG_IS_ENABLED(LOG)
  381. gd->default_log_level = state->default_log_level;
  382. #endif
  383. setup_ram_buf(state);
  384. /*
  385. * Set up the relocation offset here, since sandbox symbols are always
  386. * relocated by the OS before sandbox is entered.
  387. */
  388. gd->reloc_off = (ulong)gd->arch.text_base;
  389. /* Do pre- and post-relocation init */
  390. board_init_f(0);
  391. board_init_r(gd->new_gd, 0);
  392. /* NOTREACHED - board_init_r() does not return */
  393. return 0;
  394. err:
  395. printf("Error %d\n", ret);
  396. return 1;
  397. }