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