From e101247212f3aba3ece22c66e46e3fca89c0c768 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 10 Jan 2012 15:54:05 -0800 Subject: sandbox: sort header files in os.c Tidy this up as the list is long and likely to get longer. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/os.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch') diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 6d55b5cbce..a1d324b51f 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -19,15 +19,15 @@ * MA 02111-1307 USA */ +#include #include #include #include -#include #include -#include -#include -#include +#include #include +#include +#include #include #include -- cgit v1.2.3 From 3bdf56b78668769c091a74b40059a2ff14c5b80c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 10 Jan 2012 15:54:06 -0800 Subject: sandbox: add required header to os.c We should include the sys/time.h header to avoid warnings. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/os.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch') diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index a1d324b51f..093e7dc7ad 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3 From e2dcefcb404df39fc38786f4b76e3b94d4f476e1 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Tue, 25 Oct 2011 13:02:58 +0200 Subject: sandbox: add lseek helper Follow up patches want to be able to seek fd's. Acked-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/os.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch') diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 093e7dc7ad..f6d0e8457d 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -45,6 +45,19 @@ ssize_t os_write(int fd, const void *buf, size_t count) return write(fd, buf, count); } +off_t os_lseek(int fd, off_t offset, int whence) +{ + if (whence == OS_SEEK_SET) + whence = SEEK_SET; + else if (whence == OS_SEEK_CUR) + whence = SEEK_CUR; + else if (whence == OS_SEEK_END) + whence = SEEK_END; + else + os_exit(1); + return lseek(fd, offset, whence); +} + int os_open(const char *pathname, int flags) { return open(pathname, flags); -- cgit v1.2.3 From f7b2af0a228645f972cc882534b68d32c739f5e9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 15 Feb 2012 15:51:11 -0800 Subject: sandbox: fdt: add support for CONFIG_OF_CONTROL This adds support for a controlling fdt, mirroring the ARM implementation. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/include/asm/global_data.h | 1 + arch/sandbox/lib/board.c | 8 ++++++++ 2 files changed, 9 insertions(+) (limited to 'arch') diff --git a/arch/sandbox/include/asm/global_data.h b/arch/sandbox/include/asm/global_data.h index 8d47191f92..01a706362e 100644 --- a/arch/sandbox/include/asm/global_data.h +++ b/arch/sandbox/include/asm/global_data.h @@ -45,6 +45,7 @@ typedef struct global_data { unsigned long fb_base; /* base address of frame buffer */ u8 *ram_buf; /* emulated RAM buffer */ phys_size_t ram_size; /* RAM size */ + const void *fdt_blob; /* Our device tree, NULL if none */ void **jt; /* jump table */ char env_buf[32]; /* buffer for getenv() before reloc. */ } gd_t; diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index b7997e9a73..6d464d6ae8 100644 --- a/arch/sandbox/lib/board.c +++ b/arch/sandbox/lib/board.c @@ -156,6 +156,14 @@ void board_init_f(ulong bootflag) memset((void *)gd, 0, sizeof(gd_t)); +#if defined(CONFIG_OF_EMBED) + /* Get a pointer to the FDT */ + gd->fdt_blob = _binary_dt_dtb_start; +#elif defined(CONFIG_OF_SEPARATE) + /* FDT is at end of image */ + gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE); +#endif + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { if ((*init_fnc_ptr)() != 0) hang(); -- cgit v1.2.3 From d9165153caea9f342410ed3ac87cb68768ebec78 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 20 Feb 2012 23:56:58 -0500 Subject: sandbox: add flags for open() call This provides a way for callers to create files for writing. The flags are translated at runtime, for the ones we support. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/os.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'arch') diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index f6d0e8457d..cb469e0510 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -58,9 +58,29 @@ off_t os_lseek(int fd, off_t offset, int whence) return lseek(fd, offset, whence); } -int os_open(const char *pathname, int flags) +int os_open(const char *pathname, int os_flags) { - return open(pathname, flags); + int flags; + + switch (os_flags & OS_O_MASK) { + case OS_O_RDONLY: + default: + flags = O_RDONLY; + break; + + case OS_O_WRONLY: + flags = O_WRONLY; + break; + + case OS_O_RDWR: + flags = O_RDWR; + break; + } + + if (os_flags & OS_O_CREAT) + flags |= O_CREAT; + + return open(pathname, flags, 0777); } int os_close(int fd) -- cgit v1.2.3 From 8d30fcd9a15da1fbe803af6d584ef0c4997e47e0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 15 Feb 2012 15:51:13 -0800 Subject: sandbox: gpio: add basic driver for simulating GPIOs This provides a way of simulating GPIOs by setting values which are seen by the normal gpio_get/set_value() calls. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/include/asm/gpio.h | 81 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 arch/sandbox/include/asm/gpio.h (limited to 'arch') diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h new file mode 100644 index 0000000000..0500c539b3 --- /dev/null +++ b/arch/sandbox/include/asm/gpio.h @@ -0,0 +1,81 @@ +/* + * This is the interface to the sandbox GPIO driver for test code which + * wants to change the GPIO values reported to U-Boot. + * + * Copyright (c) 2011 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __ASM_SANDBOX_GPIO_H +#define __ASM_SANDBOX_GPIO_H + +/* + * We use the generic interface, and add a back-channel. + * + * The back-channel functions are declared in this file. They should not be used + * except in test code. + * + * Test code can, for example, call sandbox_gpio_set_value() to set the value of + * a simulated GPIO. From then on, normal code in U-Boot will see this new + * value when it calls gpio_get_value(). + * + * NOTE: DO NOT use the functions in this file except in test code! + */ +#include + +/** + * Return the simulated value of a GPIO (used only in sandbox test code) + * + * @param gp GPIO number + * @return -1 on error, 0 if GPIO is low, >0 if high + */ +int sandbox_gpio_get_value(unsigned gp); + +/** + * Set the simulated value of a GPIO (used only in sandbox test code) + * + * @param gp GPIO number + * @param value value to set (0 for low, non-zero for high) + * @return -1 on error, 0 if ok + */ +int sandbox_gpio_set_value(unsigned gp, int value); + +/** + * Return the simulated direction of a GPIO (used only in sandbox test code) + * + * @param gp GPIO number + * @return -1 on error, 0 if GPIO is input, >0 if output + */ +int sandbox_gpio_get_direction(unsigned gp); + +/** + * Set the simulated direction of a GPIO (used only in sandbox test code) + * + * @param gp GPIO number + * @param output 0 to set as input, 1 to set as output + * @return -1 on error, 0 if ok + */ +int sandbox_gpio_set_direction(unsigned gp, int output); + +/* Display information about each GPIO */ +void gpio_info(void); + +#define gpio_status() gpio_info() + +#endif -- cgit v1.2.3 From 3ab7d95aa0b57c5976e1cbb1cd80ec1a24ffa78a Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 26 Feb 2012 14:13:31 -0500 Subject: sandbox: u-boot.lds: tweak style We use tabs for indentation, not spaces. Acked-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/u-boot.lds | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'arch') diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index 2d2e50fdbf..0c56aa7793 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2011-2012 The Chromium OS Authors. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -24,11 +24,11 @@ SECTIONS { - __u_boot_cmd_start = .; - .u_boot_cmd : { *(.u_boot_cmd) } - __u_boot_cmd_end = .; - __bss_start = .; + __u_boot_cmd_start = .; + _u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + __bss_start = .; } INSERT BEFORE .data; -- cgit v1.2.3 From 20186a1cbff3fd87954627538ce712a162c22351 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sun, 26 Feb 2012 16:00:26 -0500 Subject: sandbox: disable fortification Since we provide all our own library calls, the fortification from glibc just gets in our way (which some distros enable by default). Acked-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/config.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/sandbox/config.mk b/arch/sandbox/config.mk index 2ec1bb772b..02ce4a4410 100644 --- a/arch/sandbox/config.mk +++ b/arch/sandbox/config.mk @@ -17,5 +17,5 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA -PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ +PLATFORM_CPPFLAGS += -DCONFIG_SANDBOX -D__SANDBOX__ -U_FORTIFY_SOURCE PLATFORM_LIBS += -lrt -- cgit v1.2.3 From 6fb62078210b78ff5cc87829a62166feebb8e9dc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 15 Feb 2012 15:51:15 -0800 Subject: sandbox: add concept of sandbox state The state exists through the life of U-Boot. It can be adjusted by command line options and perhaps later through a config file. It is available to U-Boot through state_...() calls (within sandbox code). The primary purpose of this is to contain the "hardware" state. It should only be used by sandbox internal code. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/Makefile | 2 +- arch/sandbox/cpu/start.c | 9 ++++++- arch/sandbox/cpu/state.c | 51 +++++++++++++++++++++++++++++++++++ arch/sandbox/include/asm/state.h | 57 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 arch/sandbox/cpu/state.c create mode 100644 arch/sandbox/include/asm/state.h (limited to 'arch') diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 2ae0f7155c..6fd09ff65b 100644 --- a/arch/sandbox/cpu/Makefile +++ b/arch/sandbox/cpu/Makefile @@ -27,7 +27,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o -COBJS := cpu.o start.o os.o +COBJS := cpu.o os.o start.o state.o SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index a429e296ec..2b66eeddbb 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The Chromium OS Authors. + * Copyright (c) 2011-2012 The Chromium OS Authors. * See file CREDITS for list of people who contributed to this * project. * @@ -20,9 +20,16 @@ */ #include +#include int main(int argc, char *argv[]) { + int err; + + err = state_init(); + if (err) + return err; + /* * Do pre- and post-relocation init, then start up U-Boot. This will * never return. diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c new file mode 100644 index 0000000000..88ae2b0820 --- /dev/null +++ b/arch/sandbox/cpu/state.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +/* Main state record for the sandbox */ +static struct sandbox_state main_state; +static struct sandbox_state *state; /* Pointer to current state record */ + +void state_record_exit(enum exit_type_id exit_type) +{ + state->exit_type = exit_type; +} + +struct sandbox_state *state_get_current(void) +{ + assert(state); + return state; +} + +int state_init(void) +{ + state = &main_state; + + /* + * Example of how to use GPIOs: + * + * sandbox_gpio_set_direction(170, 0); + * sandbox_gpio_set_value(170, 0); + */ + return 0; +} diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h new file mode 100644 index 0000000000..5b34e9448e --- /dev/null +++ b/arch/sandbox/include/asm/state.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2012 The Chromium OS Authors. + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __SANDBOX_STATE_H +#define __SANDBOX_STATE_H + +/* How we exited U-Boot */ +enum exit_type_id { + STATE_EXIT_NORMAL, + STATE_EXIT_COLD_REBOOT, + STATE_EXIT_POWER_OFF, +}; + +/* The complete state of the test system */ +struct sandbox_state { + const char *cmd; /* Command to execute */ + enum exit_type_id exit_type; /* How we exited U-Boot */ +}; + +/** + * Record the exit type to be reported by the test program. + * + * @param exit_type Exit type to record + */ +void state_record_exit(enum exit_type_id exit_type); + +/** + * Gets a pointer to the current state. + * + * @return pointer to state + */ +struct sandbox_state *state_get_current(void); + +/** + * Initialize the test system state + */ +int state_init(void); + +#endif -- cgit v1.2.3 From ab4e07eb71ca1913e5291316565c9d073987de85 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 26 Feb 2012 17:38:50 -0500 Subject: sandbox: allow processing before main loop In order to pass command line arguments to sandbox we need to be able to act on them. So take control back at the end of board_init_r() from where we can call the main loop or do something else. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/start.c | 5 +++++ arch/sandbox/include/asm/u-boot-sandbox.h | 3 +++ arch/sandbox/lib/board.c | 2 ++ 3 files changed, 10 insertions(+) (limited to 'arch') diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2b66eeddbb..4a84486c1e 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,6 +22,11 @@ #include #include +int sandbox_main_loop_init(void) +{ + return 0; +} + int main(int argc, char *argv[]) { int err; diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h index 236b4ee287..99e950b805 100644 --- a/arch/sandbox/include/asm/u-boot-sandbox.h +++ b/arch/sandbox/include/asm/u-boot-sandbox.h @@ -35,4 +35,7 @@ int board_init(void); int dram_init(void); +/* start.c */ +int sandbox_main_loop_init(void); + #endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 6d464d6ae8..25a8d02fd7 100644 --- a/arch/sandbox/lib/board.c +++ b/arch/sandbox/lib/board.c @@ -269,6 +269,8 @@ void board_init_r(gd_t *id, ulong dest_addr) post_run(NULL, POST_RAM | post_bootmode_get(0)); #endif + sandbox_main_loop_init(); + /* * For now, run the main loop. Later we might let this be done * in the main program. -- cgit v1.2.3 From 70db4212fcdb080444a23dccaf673b68a3ffc1fa Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 15 Feb 2012 15:51:16 -0800 Subject: sandbox: add getopt support This adds simple command-line parsing to sandbox. The idea is that it sets up the state with options provided, and this state can then be queried later, as needed. New flags are declared with the SB_CMDLINE_OPT_SHORT helper macro, pointers are automatically gathered up in a special section, and then the core code takes care of gathering them up and processing at runtime. This way there is no central place where we have to store a list of flags with ifdefs. Signed-off-by: Simon Glass Signed-off-by: Mike Frysinger --- arch/sandbox/cpu/os.c | 98 +++++++++++++++++++++++++++++++ arch/sandbox/cpu/start.c | 88 +++++++++++++++++++++++++++ arch/sandbox/cpu/u-boot.lds | 4 ++ arch/sandbox/include/asm/getopt.h | 71 ++++++++++++++++++++++ arch/sandbox/include/asm/sections.h | 22 +++++++ arch/sandbox/include/asm/state.h | 5 ++ arch/sandbox/include/asm/u-boot-sandbox.h | 1 + arch/sandbox/lib/board.c | 1 + 8 files changed, 290 insertions(+) create mode 100644 arch/sandbox/include/asm/getopt.h create mode 100644 arch/sandbox/include/asm/sections.h (limited to 'arch') diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index cb469e0510..36637af6ce 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,9 @@ #include #include +#include +#include +#include #include /* Operating System Interface */ @@ -155,3 +159,97 @@ u64 os_get_nsec(void) return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; #endif } + +static char *short_opts; +static struct option *long_opts; + +int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) +{ + struct sb_cmdline_option **sb_opt = __u_boot_sandbox_option_start; + size_t num_options = __u_boot_sandbox_option_count(); + size_t i; + + int hidden_short_opt; + size_t si; + + int c; + + if (short_opts || long_opts) + return 1; + + state->argc = argc; + state->argv = argv; + + /* dynamically construct the arguments to the system getopt_long */ + short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1); + long_opts = os_malloc(sizeof(*long_opts) * num_options); + if (!short_opts || !long_opts) + return 1; + + /* + * getopt_long requires "val" to be unique (since that is what the + * func returns), so generate unique values automatically for flags + * that don't have a short option. pick 0x100 as that is above the + * single byte range (where ASCII/ISO-XXXX-X charsets live). + */ + hidden_short_opt = 0x100; + si = 0; + for (i = 0; i < num_options; ++i) { + long_opts[i].name = sb_opt[i]->flag; + long_opts[i].has_arg = sb_opt[i]->has_arg ? + required_argument : no_argument; + long_opts[i].flag = NULL; + + if (sb_opt[i]->flag_short) { + short_opts[si++] = long_opts[i].val = sb_opt[i]->flag_short; + if (long_opts[i].has_arg == required_argument) + short_opts[si++] = ':'; + } else + long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++; + } + short_opts[si] = '\0'; + + /* we need to handle output ourselves since u-boot provides printf */ + opterr = 0; + + /* + * walk all of the options the user gave us on the command line, + * figure out what u-boot option structure they belong to (via + * the unique short val key), and call the appropriate callback. + */ + while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { + for (i = 0; i < num_options; ++i) { + if (sb_opt[i]->flag_short == c) { + if (sb_opt[i]->callback(state, optarg)) { + state->parse_err = sb_opt[i]->flag; + return 0; + } + break; + } + } + if (i == num_options) { + /* + * store the faulting flag for later display. we have to + * store the flag itself as the getopt parsing itself is + * tricky: need to handle the following flags (assume all + * of the below are unknown): + * -a optopt='a' optind= + * -abbbb optopt='a' optind= + * -aaaaa optopt='a' optind= + * --a optopt=0 optind= + * as you can see, it is impossible to determine the exact + * faulting flag without doing the parsing ourselves, so + * we just report the specific flag that failed. + */ + if (optopt) { + static char parse_err[3] = { '-', 0, '\0', }; + parse_err[1] = optopt; + state->parse_err = parse_err; + } else + state->parse_err = argv[optind - 1]; + break; + } + } + + return 0; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 4a84486c1e..6c3e8eb379 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -20,21 +20,109 @@ */ #include +#include +#include #include +#include + +int sandbox_early_getopt_check(void) +{ + struct sandbox_state *state = state_get_current(); + struct sb_cmdline_option **sb_opt = __u_boot_sandbox_option_start; + size_t num_options = __u_boot_sandbox_option_count(); + size_t i; + int max_arg_len, max_noarg_len; + + /* parse_err will be a string of the faulting option */ + if (!state->parse_err) + return 0; + + if (strcmp(state->parse_err, "help")) { + printf("u-boot: error: failed while parsing option: %s\n" + "\ttry running with --help for more information.\n", + state->parse_err); + os_exit(1); + } + + printf( + "u-boot, a command line test interface to U-Boot\n\n" + "Usage: u-boot [options]\n" + "Options:\n"); + + max_arg_len = 0; + for (i = 0; i < num_options; ++i) + max_arg_len = max(strlen(sb_opt[i]->flag), max_arg_len); + max_noarg_len = max_arg_len + 7; + + for (i = 0; i < num_options; ++i) { + struct sb_cmdline_option *opt = sb_opt[i]; + + /* first output the short flag if it has one */ + if (opt->flag_short >= 0x100) + printf(" "); + else + printf(" -%c, ", opt->flag_short); + + /* then the long flag */ + if (opt->has_arg) + printf("--%-*s", max_noarg_len, opt->flag); + else + printf("--%-*s ", max_arg_len, opt->flag); + + /* finally the help text */ + printf(" %s\n", opt->help); + } + + os_exit(0); +} + +static int sb_cmdline_cb_help(struct sandbox_state *state, const char *arg) +{ + /* just flag to sandbox_early_getopt_check to show usage */ + return 1; +} +SB_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help"); + int sandbox_main_loop_init(void) { + struct sandbox_state *state = state_get_current(); + + /* Execute command if required */ + if (state->cmd) { + /* TODO: redo this when cmd tidy-up series lands */ +#ifdef CONFIG_SYS_HUSH_PARSER + run_command(state->cmd, 0); +#else + parse_string_outer(state->cmd, FLAG_PARSE_SEMICOLON | + FLAG_EXIT_FROM_LOOP); +#endif + os_exit(state->exit_type); + } + return 0; } +static int sb_cmdline_cb_command(struct sandbox_state *state, const char *arg) +{ + state->cmd = arg; + return 0; +} +SB_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command"); + int main(int argc, char *argv[]) { + struct sandbox_state *state; int err; err = state_init(); if (err) return err; + state = state_get_current(); + if (os_parse_args(state, argc, argv)) + return 1; + /* * Do pre- and post-relocation init, then start up U-Boot. This will * never return. diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index 0c56aa7793..99601387cb 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -28,6 +28,10 @@ SECTIONS _u_boot_cmd : { *(.u_boot_cmd) } __u_boot_cmd_end = .; + __u_boot_sandbox_option_start = .; + _u_boot_sandbox_getopt : { *(.u_boot_sandbox_getopt) } + __u_boot_sandbox_option_end = .; + __bss_start = .; } diff --git a/arch/sandbox/include/asm/getopt.h b/arch/sandbox/include/asm/getopt.h new file mode 100644 index 0000000000..685883cd3f --- /dev/null +++ b/arch/sandbox/include/asm/getopt.h @@ -0,0 +1,71 @@ +/* + * Code for setting up command line flags like `./u-boot --help` + * + * Copyright (c) 2011 The Chromium OS Authors. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __SANDBOX_GETOPT_H +#define __SANDBOX_GETOPT_H + +struct sandbox_state; + +/* + * Internal structure for storing details about the flag. + * Most people should not have to dig around in this as + * it only gets parsed by the core sandbox code. End + * consumer code should focus on the macros below and + * the callback function. + */ +struct sb_cmdline_option { + /* The long flag name: "help" for "--help" */ + const char *flag; + /* The (optional) short flag name: "h" for "-h" */ + int flag_short; + /* The help string shown to the user when processing --help */ + const char *help; + /* Whether this flag takes an argument */ + int has_arg; + /* Callback into the end consumer code with the option */ + int (*callback)(struct sandbox_state *state, const char *opt); +}; + +/* + * Internal macro to expand the lower macros into the necessary + * magic junk that makes this all work. + */ +#define _SB_CMDLINE_OPT(f, s, ha, h) \ + static struct sb_cmdline_option sb_cmdline_option_##f = { \ + .flag = #f, \ + .flag_short = s, \ + .help = h, \ + .has_arg = ha, \ + .callback = sb_cmdline_cb_##f, \ + }; \ + /* Ppointer to the struct in a special section for the linker script */ \ + static __attribute__((section(".u_boot_sandbox_getopt"), used)) \ + struct sb_cmdline_option *sb_cmdline_option_##f##_ptr = \ + &sb_cmdline_option_##f + +/** + * Macros for end code to declare new command line flags. + * + * @param f The long flag name e.g. help + * @param ha Does the flag have an argument e.g. 0/1 + * @param h The help string displayed when showing --help + * + * This invocation: + * SB_CMDLINE_OPT(foo, 0, "The foo arg"); + * Will create a new flag named "--foo" (no short option) that takes + * no argument. If the user specifies "--foo", then the callback func + * sb_cmdline_cb_foo() will automatically be called. + */ +#define SB_CMDLINE_OPT(f, ha, h) _SB_CMDLINE_OPT(f, 0, ha, h) +/* + * Same as above, but @s is used to specify a short flag e.g. + * SB_CMDLINE_OPT(foo, 'f', 0, "The foo arg"); + */ +#define SB_CMDLINE_OPT_SHORT(f, s, ha, h) _SB_CMDLINE_OPT(f, s, ha, h) + +#endif diff --git a/arch/sandbox/include/asm/sections.h b/arch/sandbox/include/asm/sections.h new file mode 100644 index 0000000000..eafce7d8ab --- /dev/null +++ b/arch/sandbox/include/asm/sections.h @@ -0,0 +1,22 @@ +/* + * decls for symbols defined in the linker script + * + * Copyright (c) 2012 The Chromium OS Authors. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __SANDBOX_SECTIONS_H +#define __SANDBOX_SECTIONS_H + +struct sb_cmdline_option; + +extern struct sb_cmdline_option *__u_boot_sandbox_option_start[], + *__u_boot_sandbox_option_end[]; + +static inline size_t __u_boot_sandbox_option_count(void) +{ + return __u_boot_sandbox_option_end - __u_boot_sandbox_option_start; +} + +#endif diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 5b34e9448e..2b62b46ea2 100644 --- a/arch/sandbox/include/asm/state.h +++ b/arch/sandbox/include/asm/state.h @@ -22,6 +22,8 @@ #ifndef __SANDBOX_STATE_H #define __SANDBOX_STATE_H +#include + /* How we exited U-Boot */ enum exit_type_id { STATE_EXIT_NORMAL, @@ -33,6 +35,9 @@ enum exit_type_id { struct sandbox_state { const char *cmd; /* Command to execute */ enum exit_type_id exit_type; /* How we exited U-Boot */ + const char *parse_err; /* Error to report from parsing */ + int argc; /* Program arguments */ + char **argv; }; /** diff --git a/arch/sandbox/include/asm/u-boot-sandbox.h b/arch/sandbox/include/asm/u-boot-sandbox.h index 99e950b805..50bf8c605d 100644 --- a/arch/sandbox/include/asm/u-boot-sandbox.h +++ b/arch/sandbox/include/asm/u-boot-sandbox.h @@ -36,6 +36,7 @@ int board_init(void); int dram_init(void); /* start.c */ +int sandbox_early_getopt_check(void); int sandbox_main_loop_init(void); #endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 25a8d02fd7..306d1ec332 100644 --- a/arch/sandbox/lib/board.c +++ b/arch/sandbox/lib/board.c @@ -134,6 +134,7 @@ init_fnc_t *init_sequence[] = { env_init, /* initialize environment */ serial_init, /* serial communications setup */ console_init_f, /* stage 1 init of console */ + sandbox_early_getopt_check, /* process command line flags (err/help) */ display_banner, /* say that we are here */ #if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ -- cgit v1.2.3