start.c 12 KB

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