[U-Boot] [PATCH 3/3] sandbox: add getopt support
Mike Frysinger
vapier at gentoo.org
Sun Feb 26 23:38:51 CET 2012
Signed-off-by: Mike Frysinger <vapier at 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
--
1.7.8.4
More information about the U-Boot
mailing list