Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
bace3d00 | 2 | /* |
6fb62078 | 3 | * Copyright (c) 2011-2012 The Chromium OS Authors. |
bace3d00 SG |
4 | */ |
5 | ||
6 | #include <common.h> | |
d41b703f | 7 | #include <cli.h> |
288b29e4 | 8 | #include <command.h> |
9c54729c | 9 | #include <efi_loader.h> |
38068820 | 10 | #include <errno.h> |
42fdcebf | 11 | #include <event.h> |
691d719d | 12 | #include <init.h> |
a4918b23 | 13 | #include <log.h> |
5c2859cd | 14 | #include <os.h> |
4209be3e | 15 | #include <sort.h> |
70db4212 | 16 | #include <asm/getopt.h> |
401d1c4f | 17 | #include <asm/global_data.h> |
4d94dfa0 | 18 | #include <asm/io.h> |
3ff6fe5f | 19 | #include <asm/malloc.h> |
70db4212 | 20 | #include <asm/sections.h> |
6fb62078 | 21 | #include <asm/state.h> |
d41b703f | 22 | #include <dm/root.h> |
4209be3e | 23 | #include <linux/ctype.h> |
bace3d00 | 24 | |
808434cd SG |
25 | DECLARE_GLOBAL_DATA_PTR; |
26 | ||
329dccc0 HS |
27 | static char **os_argv; |
28 | ||
4209be3e SG |
29 | /* Compare two options so that they can be sorted into alphabetical order */ |
30 | static int h_compare_opt(const void *p1, const void *p2) | |
31 | { | |
32 | const struct sandbox_cmdline_option *opt1 = p1; | |
33 | const struct sandbox_cmdline_option *opt2 = p2; | |
34 | const char *str1, *str2; | |
35 | char flag1[2], flag2[2]; | |
36 | ||
37 | opt1 = *(struct sandbox_cmdline_option **)p1; | |
38 | opt2 = *(struct sandbox_cmdline_option **)p2; | |
39 | flag1[1] = '\0'; | |
40 | flag2[1] = '\0'; | |
41 | ||
42 | *flag1 = opt1->flag_short < 0x100 ? opt1->flag_short : '\0'; | |
43 | *flag2 = opt2->flag_short < 0x100 ? opt2->flag_short : '\0'; | |
44 | ||
45 | str1 = *flag1 ? flag1 : opt1->flag; | |
46 | str2 = *flag2 ? flag2 : opt2->flag; | |
47 | ||
48 | /* | |
49 | * Force lower-case flags to come before upper-case ones. We only | |
50 | * support upper-case for short flags. | |
51 | */ | |
52 | if (isalpha(*str1) && isalpha(*str2) && | |
53 | tolower(*str1) == tolower(*str2)) | |
54 | return isupper(*str1) - isupper(*str2); | |
55 | ||
56 | return strcasecmp(str1, str2); | |
57 | } | |
58 | ||
70db4212 SG |
59 | int sandbox_early_getopt_check(void) |
60 | { | |
61 | struct sandbox_state *state = state_get_current(); | |
d1f81fd0 MB |
62 | struct sandbox_cmdline_option **sb_opt = |
63 | __u_boot_sandbox_option_start(); | |
70db4212 SG |
64 | size_t num_options = __u_boot_sandbox_option_count(); |
65 | size_t i; | |
66 | int max_arg_len, max_noarg_len; | |
4209be3e SG |
67 | struct sandbox_cmdline_option **sorted_opt; |
68 | int size; | |
70db4212 SG |
69 | |
70 | /* parse_err will be a string of the faulting option */ | |
71 | if (!state->parse_err) | |
72 | return 0; | |
73 | ||
74 | if (strcmp(state->parse_err, "help")) { | |
75 | printf("u-boot: error: failed while parsing option: %s\n" | |
76 | "\ttry running with --help for more information.\n", | |
77 | state->parse_err); | |
78 | os_exit(1); | |
79 | } | |
80 | ||
81 | printf( | |
82 | "u-boot, a command line test interface to U-Boot\n\n" | |
83 | "Usage: u-boot [options]\n" | |
84 | "Options:\n"); | |
85 | ||
86 | max_arg_len = 0; | |
87 | for (i = 0; i < num_options; ++i) | |
b4141195 | 88 | max_arg_len = max((int)strlen(sb_opt[i]->flag), max_arg_len); |
70db4212 SG |
89 | max_noarg_len = max_arg_len + 7; |
90 | ||
4209be3e SG |
91 | /* Sort the options */ |
92 | size = sizeof(*sorted_opt) * num_options; | |
b308d9fd | 93 | sorted_opt = os_malloc(size); |
4209be3e SG |
94 | if (!sorted_opt) { |
95 | printf("No memory to sort options\n"); | |
96 | os_exit(1); | |
97 | } | |
98 | memcpy(sorted_opt, sb_opt, size); | |
99 | qsort(sorted_opt, num_options, sizeof(*sorted_opt), h_compare_opt); | |
100 | ||
70db4212 | 101 | for (i = 0; i < num_options; ++i) { |
4209be3e | 102 | struct sandbox_cmdline_option *opt = sorted_opt[i]; |
70db4212 SG |
103 | |
104 | /* first output the short flag if it has one */ | |
105 | if (opt->flag_short >= 0x100) | |
106 | printf(" "); | |
107 | else | |
108 | printf(" -%c, ", opt->flag_short); | |
109 | ||
110 | /* then the long flag */ | |
111 | if (opt->has_arg) | |
70db4212 | 112 | printf("--%-*s <arg> ", max_arg_len, opt->flag); |
6ebcab8d SG |
113 | else |
114 | printf("--%-*s", max_noarg_len, opt->flag); | |
70db4212 SG |
115 | |
116 | /* finally the help text */ | |
117 | printf(" %s\n", opt->help); | |
118 | } | |
119 | ||
120 | os_exit(0); | |
121 | } | |
f72d0d4a | 122 | EVENT_SPY_SIMPLE(EVT_MISC_INIT_F, sandbox_early_getopt_check); |
68969778 | 123 | |
7b3efc66 | 124 | static int sandbox_cmdline_cb_help(struct sandbox_state *state, const char *arg) |
70db4212 SG |
125 | { |
126 | /* just flag to sandbox_early_getopt_check to show usage */ | |
127 | return 1; | |
128 | } | |
7b3efc66 | 129 | SANDBOX_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help"); |
70db4212 | 130 | |
d0d0746e | 131 | #ifndef CONFIG_SPL_BUILD |
ab4e07eb SG |
132 | int sandbox_main_loop_init(void) |
133 | { | |
70db4212 SG |
134 | struct sandbox_state *state = state_get_current(); |
135 | ||
136 | /* Execute command if required */ | |
ebaa832e SS |
137 | if (state->cmd || state->run_distro_boot) { |
138 | int retval = 0; | |
88539e44 | 139 | |
7dbcb76e RV |
140 | cli_init(); |
141 | ||
2b6793de | 142 | #ifdef CONFIG_CMDLINE |
ebaa832e SS |
143 | if (state->cmd) |
144 | retval = run_command_list(state->cmd, -1, 0); | |
145 | ||
146 | if (state->run_distro_boot) | |
147 | retval = cli_simple_run_command("run distro_bootcmd", | |
148 | 0); | |
2b6793de | 149 | #endif |
c5a62d4a | 150 | if (!state->interactive) |
88539e44 | 151 | os_exit(retval); |
70db4212 SG |
152 | } |
153 | ||
ab4e07eb SG |
154 | return 0; |
155 | } | |
d0d0746e | 156 | #endif |
ab4e07eb | 157 | |
ebaa832e SS |
158 | static int sandbox_cmdline_cb_boot(struct sandbox_state *state, |
159 | const char *arg) | |
160 | { | |
161 | state->run_distro_boot = true; | |
162 | return 0; | |
163 | } | |
164 | SANDBOX_CMDLINE_OPT_SHORT(boot, 'b', 0, "Run distro boot commands"); | |
165 | ||
7b3efc66 SG |
166 | static int sandbox_cmdline_cb_command(struct sandbox_state *state, |
167 | const char *arg) | |
70db4212 SG |
168 | { |
169 | state->cmd = arg; | |
170 | return 0; | |
171 | } | |
7b3efc66 | 172 | SANDBOX_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command"); |
70db4212 | 173 | |
7b3efc66 | 174 | static int sandbox_cmdline_cb_fdt(struct sandbox_state *state, const char *arg) |
f828bf25 SG |
175 | { |
176 | state->fdt_fname = arg; | |
177 | return 0; | |
178 | } | |
7b3efc66 | 179 | SANDBOX_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT"); |
f828bf25 | 180 | |
1f32ae95 SG |
181 | static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state, |
182 | const char *arg) | |
183 | { | |
184 | const char *fmt = "%s.dtb"; | |
185 | char *fname; | |
186 | int len; | |
187 | ||
188 | len = strlen(state->argv[0]) + strlen(fmt) + 1; | |
b308d9fd | 189 | fname = os_malloc(len); |
1f32ae95 SG |
190 | if (!fname) |
191 | return -ENOMEM; | |
192 | snprintf(fname, len, fmt, state->argv[0]); | |
193 | state->fdt_fname = fname; | |
194 | ||
195 | return 0; | |
196 | } | |
197 | SANDBOX_CMDLINE_OPT_SHORT(default_fdt, 'D', 0, | |
198 | "Use the default u-boot.dtb control FDT in U-Boot directory"); | |
199 | ||
189882c9 SG |
200 | static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, |
201 | const char *arg) | |
202 | { | |
73c5cb9d | 203 | char buf[256]; |
189882c9 SG |
204 | char *fname; |
205 | int len; | |
206 | ||
73c5cb9d SG |
207 | len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf, |
208 | sizeof(buf)); | |
209 | if (len < 0) | |
210 | return len; | |
211 | ||
b308d9fd | 212 | fname = os_malloc(len); |
189882c9 SG |
213 | if (!fname) |
214 | return -ENOMEM; | |
73c5cb9d | 215 | strcpy(fname, buf); |
189882c9 SG |
216 | state->fdt_fname = fname; |
217 | ||
218 | return 0; | |
219 | } | |
220 | SANDBOX_CMDLINE_OPT_SHORT(test_fdt, 'T', 0, | |
221 | "Use the test.dtb control FDT in U-Boot directory"); | |
222 | ||
c5a62d4a SG |
223 | static int sandbox_cmdline_cb_interactive(struct sandbox_state *state, |
224 | const char *arg) | |
225 | { | |
226 | state->interactive = true; | |
227 | return 0; | |
228 | } | |
229 | ||
230 | SANDBOX_CMDLINE_OPT_SHORT(interactive, 'i', 0, "Enter interactive mode"); | |
231 | ||
bda7773f SG |
232 | static int sandbox_cmdline_cb_jump(struct sandbox_state *state, |
233 | const char *arg) | |
234 | { | |
ab839dc3 SG |
235 | /* Remember to delete this U-Boot image later */ |
236 | state->jumped_fname = arg; | |
bda7773f SG |
237 | |
238 | return 0; | |
239 | } | |
240 | SANDBOX_CMDLINE_OPT_SHORT(jump, 'j', 1, "Jumped from previous U-Boot"); | |
241 | ||
b2d93c6a SG |
242 | static int sandbox_cmdline_cb_program(struct sandbox_state *state, |
243 | const char *arg) | |
244 | { | |
245 | /* | |
246 | * Record the program name to use when jumping to future phases. This | |
247 | * is the original executable which holds all the phases. We need to | |
248 | * use this instead of argv[0] since each phase is started by | |
249 | * extracting a particular binary from the full program, then running | |
250 | * it. Therefore in that binary, argv[0] contains only the | |
251 | * current-phase executable. | |
252 | * | |
253 | * For example, sandbox TPL may be started using image file: | |
254 | * | |
255 | * ./image.bin | |
256 | * | |
257 | * but then TPL needs to run VPL, which it does by extracting the VPL | |
258 | * image from the image.bin file. | |
259 | * | |
260 | * ./temp-vpl | |
261 | * | |
262 | * When VPL runs it needs access to the original image.bin so it can | |
263 | * extract the next phase (SPL). This works if we use '-f image.bin' | |
264 | * when starting the original image.bin file. | |
265 | */ | |
266 | state->prog_fname = arg; | |
267 | ||
268 | return 0; | |
269 | } | |
270 | SANDBOX_CMDLINE_OPT_SHORT(program, 'p', 1, "U-Boot program name"); | |
271 | ||
5c2859cd SG |
272 | static int sandbox_cmdline_cb_memory(struct sandbox_state *state, |
273 | const char *arg) | |
274 | { | |
275 | int err; | |
276 | ||
277 | /* For now assume we always want to write it */ | |
278 | state->write_ram_buf = true; | |
279 | state->ram_buf_fname = arg; | |
280 | ||
f80a8bbe SG |
281 | err = os_read_ram_buf(arg); |
282 | if (err) { | |
1c5a81d8 | 283 | printf("Failed to read RAM buffer '%s': %d\n", arg, err); |
5c2859cd SG |
284 | return err; |
285 | } | |
a65d1a06 | 286 | state->ram_buf_read = true; |
5c2859cd SG |
287 | |
288 | return 0; | |
289 | } | |
290 | SANDBOX_CMDLINE_OPT_SHORT(memory, 'm', 1, | |
291 | "Read/write ram_buf memory contents from file"); | |
292 | ||
ab839dc3 SG |
293 | static int sandbox_cmdline_cb_rm_memory(struct sandbox_state *state, |
294 | const char *arg) | |
295 | { | |
296 | state->ram_buf_rm = true; | |
297 | ||
298 | return 0; | |
299 | } | |
300 | SANDBOX_CMDLINE_OPT(rm_memory, 0, "Remove memory file after reading"); | |
301 | ||
1209e272 SG |
302 | static int sandbox_cmdline_cb_state(struct sandbox_state *state, |
303 | const char *arg) | |
304 | { | |
305 | state->state_fname = arg; | |
306 | return 0; | |
307 | } | |
308 | SANDBOX_CMDLINE_OPT_SHORT(state, 's', 1, "Specify the sandbox state FDT"); | |
309 | ||
310 | static int sandbox_cmdline_cb_read(struct sandbox_state *state, | |
311 | const char *arg) | |
312 | { | |
313 | state->read_state = true; | |
314 | return 0; | |
315 | } | |
316 | SANDBOX_CMDLINE_OPT_SHORT(read, 'r', 0, "Read the state FDT on startup"); | |
317 | ||
318 | static int sandbox_cmdline_cb_write(struct sandbox_state *state, | |
319 | const char *arg) | |
320 | { | |
321 | state->write_state = true; | |
322 | return 0; | |
323 | } | |
324 | SANDBOX_CMDLINE_OPT_SHORT(write, 'w', 0, "Write state FDT on exit"); | |
325 | ||
326 | static int sandbox_cmdline_cb_ignore_missing(struct sandbox_state *state, | |
327 | const char *arg) | |
328 | { | |
329 | state->ignore_missing_state_on_read = true; | |
330 | return 0; | |
331 | } | |
332 | SANDBOX_CMDLINE_OPT_SHORT(ignore_missing, 'n', 0, | |
333 | "Ignore missing state on read"); | |
334 | ||
7d95f2a3 SG |
335 | static int sandbox_cmdline_cb_show_lcd(struct sandbox_state *state, |
336 | const char *arg) | |
337 | { | |
338 | state->show_lcd = true; | |
339 | return 0; | |
340 | } | |
341 | SANDBOX_CMDLINE_OPT_SHORT(show_lcd, 'l', 0, | |
342 | "Show the sandbox LCD display"); | |
343 | ||
6be88c72 SG |
344 | static int sandbox_cmdline_cb_double_lcd(struct sandbox_state *state, |
345 | const char *arg) | |
346 | { | |
347 | state->double_lcd = true; | |
348 | ||
349 | return 0; | |
350 | } | |
351 | SANDBOX_CMDLINE_OPT_SHORT(double_lcd, 'K', 0, | |
352 | "Double the LCD display size in each direction"); | |
353 | ||
ffb87905 SG |
354 | static const char *term_args[STATE_TERM_COUNT] = { |
355 | "raw-with-sigs", | |
356 | "raw", | |
357 | "cooked", | |
358 | }; | |
359 | ||
360 | static int sandbox_cmdline_cb_terminal(struct sandbox_state *state, | |
361 | const char *arg) | |
362 | { | |
363 | int i; | |
364 | ||
365 | for (i = 0; i < STATE_TERM_COUNT; i++) { | |
366 | if (!strcmp(arg, term_args[i])) { | |
367 | state->term_raw = i; | |
368 | return 0; | |
369 | } | |
370 | } | |
371 | ||
372 | printf("Unknown terminal setting '%s' (", arg); | |
373 | for (i = 0; i < STATE_TERM_COUNT; i++) | |
374 | printf("%s%s", i ? ", " : "", term_args[i]); | |
375 | puts(")\n"); | |
376 | ||
377 | return 1; | |
378 | } | |
379 | SANDBOX_CMDLINE_OPT_SHORT(terminal, 't', 1, | |
380 | "Set terminal to raw/cooked mode"); | |
381 | ||
9ce8b402 SG |
382 | static int sandbox_cmdline_cb_verbose(struct sandbox_state *state, |
383 | const char *arg) | |
384 | { | |
385 | state->show_test_output = true; | |
386 | return 0; | |
387 | } | |
388 | SANDBOX_CMDLINE_OPT_SHORT(verbose, 'v', 0, "Show test output"); | |
389 | ||
2b1dc29a SG |
390 | static int sandbox_cmdline_cb_log_level(struct sandbox_state *state, |
391 | const char *arg) | |
392 | { | |
393 | state->default_log_level = simple_strtol(arg, NULL, 10); | |
394 | ||
395 | return 0; | |
396 | } | |
397 | SANDBOX_CMDLINE_OPT_SHORT(log_level, 'L', 1, | |
398 | "Set log level (0=panic, 7=debug)"); | |
399 | ||
b25ff5cb SG |
400 | static int sandbox_cmdline_cb_unittests(struct sandbox_state *state, |
401 | const char *arg) | |
402 | { | |
403 | state->run_unittests = true; | |
404 | ||
405 | return 0; | |
406 | } | |
407 | SANDBOX_CMDLINE_OPT_SHORT(unittests, 'u', 0, "Run unit tests"); | |
408 | ||
22b29cc8 SG |
409 | static int sandbox_cmdline_cb_select_unittests(struct sandbox_state *state, |
410 | const char *arg) | |
411 | { | |
412 | state->select_unittests = arg; | |
413 | ||
414 | return 0; | |
415 | } | |
416 | SANDBOX_CMDLINE_OPT_SHORT(select_unittests, 'k', 1, "Select unit tests to run"); | |
417 | ||
85f718f6 SG |
418 | static int sandbox_cmdline_cb_signals(struct sandbox_state *state, |
419 | const char *arg) | |
420 | { | |
421 | state->handle_signals = true; | |
422 | ||
423 | return 0; | |
424 | } | |
425 | SANDBOX_CMDLINE_OPT_SHORT(signals, 'S', 0, | |
426 | "Handle signals (such as SIGSEGV) in sandbox"); | |
427 | ||
cb897009 SG |
428 | static int sandbox_cmdline_cb_autoboot_keyed(struct sandbox_state *state, |
429 | const char *arg) | |
430 | { | |
431 | state->autoboot_keyed = true; | |
432 | ||
433 | return 0; | |
434 | } | |
435 | SANDBOX_CMDLINE_OPT(autoboot_keyed, 0, "Allow keyed autoboot"); | |
436 | ||
bb967240 SG |
437 | static void setup_ram_buf(struct sandbox_state *state) |
438 | { | |
a65d1a06 | 439 | /* Zero the RAM buffer if we didn't read it, to keep valgrind happy */ |
5dbe794d | 440 | if (!state->ram_buf_read) |
a65d1a06 | 441 | memset(state->ram_buf, '\0', state->ram_size); |
a65d1a06 | 442 | |
bb967240 SG |
443 | gd->arch.ram_buf = state->ram_buf; |
444 | gd->ram_size = state->ram_size; | |
445 | } | |
446 | ||
d66ddafa SG |
447 | void state_show(struct sandbox_state *state) |
448 | { | |
449 | char **p; | |
450 | ||
451 | printf("Arguments:\n"); | |
452 | for (p = state->argv; *p; p++) | |
453 | printf("%s ", *p); | |
454 | printf("\n"); | |
455 | } | |
456 | ||
9c54729c HS |
457 | void __efi_runtime EFIAPI efi_reset_system( |
458 | enum efi_reset_type reset_type, | |
459 | efi_status_t reset_status, | |
460 | unsigned long data_size, void *reset_data) | |
461 | { | |
7a001e0f HS |
462 | if (reset_type == EFI_RESET_SHUTDOWN) |
463 | sandbox_exit(); | |
464 | else | |
465 | sandbox_reset(); | |
9c54729c HS |
466 | } |
467 | ||
329dccc0 HS |
468 | void sandbox_reset(void) |
469 | { | |
470 | /* Do this here while it still has an effect */ | |
471 | os_fd_restore(); | |
472 | if (state_uninit()) | |
473 | os_exit(2); | |
474 | ||
329dccc0 HS |
475 | /* Restart U-Boot */ |
476 | os_relaunch(os_argv); | |
477 | } | |
478 | ||
001c39a1 | 479 | int sandbox_main(int argc, char *argv[]) |
bace3d00 | 480 | { |
70db4212 | 481 | struct sandbox_state *state; |
205b9f51 | 482 | void * text_base; |
4d94dfa0 | 483 | gd_t data; |
b308d9fd | 484 | int size; |
1209e272 | 485 | int ret; |
6fb62078 | 486 | |
205b9f51 HS |
487 | text_base = os_find_text_base(); |
488 | ||
3beba4ad HS |
489 | /* |
490 | * This must be the first invocation of os_malloc() to have | |
491 | * state->ram_buf in the low 4 GiB. | |
492 | */ | |
493 | ret = state_init(); | |
494 | if (ret) | |
495 | goto err; | |
496 | ||
329dccc0 HS |
497 | /* |
498 | * Copy argv[] so that we can pass the arguments in the original | |
499 | * sequence when resetting the sandbox. | |
500 | */ | |
b308d9fd SG |
501 | size = sizeof(char *) * (argc + 1); |
502 | os_argv = os_malloc(size); | |
329dccc0 HS |
503 | if (!os_argv) |
504 | os_exit(1); | |
b308d9fd | 505 | memcpy(os_argv, argv, size); |
329dccc0 | 506 | |
001d1885 SG |
507 | memset(&data, '\0', sizeof(data)); |
508 | gd = &data; | |
205b9f51 | 509 | gd->arch.text_base = text_base; |
001d1885 | 510 | |
70db4212 SG |
511 | state = state_get_current(); |
512 | if (os_parse_args(state, argc, argv)) | |
513 | return 1; | |
514 | ||
10bb90fa PD |
515 | /* Remove old memory file if required */ |
516 | if (state->ram_buf_rm && state->ram_buf_fname) { | |
517 | os_unlink(state->ram_buf_fname); | |
518 | state->write_ram_buf = false; | |
519 | state->ram_buf_fname = NULL; | |
520 | } | |
521 | ||
1209e272 SG |
522 | ret = sandbox_read_state(state, state->state_fname); |
523 | if (ret) | |
524 | goto err; | |
525 | ||
85f718f6 SG |
526 | if (state->handle_signals) { |
527 | ret = os_setup_signal_handlers(); | |
528 | if (ret) | |
529 | goto err; | |
530 | } | |
b46f30a3 | 531 | |
1fc50d72 | 532 | #if CONFIG_VAL(SYS_MALLOC_F_LEN) |
dd5b58c4 | 533 | gd->malloc_base = CFG_MALLOC_F_ADDR; |
2b1dc29a SG |
534 | #endif |
535 | #if CONFIG_IS_ENABLED(LOG) | |
536 | gd->default_log_level = state->default_log_level; | |
29afe9e6 | 537 | #endif |
bb967240 | 538 | setup_ram_buf(state); |
4d94dfa0 | 539 | |
001d1885 SG |
540 | /* |
541 | * Set up the relocation offset here, since sandbox symbols are always | |
542 | * relocated by the OS before sandbox is entered. | |
543 | */ | |
544 | gd->reloc_off = (ulong)gd->arch.text_base; | |
545 | ||
a4918b23 | 546 | /* sandbox test: log functions called before log_init in board_init_f */ |
a4918b23 PD |
547 | log_debug("debug: %s\n", __func__); |
548 | ||
808434cd | 549 | /* Do pre- and post-relocation init */ |
bace3d00 | 550 | board_init_f(0); |
8ec21bbe | 551 | |
808434cd SG |
552 | board_init_r(gd->new_gd, 0); |
553 | ||
554 | /* NOTREACHED - board_init_r() does not return */ | |
8ec21bbe | 555 | return 0; |
1209e272 SG |
556 | |
557 | err: | |
558 | printf("Error %d\n", ret); | |
559 | return 1; | |
bace3d00 | 560 | } |