From 28be0e94db5c92202a94fe204beb5d0ea0936771 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Thu, 10 Jun 2010 12:12:03 +0530 Subject: [PATCH] add example usage to hello command --- commands/acpi.c | 5 ++--- commands/echo.c | 4 ++-- commands/extcmd.c | 23 ++++++++++++++----- commands/hashsum.c | 6 ++--- commands/hdparm.c | 4 ++-- commands/help.c | 2 +- commands/hexdump.c | 4 ++-- commands/i386/cpuid.c | 2 +- commands/i386/pc/drivemap.c | 12 +++++----- commands/i386/pc/halt.c | 4 ++-- commands/iorw.c | 8 +++---- commands/keystatus.c | 4 ++-- commands/loadenv.c | 12 +++++----- commands/ls.c | 4 ++-- commands/lspci.c | 4 ++-- commands/memrw.c | 8 +++---- commands/probe.c | 4 ++-- commands/search_wrap.c | 4 ++-- commands/setpci.c | 16 ++++++------- commands/sleep.c | 4 ++-- disk/loopback.c | 4 ++-- hello/hello.c | 38 ++++++++++++++++++++++++++----- include/grub/command.h | 2 ++ include/grub/extcmd.h | 22 +++++++++++++++--- include/grub/script_sh.h | 3 +++ loader/i386/bsd.c | 20 ++++++++--------- loader/xnu.c | 6 ++--- script/argv.c | 45 +++++++++++++++++++++++++++++++++++-- script/execute.c | 25 ++++++++++++++++----- script/parser.y | 2 +- script/script.c | 8 ++++++- term/gfxterm.c | 7 +++--- term/serial.c | 4 ++-- tests/lib/functional_test.c | 2 +- 34 files changed, 220 insertions(+), 102 deletions(-) diff --git a/commands/acpi.c b/commands/acpi.c index 5bbfd008b..bdfdea073 100644 --- a/commands/acpi.c +++ b/commands/acpi.c @@ -456,10 +456,9 @@ free_tables (void) } static grub_err_t -grub_cmd_acpi (struct grub_extcmd *cmd, - int argc, char **args) +grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; struct grub_acpi_rsdp_v10 *rsdp; struct efiemu_acpi_table *cur, *t; grub_err_t err; diff --git a/commands/echo.c b/commands/echo.c index 4fea091cb..6bc00eae8 100644 --- a/commands/echo.c +++ b/commands/echo.c @@ -30,9 +30,9 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_echo (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_echo (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int newline = 1; int i; diff --git a/commands/extcmd.c b/commands/extcmd.c index 16796febf..76cbe4e26 100644 --- a/commands/extcmd.c +++ b/commands/extcmd.c @@ -21,15 +21,17 @@ #include #include #include +#include -static grub_err_t -grub_extcmd_dispatcher (struct grub_command *cmd, - int argc, char **args) +grub_err_t +grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, + struct grub_script **scripts) { int new_argc; char **new_args; struct grub_arg_option *parser; struct grub_arg_list *state; + struct grub_extcmd_context context; int maxargs = 0; grub_err_t ret; grub_extcmd_t ext; @@ -44,8 +46,11 @@ grub_extcmd_dispatcher (struct grub_command *cmd, if (grub_arg_parse (ext, argc, args, state, &new_args, &new_argc)) { - ext->state = state; - ret = (ext->func) (ext, new_argc, new_args); + context.extcmd = ext; + context.state = state; + context.script_params = scripts; + + ret = (ext->func) (&context, new_argc, new_args); grub_free (new_args); } else @@ -56,6 +61,12 @@ grub_extcmd_dispatcher (struct grub_command *cmd, return ret; } +static grub_err_t +grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) +{ + return grub_extcmd_dispatcher (cmd, argc, args, 0); +} + grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, unsigned flags, const char *summary, @@ -69,7 +80,7 @@ grub_register_extcmd (const char *name, grub_extcmd_func_t func, if (! ext) return 0; - cmd = grub_register_command_prio (name, grub_extcmd_dispatcher, + cmd = grub_register_command_prio (name, grub_extcmd_dispatch, summary, description, 1); if (! cmd) { diff --git a/commands/hashsum.c b/commands/hashsum.c index d5f551dbb..df85015a6 100644 --- a/commands/hashsum.c +++ b/commands/hashsum.c @@ -165,10 +165,10 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, } static grub_err_t -grub_cmd_hashsum (struct grub_extcmd *cmd, +grub_cmd_hashsum (struct grub_extcmd_context *ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *hashname = NULL; const char *prefix = NULL; const gcry_md_spec_t *hash; @@ -177,7 +177,7 @@ grub_cmd_hashsum (struct grub_extcmd *cmd, unsigned unread = 0; for (i = 0; i < ARRAY_SIZE (aliases); i++) - if (grub_strcmp (cmd->cmd->name, aliases[i].name) == 0) + if (grub_strcmp (ctxt->extcmd->cmd->name, aliases[i].name) == 0) hashname = aliases[i].hashname; if (state[0].set) hashname = state[0].arg; diff --git a/commands/hdparm.c b/commands/hdparm.c index a3f8bbff0..54724077d 100644 --- a/commands/hdparm.c +++ b/commands/hdparm.c @@ -270,9 +270,9 @@ static int get_int_arg (const struct grub_arg_list *state) } static grub_err_t -grub_cmd_hdparm (grub_extcmd_t cmd, int argc, char **args) // state???? +grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check command line. */ if (argc != 1) diff --git a/commands/help.c b/commands/help.c index c2aad03b2..2b2eeaa84 100644 --- a/commands/help.c +++ b/commands/help.c @@ -27,7 +27,7 @@ #include static grub_err_t -grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, +grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char **args) { int cnt = 0; diff --git a/commands/hexdump.c b/commands/hexdump.c index c1d4ecba9..6c518f649 100644 --- a/commands/hexdump.c +++ b/commands/hexdump.c @@ -34,9 +34,9 @@ static const struct grub_arg_option options[] = { }; static grub_err_t -grub_cmd_hexdump (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; char buf[GRUB_DISK_SECTOR_SIZE * 4]; grub_ssize_t size, length; grub_disk_addr_t skip; diff --git a/commands/i386/cpuid.c b/commands/i386/cpuid.c index 6eebf91a1..412b284d0 100644 --- a/commands/i386/cpuid.c +++ b/commands/i386/cpuid.c @@ -43,7 +43,7 @@ static const struct grub_arg_option options[] = unsigned char grub_cpuid_has_longmode = 0; static grub_err_t -grub_cmd_cpuid (grub_extcmd_t cmd __attribute__ ((unused)), +grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { diff --git a/commands/i386/pc/drivemap.c b/commands/i386/pc/drivemap.c index 4afc43358..7ecfe7454 100644 --- a/commands/i386/pc/drivemap.c +++ b/commands/i386/pc/drivemap.c @@ -196,13 +196,13 @@ list_mappings (void) } static grub_err_t -grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) +grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args) { - if (cmd->state[OPTIDX_LIST].set) + if (ctxt->state[OPTIDX_LIST].set) { return list_mappings (); } - else if (cmd->state[OPTIDX_RESET].set) + else if (ctxt->state[OPTIDX_RESET].set) { /* Reset: just delete all mappings, freeing their memory. */ drivemap_node_t *curnode = map_head; @@ -216,7 +216,7 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) map_head = 0; return GRUB_ERR_NONE; } - else if (!cmd->state[OPTIDX_SWAP].set && argc == 0) + else if (!ctxt->state[OPTIDX_SWAP].set && argc == 0) { /* No arguments */ return list_mappings (); @@ -248,11 +248,11 @@ grub_cmd_drivemap (struct grub_extcmd *cmd, int argc, char **args) } /* Set the mapping for the disk (overwrites any existing mapping). */ grub_dprintf ("drivemap", "%s %s (%02x) = %s (%02x)\n", - cmd->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", + ctxt->state[OPTIDX_SWAP].set ? "Swapping" : "Mapping", args[1], mapto, args[0], mapfrom); err = drivemap_set (mapto, mapfrom); /* If -s, perform the reverse mapping too (only if the first was OK). */ - if (cmd->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) + if (ctxt->state[OPTIDX_SWAP].set && err == GRUB_ERR_NONE) err = drivemap_set (mapfrom, mapto); return err; } diff --git a/commands/i386/pc/halt.c b/commands/i386/pc/halt.c index 4c39612ae..10b298644 100644 --- a/commands/i386/pc/halt.c +++ b/commands/i386/pc/halt.c @@ -29,12 +29,12 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_halt (grub_extcmd_t cmd, +grub_cmd_halt (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int no_apm = 0; if (state[0].set) no_apm = 1; diff --git a/commands/iorw.c b/commands/iorw.c index 474c8712e..bd0183794 100644 --- a/commands/iorw.c +++ b/commands/iorw.c @@ -36,7 +36,7 @@ static const struct grub_arg_option options[] = static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; @@ -46,7 +46,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("in") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1]) { case 'l': value = grub_inl (addr); @@ -61,10 +61,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); diff --git a/commands/keystatus.c b/commands/keystatus.c index 838792889..c83c00560 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -34,11 +34,11 @@ static const struct grub_arg_option options[] = #define grub_cur_term_input grub_term_get_current_input () static grub_err_t -grub_cmd_keystatus (grub_extcmd_t cmd, +grub_cmd_keystatus (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int expect_mods = 0; int mods; diff --git a/commands/loadenv.c b/commands/loadenv.c index d763b2d5e..381810a92 100644 --- a/commands/loadenv.c +++ b/commands/loadenv.c @@ -111,11 +111,11 @@ read_envblk_file (grub_file_t file) } static grub_err_t -grub_cmd_load_env (grub_extcmd_t cmd, +grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -143,11 +143,11 @@ grub_cmd_load_env (grub_extcmd_t cmd, } static grub_err_t -grub_cmd_list_env (grub_extcmd_t cmd, +grub_cmd_list_env (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; @@ -280,9 +280,9 @@ write_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, } static grub_err_t -grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_save_env (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; grub_envblk_t envblk; struct blocklist *head = 0; diff --git a/commands/ls.c b/commands/ls.c index eb1049617..6b2f63c19 100644 --- a/commands/ls.c +++ b/commands/ls.c @@ -248,9 +248,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) } static grub_err_t -grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; if (argc == 0) grub_ls_list_devices (state[0].set); diff --git a/commands/lspci.c b/commands/lspci.c index a69bb35ad..bc52e060a 100644 --- a/commands/lspci.c +++ b/commands/lspci.c @@ -211,11 +211,11 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) } static grub_err_t -grub_cmd_lspci (grub_extcmd_t cmd, +grub_cmd_lspci (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - iospace = cmd->state[0].set; + iospace = ctxt->state[0].set; grub_pci_iterate (grub_lspci_iter); return GRUB_ERR_NONE; } diff --git a/commands/memrw.c b/commands/memrw.c index 6a4d43be2..d28f45ec1 100644 --- a/commands/memrw.c +++ b/commands/memrw.c @@ -35,7 +35,7 @@ static const struct grub_arg_option options[] = static grub_err_t -grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; @@ -45,7 +45,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments"); addr = grub_strtoul (argv[0], 0, 0); - switch (cmd->cmd->name[sizeof ("read_") - 1]) + switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1]) { case 'd': value = *((volatile grub_uint32_t *) addr); @@ -60,10 +60,10 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) break; } - if (cmd->state[0].set) + if (ctxt->state[0].set) { grub_snprintf (buf, sizeof (buf), "%x", value); - grub_env_set (cmd->state[0].arg, buf); + grub_env_set (ctxt->state[0].arg, buf); } else grub_printf ("0x%x\n", value); diff --git a/commands/probe.c b/commands/probe.c index c2cc599e9..f3941e029 100644 --- a/commands/probe.c +++ b/commands/probe.c @@ -45,9 +45,9 @@ static const struct grub_arg_option options[] = }; static grub_err_t -grub_cmd_probe (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_device_t dev; grub_fs_t fs; char *ptr; diff --git a/commands/search_wrap.c b/commands/search_wrap.c index 2891d85d7..fff3fb47a 100644 --- a/commands/search_wrap.c +++ b/commands/search_wrap.c @@ -50,9 +50,9 @@ enum options }; static grub_err_t -grub_cmd_search (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; const char *var = 0; if (argc == 0) diff --git a/commands/setpci.c b/commands/setpci.c index fbc7c214e..89a0085d8 100644 --- a/commands/setpci.c +++ b/commands/setpci.c @@ -155,7 +155,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) } static grub_err_t -grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) +grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) { const char *ptr; unsigned i; @@ -163,14 +163,14 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) pciid_check_value = 0; pciid_check_mask = 0; - if (cmd->state[0].set) + if (ctxt->state[0].set) { - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); if (grub_errno == GRUB_ERR_BAD_NUMBER) { grub_errno = GRUB_ERR_NONE; - ptr = cmd->state[0].arg; + ptr = ctxt->state[0].arg; } else pciid_check_mask |= 0xffff; @@ -191,11 +191,11 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) check_bus = check_device = check_function = 0; - if (cmd->state[1].set) + if (ctxt->state[1].set) { const char *optr; - ptr = cmd->state[1].arg; + ptr = ctxt->state[1].arg; optr = ptr; bus = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno == GRUB_ERR_BAD_NUMBER) @@ -229,8 +229,8 @@ grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) } } - if (cmd->state[2].set) - varname = cmd->state[2].arg; + if (ctxt->state[2].set) + varname = ctxt->state[2].arg; else varname = NULL; diff --git a/commands/sleep.c b/commands/sleep.c index ead279506..ee0875cf7 100644 --- a/commands/sleep.c +++ b/commands/sleep.c @@ -60,9 +60,9 @@ grub_interruptible_millisleep (grub_uint32_t ms) } static grub_err_t -grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; int n; if (argc != 1) diff --git a/disk/loopback.c b/disk/loopback.c index 1b525e05f..52929e765 100644 --- a/disk/loopback.c +++ b/disk/loopback.c @@ -71,9 +71,9 @@ delete_loopback (const char *name) /* The command to add and remove loopback devices. */ static grub_err_t -grub_cmd_loopback (grub_extcmd_t cmd, int argc, char **args) +grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) { - struct grub_arg_list *state = state = cmd->state; + struct grub_arg_list *state = ctxt->state; grub_file_t file; struct grub_loopback *newdev; diff --git a/hello/hello.c b/hello/hello.c index eff07d941..16c3bb5ce 100644 --- a/hello/hello.c +++ b/hello/hello.c @@ -26,12 +26,36 @@ #include #include +static struct grub_script *script; + static grub_err_t -grub_cmd_hello (struct grub_extcmd *cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) +grub_cmd_hello (grub_extcmd_context_t ctxt, + int argc, char **args __attribute__ ((unused))) { - grub_printf ("Hello World\n"); + if (argc == 0 && script == 0) + grub_printf ("Hello World\n"); + + else if (argc == 0) + grub_script_execute (script); + + else + { + if (! ctxt->script_params || ! ctxt->script_params[0]) + return 1; + + if (script) + grub_script_free (script); + + script = grub_malloc (sizeof (*script)); + if (! script) + return 1; + + script->cmd = ctxt->script_params[0]->cmd; + script->mem = ctxt->script_params[0]->mem; + ctxt->script_params[0]->cmd = 0; + ctxt->script_params[0]->mem = 0; + } + return 0; } @@ -39,11 +63,15 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hello", grub_cmd_hello, + GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, 0, N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) { + if (script) + grub_script_free (script); + grub_unregister_extcmd (cmd); } diff --git a/include/grub/command.h b/include/grub/command.h index 6e9942b60..c2523f288 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -37,6 +37,8 @@ #define GRUB_COMMAND_FLAG_EXTCMD 0x10 /* This is an dynamic command. */ #define GRUB_COMMAND_FLAG_DYNCMD 0x20 +/* This command accepts block arguments. */ +#define GRUB_COMMAND_FLAG_BLOCKS 0x40 struct grub_command; diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h index 03eaba8f8..54f0958fe 100644 --- a/include/grub/extcmd.h +++ b/include/grub/extcmd.h @@ -21,10 +21,12 @@ #include #include +#include struct grub_extcmd; +struct grub_extcmd_context; -typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd *cmd, +typedef grub_err_t (*grub_extcmd_func_t) (struct grub_extcmd_context *ctxt, int argc, char **args); /* The argcmd description. */ @@ -38,11 +40,21 @@ struct grub_extcmd const struct grub_arg_option *options; void *data; - - struct grub_arg_list *state; }; typedef struct grub_extcmd *grub_extcmd_t; +/* Command context for each instance of execution. */ +struct grub_extcmd_context +{ + struct grub_extcmd *extcmd; + + struct grub_arg_list *state; + + /* Script parameters, if any. */ + struct grub_script **script_params; +}; +typedef struct grub_extcmd_context *grub_extcmd_context_t; + grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, unsigned flags, @@ -52,4 +64,8 @@ grub_extcmd_t grub_register_extcmd (const char *name, void grub_unregister_extcmd (grub_extcmd_t cmd); +grub_err_t +grub_extcmd_dispatcher (struct grub_command *cmd, int argc, char **args, + struct grub_script **scripts); + #endif /* ! GRUB_EXTCMD_HEADER */ diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 87fb26f93..a17dcca70 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -72,6 +72,7 @@ struct grub_script_argv { unsigned argc; char **args; + struct grub_script **scripts; }; /* A complete argument. It consists of a list of one or more `struct @@ -230,6 +231,8 @@ void grub_script_argv_free (struct grub_script_argv *argv); int grub_script_argv_next (struct grub_script_argv *argv); int grub_script_argv_append (struct grub_script_argv *argv, const char *s); int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); +int grub_script_argv_script_append (struct grub_script_argv *argv, + struct grub_script *s); struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index 3c7fe2fee..c92712562 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -946,10 +946,10 @@ grub_bsd_parse_flags (const struct grub_arg_list *state, } static grub_err_t -grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { kernel_type = KERNEL_TYPE_FREEBSD; - bootflags = grub_bsd_parse_flags (cmd->state, freebsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, freebsd_flags); if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) { @@ -1009,16 +1009,16 @@ grub_cmd_freebsd (grub_extcmd_t cmd, int argc, char *argv[]) } static grub_err_t -grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_openbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { grub_uint32_t bootdev; kernel_type = KERNEL_TYPE_OPENBSD; - bootflags = grub_bsd_parse_flags (cmd->state, openbsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, openbsd_flags); - if (cmd->state[OPENBSD_ROOT_ARG].set) + if (ctxt->state[OPENBSD_ROOT_ARG].set) { - const char *arg = cmd->state[OPENBSD_ROOT_ARG].arg; + const char *arg = ctxt->state[OPENBSD_ROOT_ARG].arg; int unit, part; if (*(arg++) != 'w' || *(arg++) != 'd') return grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -1049,16 +1049,16 @@ grub_cmd_openbsd (grub_extcmd_t cmd, int argc, char *argv[]) } static grub_err_t -grub_cmd_netbsd (grub_extcmd_t cmd, int argc, char *argv[]) +grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) { kernel_type = KERNEL_TYPE_NETBSD; - bootflags = grub_bsd_parse_flags (cmd->state, netbsd_flags); + bootflags = grub_bsd_parse_flags (ctxt->state, netbsd_flags); if (grub_bsd_load (argc, argv) == GRUB_ERR_NONE) { grub_loader_set (grub_netbsd_boot, grub_bsd_unload, 1); - if (cmd->state[NETBSD_ROOT_ARG].set) - netbsd_root = grub_strdup (cmd->state[NETBSD_ROOT_ARG].arg); + if (ctxt->state[NETBSD_ROOT_ARG].set) + netbsd_root = grub_strdup (ctxt->state[NETBSD_ROOT_ARG].arg); } return grub_errno; diff --git a/loader/xnu.c b/loader/xnu.c index 8f1d0c641..5c7bd50be 100644 --- a/loader/xnu.c +++ b/loader/xnu.c @@ -1368,15 +1368,15 @@ static const struct grub_arg_option xnu_splash_cmd_options[] = }; static grub_err_t -grub_cmd_xnu_splash (grub_extcmd_t cmd, +grub_cmd_xnu_splash (grub_extcmd_context_t ctxt, int argc, char *args[]) { grub_err_t err; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); - if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && - grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, + if (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && + grub_strcmp (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, "stretch") == 0) grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH; else diff --git a/script/argv.c b/script/argv.c index 69322779d..f962556d8 100644 --- a/script/argv.c +++ b/script/argv.c @@ -52,8 +52,17 @@ grub_script_argv_free (struct grub_script_argv *argv) grub_free (argv->args); } + if (argv->scripts) + { + for (i = 0; i < argv->argc; i++) + grub_script_free (argv->scripts[i]); + + grub_free (argv->scripts); + } + argv->argc = 0; argv->args = 0; + argv->scripts = 0; } /* Prepare for next argc. */ @@ -61,20 +70,33 @@ int grub_script_argv_next (struct grub_script_argv *argv) { char **p = argv->args; + struct grub_script **q = argv->scripts; - if (argv->args && argv->args[argv->argc - 1] == 0) + if (argv->args && argv->argc && argv->args[argv->argc - 1] == 0) return 0; p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); if (! p) return 1; + q = grub_realloc (q, round_up_exp ((argv->argc + 2) * sizeof (struct grub_script *))); + if (! q) + { + grub_free (p); + return 1; + } + argv->argc++; argv->args = p; + argv->scripts = q; if (argv->argc == 1) - argv->args[0] = 0; + { + argv->args[0] = 0; + argv->scripts[0] = 0; + } argv->args[argv->argc] = 0; + argv->scripts[argv->argc] = 0; return 0; } @@ -100,6 +122,25 @@ grub_script_argv_append (struct grub_script_argv *argv, const char *s) return 0; } +/* Append grub_script `s' as the last argument. */ +int +grub_script_argv_script_append (struct grub_script_argv *argv, + struct grub_script *script) +{ + struct grub_script *s; + + s = grub_malloc (sizeof (*s)); + if (! s) + return 1; + + if (argv->scripts[argv->argc - 1]) + grub_script_free (argv->scripts[argv->argc - 1]); + + *s = *script; + argv->scripts[argv->argc - 1] = s; + return 0; +} + /* Split `s' and append words as multiple arguments. */ int grub_script_argv_split_append (struct grub_script_argv *argv, char *s) diff --git a/script/execute.c b/script/execute.c index 691b3c893..0ac42cf4a 100644 --- a/script/execute.c +++ b/script/execute.c @@ -25,6 +25,7 @@ #include #include #include +#include /* Max digits for a char is 3 (0xFF is 255), similarly for an int it is sizeof (int) * 3, and one extra for a possible -ve sign. */ @@ -51,7 +52,7 @@ grub_env_special (const char *name) static char ** grub_script_env_get (const char *name, grub_script_arg_type_t type) { - struct grub_script_argv result = { 0, 0 }; + struct grub_script_argv result = { 0, 0, 0 }; if (grub_script_argv_next (&result)) goto fail; @@ -169,7 +170,7 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, int i; char **values = 0; struct grub_script_arg *arg = 0; - struct grub_script_argv result = { 0, 0 }; + struct grub_script_argv result = { 0, 0, 0 }; for (; arglist && arglist->arg; arglist = arglist->next) { @@ -196,6 +197,11 @@ grub_script_arglist_to_argv (struct grub_script_arglist *arglist, break; case GRUB_SCRIPT_ARG_TYPE_BLOCK: + if (grub_script_argv_append (&result, arg->str) || + grub_script_argv_script_append (&result, &arg->block)) + goto fail; + break; + case GRUB_SCRIPT_ARG_TYPE_TEXT: if (grub_strlen (arg->str) && grub_script_argv_append (&result, arg->str)) @@ -270,7 +276,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; /* Lookup the command. */ if (grub_script_arglist_to_argv (cmdline->arglist, &argv)) @@ -314,7 +320,14 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) /* Execute the GRUB command or function. */ if (grubcmd) - ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + { + if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) && + (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD)) + ret = grub_extcmd_dispatcher (grubcmd, argv.argc - 1, argv.args + 1, + argv.scripts + 1); + else + ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + } else ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1); @@ -374,7 +387,7 @@ grub_script_execute_cmdfor (struct grub_script_cmd *cmd) { unsigned i; grub_err_t result; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; if (grub_script_arglist_to_argv (cmdfor->words, &argv)) @@ -416,7 +429,7 @@ grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd) { struct grub_script_cmd_menuentry *cmd_menuentry; - struct grub_script_argv argv = { 0, 0 }; + struct grub_script_argv argv = { 0, 0, 0 }; cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd; diff --git a/script/parser.y b/script/parser.y index 653e2bc84..d774ca918 100644 --- a/script/parser.y +++ b/script/parser.y @@ -164,7 +164,7 @@ block: "{" if ((p = grub_script_lexer_record_stop (state, $2))) *grub_strrchr (p, '}') = '\0'; - if (arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p)) + if ((arg = grub_script_arg_add (state, 0, GRUB_SCRIPT_ARG_TYPE_BLOCK, p))) { arg->block.cmd = $3; arg->block.mem = memory; diff --git a/script/script.c b/script/script.c index 9cee40dcb..9017a08e8 100644 --- a/script/script.c +++ b/script/script.c @@ -96,7 +96,10 @@ grub_script_free (struct grub_script *script) { if (!script) return; - grub_script_mem_free (script->mem); + + if (script->mem) + grub_script_mem_free (script->mem); + grub_free (script); } @@ -119,6 +122,9 @@ grub_script_arg_add (struct grub_parser_param *state, return arg; argpart->type = type; + argpart->block.mem = 0; + argpart->block.cmd = 0; + len = grub_strlen (str) + 1; argpart->str = grub_script_malloc (state, len); if (!argpart->str) diff --git a/term/gfxterm.c b/term/gfxterm.c index ecfe4ff3b..ffded5e6b 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -1091,11 +1091,10 @@ static const struct grub_arg_option background_image_cmd_options[] = }; static grub_err_t -grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)), - int argc, - char **args) +grub_gfxterm_background_image_cmd (grub_extcmd_context_t ctxt, + int argc, char **args) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; /* Check that we have video adapter active. */ if (grub_video_get_info(NULL) != GRUB_ERR_NONE) diff --git a/term/serial.c b/term/serial.c index 2347bb3ee..168e40bad 100644 --- a/term/serial.c +++ b/term/serial.c @@ -497,11 +497,11 @@ static struct grub_term_output grub_serial_term_output = static grub_err_t -grub_cmd_serial (grub_extcmd_t cmd, +grub_cmd_serial (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - struct grub_arg_list *state = cmd->state; + struct grub_arg_list *state = ctxt->state; struct serial_port backup_settings = serial_settings; grub_err_t hwiniterr; diff --git a/tests/lib/functional_test.c b/tests/lib/functional_test.c index 8ff08cf8a..8be6c8e89 100644 --- a/tests/lib/functional_test.c +++ b/tests/lib/functional_test.c @@ -22,7 +22,7 @@ #include static grub_err_t -grub_functional_test (struct grub_extcmd *cmd __attribute__ ((unused)), +grub_functional_test (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) {