diff options
-rw-r--r-- | discover/grub2/grub2.h | 1 | ||||
-rw-r--r-- | discover/grub2/script.c | 35 | ||||
-rw-r--r-- | test/parser/Makefile.am | 2 | ||||
-rw-r--r-- | test/parser/test-grub2-implicit-default-invalid.c | 26 | ||||
-rw-r--r-- | test/parser/test-grub2-implicit-default-unset.c | 25 |
5 files changed, 88 insertions, 1 deletions
diff --git a/discover/grub2/grub2.h b/discover/grub2/grub2.h index 0a89324..68176fb 100644 --- a/discover/grub2/grub2.h +++ b/discover/grub2/grub2.h @@ -98,6 +98,7 @@ struct grub2_script { struct discover_boot_option *opt; const char *filename; unsigned int n_options; + struct list options; }; struct grub2_parser { diff --git a/discover/grub2/script.c b/discover/grub2/script.c index 36f73b2..f521681 100644 --- a/discover/grub2/script.c +++ b/discover/grub2/script.c @@ -364,7 +364,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; @@ -463,11 +463,43 @@ 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; + 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 +512,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; diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am index 1bb45e8..d69ca7f 100644 --- a/test/parser/Makefile.am +++ b/test/parser/Makefile.am @@ -21,6 +21,8 @@ parser_TESTS = \ test/parser/test-grub2-if-formats \ test/parser/test-grub2-default-index \ test/parser/test-grub2-default-multiword \ + test/parser/test-grub2-implicit-default-unset \ + test/parser/test-grub2-implicit-default-invalid \ test/parser/test-grub2-multiple-resolve \ test/parser/test-grub2-multiple-id \ test/parser/test-grub2-single-line-if \ diff --git a/test/parser/test-grub2-implicit-default-invalid.c b/test/parser/test-grub2-implicit-default-invalid.c new file mode 100644 index 0000000..72902db --- /dev/null +++ b/test/parser/test-grub2-implicit-default-invalid.c @@ -0,0 +1,26 @@ + +#include "parser-test.h" + +#if 0 /* PARSER_EMBEDDED_CONFIG */ +default=missing +menuentry 'test.1' { + linux /vmlinux +} +menuentry 'test.2' { + linux /vmlinux +} +#endif + +void run_test(struct parser_test *test) +{ + struct discover_boot_option *opt; + + test_read_conf_embedded(test, "/grub2/grub.cfg"); + test_run_parser(test, "grub2"); + + check_boot_option_count(test->ctx, 2); + opt = get_boot_option(test->ctx, 0); + + check_name(opt, "test.1"); + check_is_default(opt); +} diff --git a/test/parser/test-grub2-implicit-default-unset.c b/test/parser/test-grub2-implicit-default-unset.c new file mode 100644 index 0000000..ecc4c00 --- /dev/null +++ b/test/parser/test-grub2-implicit-default-unset.c @@ -0,0 +1,25 @@ + +#include "parser-test.h" + +#if 0 /* PARSER_EMBEDDED_CONFIG */ +menuentry 'test.1' { + linux /vmlinux +} +menuentry 'test.2' { + linux /vmlinux +} +#endif + +void run_test(struct parser_test *test) +{ + struct discover_boot_option *opt; + + test_read_conf_embedded(test, "/grub2/grub.cfg"); + test_run_parser(test, "grub2"); + + check_boot_option_count(test->ctx, 2); + opt = get_boot_option(test->ctx, 0); + + check_name(opt, "test.1"); + check_is_default(opt); +} |