start.c 10 KB

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