start.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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 int sandbox_cmdline_cb_autoboot_keyed(struct sandbox_state *state,
  335. const char *arg)
  336. {
  337. state->autoboot_keyed = true;
  338. return 0;
  339. }
  340. SANDBOX_CMDLINE_OPT(autoboot_keyed, 0, "Allow keyed autoboot");
  341. static void setup_ram_buf(struct sandbox_state *state)
  342. {
  343. /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */
  344. if (!state->ram_buf_read)
  345. memset(state->ram_buf, '\0', state->ram_size);
  346. gd->arch.ram_buf = state->ram_buf;
  347. gd->ram_size = state->ram_size;
  348. }
  349. void state_show(struct sandbox_state *state)
  350. {
  351. char **p;
  352. printf("Arguments:\n");
  353. for (p = state->argv; *p; p++)
  354. printf("%s ", *p);
  355. printf("\n");
  356. }
  357. void __efi_runtime EFIAPI efi_reset_system(
  358. enum efi_reset_type reset_type,
  359. efi_status_t reset_status,
  360. unsigned long data_size, void *reset_data)
  361. {
  362. os_fd_restore();
  363. os_relaunch(os_argv);
  364. }
  365. void sandbox_reset(void)
  366. {
  367. /* Do this here while it still has an effect */
  368. os_fd_restore();
  369. if (state_uninit())
  370. os_exit(2);
  371. /* Restart U-Boot */
  372. os_relaunch(os_argv);
  373. }
  374. int main(int argc, char *argv[])
  375. {
  376. struct sandbox_state *state;
  377. void * text_base;
  378. gd_t data;
  379. int size;
  380. int ret;
  381. text_base = os_find_text_base();
  382. /*
  383. * This must be the first invocation of os_malloc() to have
  384. * state->ram_buf in the low 4 GiB.
  385. */
  386. ret = state_init();
  387. if (ret)
  388. goto err;
  389. /*
  390. * Copy argv[] so that we can pass the arguments in the original
  391. * sequence when resetting the sandbox.
  392. */
  393. size = sizeof(char *) * (argc + 1);
  394. os_argv = os_malloc(size);
  395. if (!os_argv)
  396. os_exit(1);
  397. memcpy(os_argv, argv, size);
  398. memset(&data, '\0', sizeof(data));
  399. gd = &data;
  400. gd->arch.text_base = text_base;
  401. state = state_get_current();
  402. if (os_parse_args(state, argc, argv))
  403. return 1;
  404. /* Remove old memory file if required */
  405. if (state->ram_buf_rm && state->ram_buf_fname) {
  406. os_unlink(state->ram_buf_fname);
  407. state->write_ram_buf = false;
  408. state->ram_buf_fname = NULL;
  409. }
  410. ret = sandbox_read_state(state, state->state_fname);
  411. if (ret)
  412. goto err;
  413. if (state->handle_signals) {
  414. ret = os_setup_signal_handlers();
  415. if (ret)
  416. goto err;
  417. }
  418. #if CONFIG_VAL(SYS_MALLOC_F_LEN)
  419. gd->malloc_base = CONFIG_MALLOC_F_ADDR;
  420. #endif
  421. #if CONFIG_IS_ENABLED(LOG)
  422. gd->default_log_level = state->default_log_level;
  423. #endif
  424. setup_ram_buf(state);
  425. /*
  426. * Set up the relocation offset here, since sandbox symbols are always
  427. * relocated by the OS before sandbox is entered.
  428. */
  429. gd->reloc_off = (ulong)gd->arch.text_base;
  430. /* sandbox test: log functions called before log_init in board_init_f */
  431. log_debug("debug: %s\n", __func__);
  432. /* Do pre- and post-relocation init */
  433. board_init_f(0);
  434. board_init_r(gd->new_gd, 0);
  435. /* NOTREACHED - board_init_r() does not return */
  436. return 0;
  437. err:
  438. printf("Error %d\n", ret);
  439. return 1;
  440. }