[U-Boot] [PATCH 1/3] sandbox: add concept of sandbox state

From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org --- 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
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 2ae0f71..6fd09ff 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 a429e29..2b66eed 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 <common.h> +#include <asm/state.h>
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 0000000..88ae2b0 --- /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 <common.h> +#include <asm/state.h> + +/* 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 0000000..5b34e94 --- /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

From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org --- 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(+), 0 deletions(-)
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2b66eed..dc020ee 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,6 +22,11 @@ #include <common.h> #include <asm/state.h>
+int sb_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 236b4ee..f0e8b3c 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 sb_main_loop_init(void); + #endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 6d464d6..1082e7d 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
+ sb_main_loop_init(); + /* * For now, run the main loop. Later we might let this be done * in the main program.

Hi Mike,
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger vapier@gentoo.org wrote:
From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org
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(+), 0 deletions(-)
diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2b66eed..dc020ee 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,6 +22,11 @@ #include <common.h> #include <asm/state.h>
+int sb_main_loop_init(void)
Would prefer sandbox_main_loop_init()
+{
- 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 236b4ee..f0e8b3c 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 sb_main_loop_init(void);
#endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 6d464d6..1082e7d 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
- sb_main_loop_init();
/* * For now, run the main loop. Later we might let this be done * in the main program. -- 1.7.8.4
Regards, Simon

Signed-off-by: Mike Frysinger vapier@gentoo.org --- arch/sandbox/cpu/os.c | 64 ++++++++++++++++++++++ arch/sandbox/cpu/start.c | 83 +++++++++++++++++++++++++++++ arch/sandbox/cpu/u-boot.lds | 4 ++ arch/sandbox/include/asm/state.h | 5 ++ arch/sandbox/include/asm/u-boot-sandbox.h | 1 + arch/sandbox/lib/board.c | 1 + include/os.h | 35 ++++++++++++ 7 files changed, 193 insertions(+), 0 deletions(-)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index cb469e0..4b1c987 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -21,6 +21,7 @@
#include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <stdlib.h> #include <termios.h> #include <time.h> @@ -32,6 +33,7 @@ #include <linux/types.h>
#include <os.h> +#include <asm/state.h>
/* Operating System Interface */
@@ -155,3 +157,65 @@ u64 os_get_nsec(void) return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; #endif } + +extern struct sb_cmdline_option *__u_boot_sb_getopt_start[], + *__u_boot_sb_getopt_end[]; +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_sb_getopt_start; + size_t num_flags = __u_boot_sb_getopt_end - __u_boot_sb_getopt_start; + size_t i; + + int hidden_short_opt; + size_t si; + + int c; + + if (short_opts || long_opts) + os_exit(1); + + state->argc = argc; + state->argv = argv; + + short_opts = os_malloc(sizeof(*short_opts) * (num_flags + 1)); + long_opts = os_malloc(sizeof(*long_opts) * num_flags); + if (!short_opts || !long_opts) + os_exit(1); + + si = 0; + hidden_short_opt = 0x80; + for (i = 0; i < num_flags; ++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; + 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; + + while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { + for (i = 0; i < num_flags; ++i) { + if (sb_opt[i]->flag_short == c) { + sb_opt[i]->callback(state, optarg); + break; + } + } + if (i == num_flags) { + /* store the faulting flag index for later */ + state->parse_err = -optind; + break; + } + } + + return 0; +} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index dc020ee..895ec49 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,19 +22,102 @@ #include <common.h> #include <asm/state.h>
+#include <os.h> + +extern struct sb_cmdline_option *__u_boot_sb_getopt_start[], + *__u_boot_sb_getopt_end[]; + +int sb_early_getopt_check(void) +{ + struct sandbox_state *state = state_get_current(); + struct sb_cmdline_option **sb_opt = __u_boot_sb_getopt_start; + size_t num_flags = __u_boot_sb_getopt_end - __u_boot_sb_getopt_start; + size_t i; + int max_arg_len, max_noarg_len; + + if (state->parse_err == 0) + return 0; + + if (state->parse_err < 0) + printf("error: unknown option: %s\n\n", + state->argv[-state->parse_err - 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_flags; ++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_flags; ++i) { + /* first output the short flag if it has one */ + if (sb_opt[i]->flag_short >= 0x80) + printf(" "); + else + printf(" -%c, ", sb_opt[i]->flag_short); + + /* then the long flag */ + if (sb_opt[i]->has_arg) + printf("--%-*s", max_noarg_len, sb_opt[i]->flag); + else + printf("--%-*s <arg> ", max_arg_len, sb_opt[i]->flag); + + /* finally the help text */ + printf(" %s\n", sb_opt[i]->help); + } + + os_exit(state->parse_err < 0 ? 1 : 0); +} + +static int sb_cmdline_cb_help(struct sandbox_state *state, const char *arg) +{ + /* just flag to sb_early_getopt_check to show usage */ + state->parse_err = 1; + return 0; +} +SB_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help"); + int sb_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(); + os_parse_args(state, argc, argv); + /* * 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 0c56aa7..2ca6b8c 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_sb_getopt_start = .; + _u_boot_sb_getopt : { *(.u_boot_sb_getopt) } + __u_boot_sb_getopt_end = .; + __bss_start = .; }
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 5b34e94..edeef08 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 <config.h> + /* 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 */ + int 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 f0e8b3c..8255e9d 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 sb_early_getopt_check(void); int sb_main_loop_init(void);
#endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 1082e7d..5c6da5b 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 */ + sb_early_getopt_check, display_banner, /* say that we are here */ #if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ diff --git a/include/os.h b/include/os.h index 6b7ee47..aea4503 100644 --- a/include/os.h +++ b/include/os.h @@ -27,6 +27,8 @@ #ifndef __OS_H__ #define __OS_H__
+struct sandbox_state; + /** * Access to the OS read() system call * @@ -122,4 +124,37 @@ void os_usleep(unsigned long usec); */ u64 os_get_nsec(void);
+/** + * Parse arguments and update sandbox state. + * + * @param state Sandbox state to update + * @param argc Argument count + * @param argv Argument vector + * @return 0 if ok, and program should continue; + * 1 if ok, but program should stop; + * -1 on error: program should terminate. + */ +int os_parse_args(struct sandbox_state *state, int argc, char *argv[]); + +struct sb_cmdline_option { + const char *flag; + char flag_short; + const char *help; + int has_arg; + int (*callback)(struct sandbox_state *state, const char *opt); +}; +#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, \ + }; \ + static __attribute__((section(".u_boot_sb_getopt"), used)) \ + struct sb_cmdline_option *sb_cmdline_option_##f##_ptr = \ + &sb_cmdline_option_##f +#define SB_CMDLINE_OPT(f, ha, h) _SB_CMDLINE_OPT(f, 0, ha, h) +#define SB_CMDLINE_OPT_SHORT(f, s, ha, h) _SB_CMDLINE_OPT(f, s, ha, h) + #endif

Hi Mike,
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger vapier@gentoo.org wrote:
Signed-off-by: Mike Frysinger vapier@gentoo.org
arch/sandbox/cpu/os.c | 64 ++++++++++++++++++++++ arch/sandbox/cpu/start.c | 83 +++++++++++++++++++++++++++++ arch/sandbox/cpu/u-boot.lds | 4 ++ arch/sandbox/include/asm/state.h | 5 ++ arch/sandbox/include/asm/u-boot-sandbox.h | 1 + arch/sandbox/lib/board.c | 1 + include/os.h | 35 ++++++++++++ 7 files changed, 193 insertions(+), 0 deletions(-)
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index cb469e0..4b1c987 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -21,6 +21,7 @@
#include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <stdlib.h> #include <termios.h> #include <time.h> @@ -32,6 +33,7 @@ #include <linux/types.h>
#include <os.h> +#include <asm/state.h>
/* Operating System Interface */
@@ -155,3 +157,65 @@ u64 os_get_nsec(void) return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000; #endif }
+extern struct sb_cmdline_option *__u_boot_sb_getopt_start[],
- *__u_boot_sb_getopt_end[];
I wonder if we can put this in asm-generic/sections.h - or perhaps that doesn't exist yet?
Also how about __u_boot_sandbox_option_start/end? I'm really not keen on 'sb'.
+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_sb_getopt_start;
- size_t num_flags = __u_boot_sb_getopt_end - __u_boot_sb_getopt_start;
num_options?
- size_t i;
- int hidden_short_opt;
- size_t si;
si?
- int c;
- if (short_opts || long_opts)
- os_exit(1);
- state->argc = argc;
- state->argv = argv;
- short_opts = os_malloc(sizeof(*short_opts) * (num_flags + 1));
Comment on why +1? is it for \0 terminator?
- long_opts = os_malloc(sizeof(*long_opts) * num_flags);
- if (!short_opts || !long_opts)
- os_exit(1);
- si = 0;
- hidden_short_opt = 0x80;
- for (i = 0; i < num_flags; ++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;
- else
- long_opts[i].val = sb_opt[i]->flag_short = hidden_short_opt++;
What is this hidden_short_opt for? Suggest a comment.
- }
- short_opts[si] = '\0';
- /* We need to handle output ourselves since u-boot provides printf */
- opterr = 0;
- while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
- for (i = 0; i < num_flags; ++i) {
- if (sb_opt[i]->flag_short == c) {
- sb_opt[i]->callback(state, optarg);
- break;
- }
- }
- if (i == num_flags) {
- /* store the faulting flag index for later */
- state->parse_err = -optind;
- break;
- }
- }
- return 0;
+} diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index dc020ee..895ec49 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -22,19 +22,102 @@ #include <common.h> #include <asm/state.h>
+#include <os.h>
+extern struct sb_cmdline_option *__u_boot_sb_getopt_start[],
- *__u_boot_sb_getopt_end[];
As above
+int sb_early_getopt_check(void) +{
- struct sandbox_state *state = state_get_current();
- struct sb_cmdline_option **sb_opt = __u_boot_sb_getopt_start;
- size_t num_flags = __u_boot_sb_getopt_end - __u_boot_sb_getopt_start;
num_options again
- size_t i;
- int max_arg_len, max_noarg_len;
- if (state->parse_err == 0)
- return 0;
Comment: parse_error stores -n where n is the index of the option that we faulted.
- if (state->parse_err < 0)
- printf("error: unknown option: %s\n\n",
- state->argv[-state->parse_err - 1]);
- printf(
do we need this extra newline?
- "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_flags; ++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_flags; ++i) {
- /* first output the short flag if it has one */
- if (sb_opt[i]->flag_short >= 0x80)
Can we declare a pointer to sb_opt[i] and the top here and use it below?
- printf(" ");
- else
- printf(" -%c, ", sb_opt[i]->flag_short);
- /* then the long flag */
- if (sb_opt[i]->has_arg)
- printf("--%-*s", max_noarg_len, sb_opt[i]->flag);
- else
- printf("--%-*s <arg> ", max_arg_len, sb_opt[i]->flag);
- /* finally the help text */
- printf(" %s\n", sb_opt[i]->help);
puts() might be safer, but then again I think we have vsnprintf() turned on now.
- }
- os_exit(state->parse_err < 0 ? 1 : 0);
+}
+static int sb_cmdline_cb_help(struct sandbox_state *state, const char *arg) +{
- /* just flag to sb_early_getopt_check to show usage */
- state->parse_err = 1;
- return 0;
+} +SB_CMDLINE_OPT_SHORT(help, 'h', 0, "Display help");
int sb_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();
- os_parse_args(state, argc, argv);
We don't check the return value. Perhaps add a comment as to why.
/* * 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 0c56aa7..2ca6b8c 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_sb_getopt_start = .;
- _u_boot_sb_getopt : { *(.u_boot_sb_getopt) }
- __u_boot_sb_getopt_end = .;
__bss_start = .; }
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h index 5b34e94..edeef08 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 <config.h>
/* 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 */
- int 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 f0e8b3c..8255e9d 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 sb_early_getopt_check(void); int sb_main_loop_init(void);
#endif /* _U_BOOT_SANDBOX_H_ */ diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c index 1082e7d..5c6da5b 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 */
- sb_early_getopt_check,
comment
display_banner, /* say that we are here */ #if defined(CONFIG_DISPLAY_CPUINFO) print_cpuinfo, /* display cpu info (and speed) */ diff --git a/include/os.h b/include/os.h index 6b7ee47..aea4503 100644 --- a/include/os.h +++ b/include/os.h @@ -27,6 +27,8 @@ #ifndef __OS_H__ #define __OS_H__
+struct sandbox_state;
/** * Access to the OS read() system call * @@ -122,4 +124,37 @@ void os_usleep(unsigned long usec); */ u64 os_get_nsec(void);
+/**
- Parse arguments and update sandbox state.
- @param state Sandbox state to update
- @param argc Argument count
- @param argv Argument vector
- @return 0 if ok, and program should continue;
- 1 if ok, but program should stop;
- -1 on error: program should terminate.
- */
+int os_parse_args(struct sandbox_state *state, int argc, char *argv[]);
+struct sb_cmdline_option {
- const char *flag;
comment each of these members
- char flag_short;
- const char *help;
- int has_arg;
- int (*callback)(struct sandbox_state *state, const char *opt);
comment this callback
+}; +#define _SB_CMDLINE_OPT(f, s, ha, h) \
comment: declare an option to be understood by sandbox...
- static struct sb_cmdline_option sb_cmdline_option_##f = { \
- .flag = #f, \
- .flag_short = s, \
- .help = h, \
- .has_arg = ha, \
- .callback = sb_cmdline_cb_##f, \
- }; \
- static __attribute__((section(".u_boot_sb_getopt"), used)) \
- struct sb_cmdline_option *sb_cmdline_option_##f##_ptr = \
- &sb_cmdline_option_##f
+#define SB_CMDLINE_OPT(f, ha, h) _SB_CMDLINE_OPT(f, 0, ha, h) +#define SB_CMDLINE_OPT_SHORT(f, s, ha, h) _SB_CMDLINE_OPT(f, s, ha, h)
SANDBOX: also please comment these, perhaps with args also.
#endif
1.7.8.4
Regards, Simon

On Sunday 26 February 2012 21:46:23 Simon Glass wrote:
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger wrote:
--- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c
+extern struct sb_cmdline_option *__u_boot_sb_getopt_start[],
*__u_boot_sb_getopt_end[];
I wonder if we can put this in asm-generic/sections.h - or perhaps that doesn't exist yet?
sorry, should have labeled this patch more as a PoC as i know it requires a little more polish. these would go into sandbox's asm/sections.h since these are specific to the sandbox port.
Also how about __u_boot_sandbox_option_start/end? I'm really not keen on 'sb'.
for these two vars, that's fine. i prefer "sb" for internal static stuff since "sandbox" can get wordy real fast.
int hidden_short_opt;
size_t si;
si?
short_opt_index is the self-commenting name
short_opts = os_malloc(sizeof(*short_opts) * (num_flags + 1));
Comment on why +1? is it for \0 terminator?
yes, the getopt_long() api requires a NUL terminated string
si = 0;
hidden_short_opt = 0x80;
for (i = 0; i < num_flags; ++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; + else
long_opts[i].val = sb_opt[i]->flag_short =
hidden_short_opt++;
What is this hidden_short_opt for? Suggest a comment.
i think most options we have will be long only. much harder to make sure you don't have collisions in the entire base when the flag definition is in the subfiles. but getopt_long() needs a unique int for each long flag, so "hidden" just means "not an ascii char".
if (state->parse_err < 0)
printf("error: unknown option: %s\n\n",
state->argv[-state->parse_err - 1]);
printf(
do we need this extra newline?
i find the extra newline helps to differentiate from the noise when we turn around and dump the --help output. alternative would be to not automatically show --help.
for (i = 0; i < num_flags; ++i) {
/* first output the short flag if it has one */
if (sb_opt[i]->flag_short >= 0x80)
Can we declare a pointer to sb_opt[i] and the top here and use it below?
yes
printf(" ");
else
printf(" -%c, ", sb_opt[i]->flag_short);
/* then the long flag */
if (sb_opt[i]->has_arg)
printf("--%-*s", max_noarg_len, sb_opt[i]->flag);
else
printf("--%-*s <arg> ", max_arg_len,
sb_opt[i]->flag); +
/* finally the help text */
printf(" %s\n", sb_opt[i]->help);
puts() might be safer, but then again I think we have vsnprintf() turned on now.
not sure what you mean by "safer" ... if you mean the implicit stack overflows, i don't think that'll be an issue here. the help strings aren't very long.
int main(int argc, char *argv[]) { ...
state = state_get_current();
os_parse_args(state, argc, argv);
We don't check the return value. Perhaps add a comment as to why.
since the code takes care of setting parse_err itself now, i'm not sure what to do with the return value -mike

Hi Mike,
On Sun, Feb 26, 2012 at 8:20 PM, Mike Frysinger vapier@gentoo.org wrote:
On Sunday 26 February 2012 21:46:23 Simon Glass wrote:
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger wrote:
--- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c
+extern struct sb_cmdline_option *__u_boot_sb_getopt_start[],
- *__u_boot_sb_getopt_end[];
I wonder if we can put this in asm-generic/sections.h - or perhaps that doesn't exist yet?
sorry, should have labeled this patch more as a PoC as i know it requires a little more polish. these would go into sandbox's asm/sections.h since these are specific to the sandbox port.
Also how about __u_boot_sandbox_option_start/end? I'm really not keen on 'sb'.
for these two vars, that's fine. i prefer "sb" for internal static stuff since "sandbox" can get wordy real fast.
- int hidden_short_opt;
- size_t si;
si?
short_opt_index is the self-commenting name
- short_opts = os_malloc(sizeof(*short_opts) * (num_flags + 1));
Comment on why +1? is it for \0 terminator?
yes, the getopt_long() api requires a NUL terminated string
- si = 0;
- hidden_short_opt = 0x80;
- for (i = 0; i < num_flags; ++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; + else
- long_opts[i].val = sb_opt[i]->flag_short =
hidden_short_opt++;
What is this hidden_short_opt for? Suggest a comment.
i think most options we have will be long only. much harder to make sure you don't have collisions in the entire base when the flag definition is in the subfiles. but getopt_long() needs a unique int for each long flag, so "hidden" just means "not an ascii char".
- if (state->parse_err < 0)
- printf("error: unknown option: %s\n\n",
- state->argv[-state->parse_err - 1]);
- printf(
do we need this extra newline?
i find the extra newline helps to differentiate from the noise when we turn around and dump the --help output. alternative would be to not automatically show --help.
- for (i = 0; i < num_flags; ++i) {
- /* first output the short flag if it has one */
- if (sb_opt[i]->flag_short >= 0x80)
Can we declare a pointer to sb_opt[i] and the top here and use it below?
yes
- printf(" ");
- else
- printf(" -%c, ", sb_opt[i]->flag_short);
- /* then the long flag */
- if (sb_opt[i]->has_arg)
- printf("--%-*s", max_noarg_len, sb_opt[i]->flag);
- else
- printf("--%-*s <arg> ", max_arg_len,
sb_opt[i]->flag); +
- /* finally the help text */
- printf(" %s\n", sb_opt[i]->help);
puts() might be safer, but then again I think we have vsnprintf() turned on now.
not sure what you mean by "safer" ... if you mean the implicit stack overflows, i don't think that'll be an issue here. the help strings aren't very long.
int main(int argc, char *argv[]) { ...
- state = state_get_current();
- os_parse_args(state, argc, argv);
We don't check the return value. Perhaps add a comment as to why.
since the code takes care of setting parse_err itself now, i'm not sure what to do with the return value
I agree it is right, just asking for a comment. Same with most of my other things - more comments as I suggested is nice for people that come into the code fresh.
Regards, Simon
-mike

On Sunday 26 February 2012 23:26:52 Simon Glass wrote:
On Sun, Feb 26, 2012 at 8:20 PM, Mike Frysinger wrote:
On Sunday 26 February 2012 21:46:23 Simon Glass wrote:
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger wrote:
int main(int argc, char *argv[]) { ...
state = state_get_current();
os_parse_args(state, argc, argv);
We don't check the return value. Perhaps add a comment as to why.
since the code takes care of setting parse_err itself now, i'm not sure what to do with the return value
I agree it is right, just asking for a comment. Same with most of my other things - more comments as I suggested is nice for people that come into the code fresh.
my plan was to clean this up a bit more before submitting (such as adding comments). i was looking more for feedback on the general approach here and any fundamental sticking points since this is a semi-radical departure from what either of us posted earlier.
in this case, i'm asking: should we just toss the return value and have it be void ? -mike

Hi Mike,
On Sun, Feb 26, 2012 at 8:35 PM, Mike Frysinger vapier@gentoo.org wrote:
On Sunday 26 February 2012 23:26:52 Simon Glass wrote:
On Sun, Feb 26, 2012 at 8:20 PM, Mike Frysinger wrote:
On Sunday 26 February 2012 21:46:23 Simon Glass wrote:
On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger wrote:
int main(int argc, char *argv[]) { ...
- state = state_get_current();
- os_parse_args(state, argc, argv);
We don't check the return value. Perhaps add a comment as to why.
since the code takes care of setting parse_err itself now, i'm not sure what to do with the return value
I agree it is right, just asking for a comment. Same with most of my other things - more comments as I suggested is nice for people that come into the code fresh.
my plan was to clean this up a bit more before submitting (such as adding comments). i was looking more for feedback on the general approach here and any fundamental sticking points since this is a semi-radical departure from what either of us posted earlier.
OK I see. Well actually I was expecting that we would need something along these lines eventually, since arg parsing belongs with the module that provides the argument I think. So as well to have it now, even if it doesn't have a lot of uses yet. It will.
in this case, i'm asking: should we just toss the return value and have it be void ?
I suggest not - even if we ignore it, it seems like information that should be returned. Perhaps we should make it more explicit by returning state->return_code with a comment that callers can use it now or later. But I think the way you have done it is fine.
Regards, Simon
-mike

From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org --- v2 - rework error detection to handle edge cases - add comments all over - do some renaming - split into dedicated headers where applicable - should be ready for merging now if people are happy
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 + include/os.h | 14 ++++ 9 files changed, 304 insertions(+), 0 deletions(-) create mode 100644 arch/sandbox/include/asm/getopt.h create mode 100644 arch/sandbox/include/asm/sections.h
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index cb469e0..36637af 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -21,6 +21,7 @@
#include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <stdlib.h> #include <termios.h> #include <time.h> @@ -31,6 +32,9 @@ #include <sys/types.h> #include <linux/types.h>
+#include <asm/getopt.h> +#include <asm/sections.h> +#include <asm/state.h> #include <os.h>
/* 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=<next> + * -abbbb optopt='a' optind=<this> + * -aaaaa optopt='a' optind=<this> + * --a optopt=0 optind=<this> + * 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 4a84486..6c3e8eb 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -20,21 +20,109 @@ */
#include <common.h> +#include <asm/getopt.h> +#include <asm/sections.h> #include <asm/state.h>
+#include <os.h> + +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 <arg> ", 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 0c56aa7..9960138 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 0000000..685883c --- /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 0000000..eafce7d --- /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 5b34e94..2b62b46 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 <config.h> + /* 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 99e950b..50bf8c6 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 25a8d02..306d1ec 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) */ diff --git a/include/os.h b/include/os.h index 6b7ee47..45729c1 100644 --- a/include/os.h +++ b/include/os.h @@ -27,6 +27,8 @@ #ifndef __OS_H__ #define __OS_H__
+struct sandbox_state; + /** * Access to the OS read() system call * @@ -122,4 +124,16 @@ void os_usleep(unsigned long usec); */ u64 os_get_nsec(void);
+/** + * Parse arguments and update sandbox state. + * + * @param state Sandbox state to update + * @param argc Argument count + * @param argv Argument vector + * @return 0 if ok, and program should continue; + * 1 if ok, but program should stop; + * -1 on error: program should terminate. + */ +int os_parse_args(struct sandbox_state *state, int argc, char *argv[]); + #endif

On Sat, Mar 3, 2012 at 11:38 PM, Mike Frysinger vapier@gentoo.org wrote:
From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org
Acked-by: Simon Glass sjg@chromium.org
v2 - rework error detection to handle edge cases - add comments all over - do some renaming - split into dedicated headers where applicable - should be ready for merging now if people are happy
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 + include/os.h | 14 ++++ 9 files changed, 304 insertions(+), 0 deletions(-) create mode 100644 arch/sandbox/include/asm/getopt.h create mode 100644 arch/sandbox/include/asm/sections.h
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index cb469e0..36637af 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -21,6 +21,7 @@
#include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <stdlib.h> #include <termios.h> #include <time.h> @@ -31,6 +32,9 @@ #include <sys/types.h> #include <linux/types.h>
+#include <asm/getopt.h> +#include <asm/sections.h> +#include <asm/state.h> #include <os.h>
/* 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=<next>
- * -abbbb optopt='a' optind=<this>
- * -aaaaa optopt='a' optind=<this>
- * --a optopt=0 optind=<this>
- * 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 4a84486..6c3e8eb 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -20,21 +20,109 @@ */
#include <common.h> +#include <asm/getopt.h> +#include <asm/sections.h> #include <asm/state.h>
+#include <os.h>
+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 <arg> ", 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 0c56aa7..9960138 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 0000000..685883c --- /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 0000000..eafce7d --- /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 5b34e94..2b62b46 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 <config.h>
/* 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 99e950b..50bf8c6 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 25a8d02..306d1ec 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) */ diff --git a/include/os.h b/include/os.h index 6b7ee47..45729c1 100644 --- a/include/os.h +++ b/include/os.h @@ -27,6 +27,8 @@ #ifndef __OS_H__ #define __OS_H__
+struct sandbox_state;
/** * Access to the OS read() system call * @@ -122,4 +124,16 @@ void os_usleep(unsigned long usec); */ u64 os_get_nsec(void);
+/**
- Parse arguments and update sandbox state.
- @param state Sandbox state to update
- @param argc Argument count
- @param argv Argument vector
- @return 0 if ok, and program should continue;
- 1 if ok, but program should stop;
- -1 on error: program should terminate.
- */
+int os_parse_args(struct sandbox_state *state, int argc, char *argv[]);
#endif
1.7.8.4

On Sun, Feb 26, 2012 at 2:38 PM, Mike Frysinger vapier@gentoo.org wrote:
From: Simon Glass sjg@chromium.org
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 sjg@chromium.org Signed-off-by: Mike Frysinger vapier@gentoo.org
Acked-by: Simon Glass sjg@chromium.org
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
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile index 2ae0f71..6fd09ff 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 a429e29..2b66eed 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 <common.h> +#include <asm/state.h>
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 0000000..88ae2b0 --- /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 <common.h> +#include <asm/state.h>
+/* 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 0000000..5b34e94 --- /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
1.7.8.4
participants (2)
-
Mike Frysinger
-
Simon Glass