X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fgrub2%2Fscript.c;h=c910bf8bc1a28bf86901459b11d7a99ad059bc35;hp=0618297784499f5d60ac0e597e03ff8602ee05d7;hb=53e0f3ef35ac694220dce135f01a4f736cbd1c19;hpb=1b272c7d47390077eee0a0638329b1a7df521329 diff --git a/discover/grub2/script.c b/discover/grub2/script.c index 0618297..c910bf8 100644 --- a/discover/grub2/script.c +++ b/discover/grub2/script.c @@ -103,7 +103,7 @@ static bool is_delim(char c) } static bool option_is_default(struct grub2_script *script, - struct discover_boot_option *opt, const char *id) + struct discover_boot_option *opt, const char *id) { unsigned int default_idx; const char *var; @@ -117,12 +117,10 @@ static bool option_is_default(struct grub2_script *script, if (end != var && *end == '\0') return default_idx == script->n_options; - /* if we don't have an explicit id for this option, fall back to - * the name */ - if (!id) - id = opt->option->name; + if (id && !strcmp(id, var)) + return true; - return !strcmp(id, var); + return !strcmp(opt->option->name, var); } static void append_text_to_current_arg(struct grub2_argv *argv, @@ -227,7 +225,7 @@ static void process_expansions(struct grub2_script *script, } /* we may have allocated an extra argv element but not populated it */ - if (!argv->argv[argv->argc - 1]) + if (argv->argv && !argv->argv[argv->argc - 1]) argv->argc--; } @@ -309,7 +307,7 @@ int statement_if_execute(struct grub2_script *script, { struct grub2_statement_if *st = to_stmt_if(statement); struct grub2_statement *conditional; - bool executed; + bool executed = false; int rc = 0; list_for_each_entry(&st->conditionals->list, conditional, list) { @@ -364,7 +362,7 @@ int statement_menuentry_execute(struct grub2_script *script, opt->option->is_default = option_is_default(script, opt, id); - discover_context_add_boot_option(script->ctx, opt); + list_add_tail(&script->options, &opt->list); script->n_options++; script->opt = NULL; @@ -379,8 +377,8 @@ static int function_invoke(struct grub2_script *script, int i; /* set positional parameters */ - for (i = 0; i < argc; i++) { - name = talloc_asprintf(script, "$%d", i); + for (i = 1; i < argc; i++) { + name = talloc_asprintf(script, "%d", i); script_env_set(script, name, argv[i]); } @@ -463,11 +461,46 @@ void script_register_function(struct grub2_script *script, list_add(&script->symtab, &entry->list); } +static void set_fallback_default(struct grub2_script *script) +{ + struct discover_boot_option *opt, *first = NULL; + bool have_default = false; + + list_for_each_entry(&script->options, opt, list) { + if (!first) + first = opt; + have_default = have_default || opt->option->is_default; + } + + if (!have_default && first) { + const char *env = script_env_get(script, "default"); + + pb_log("grub: no explicit default (env default=%s), " + "falling back to first option (%s)\n", + env ?: "unset", first->option->name); + + first->option->is_default = true; + } +} void script_execute(struct grub2_script *script) { + struct discover_boot_option *opt, *tmp; + + if (!script) + return; + init_env(script); statements_execute(script, script->statements); + + set_fallback_default(script); + + list_for_each_entry_safe(&script->options, opt, tmp, list) + discover_context_add_boot_option(script->ctx, opt); + + /* Our option list will be invalid, as we've added all options to the + * discover context */ + list_init(&script->options); } struct grub2_script *create_script(struct grub2_parser *parser, @@ -480,6 +513,7 @@ struct grub2_script *create_script(struct grub2_parser *parser, script->ctx = ctx; list_init(&script->symtab); + list_init(&script->options); register_builtins(script); return script;