discover/grub2: Reimplement default options
authorJeremy Kerr <jk@ozlabs.org>
Wed, 25 Sep 2013 00:37:50 +0000 (08:37 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Wed, 25 Sep 2013 03:34:26 +0000 (11:34 +0800)
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
discover/grub2/grub2.h
discover/grub2/script.c
test/parser/Makefile.am
test/parser/test-grub2-default-index.c [new file with mode: 0644]
test/parser/test-grub2-default-multiword.c [new file with mode: 0644]
test/parser/test-grub2-default.c [new file with mode: 0644]

index 4d083ae9ed18f8f8bb6cfc2d5d9582ed54a5c78e..5ee8503dbf88af6c0db0934c075faac3cf3c24db 100644 (file)
@@ -89,6 +89,7 @@ struct grub2_script {
        struct list                     symtab;
        struct discover_context         *ctx;
        struct discover_boot_option     *opt;
+       unsigned int                    n_options;
 };
 
 struct grub2_parser {
index 3f5bc236a66911fb54111a8ec7d3916c68454cca..0cf21967450efb3fbdf22c76f901c1c312b4d9d1 100644 (file)
@@ -1,6 +1,7 @@
 
 #include <sys/types.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <types/types.h>
 #include <talloc/talloc.h>
@@ -96,6 +97,24 @@ static bool is_delim(char c)
        return c == ' ' || c == '\t';
 }
 
+static bool option_is_default(struct grub2_script *script,
+               struct discover_boot_option *opt)
+{
+       unsigned int default_idx;
+       const char *var;
+       char *end;
+
+       var = script_env_get(script, "default");
+       if (!var)
+               return false;
+
+       default_idx = strtoul(var, &end, 10);
+       if (end != var && *end == '\0')
+               return default_idx == script->n_options;
+
+       return !strcmp(opt->option->name, var);
+}
+
 /* For non-double-quoted variable expansions, we may need to split the
  * variable's value into multiple argv items.
  *
@@ -333,7 +352,10 @@ int statement_menuentry_execute(struct grub2_script *script,
 
        statements_execute(script, st->statements);
 
+       opt->option->is_default = option_is_default(script, opt);
+
        discover_context_add_boot_option(script->ctx, opt);
+       script->n_options++;
        script->opt = NULL;
 
        return 0;
@@ -407,11 +429,10 @@ struct grub2_script *create_script(struct grub2_parser *parser,
 {
        struct grub2_script *script;
 
-       script = talloc(parser, struct grub2_script);
+       script = talloc_zero(parser, struct grub2_script);
 
        init_env(script);
        script->ctx = ctx;
-       script->opt = NULL;
 
        list_init(&script->symtab);
        register_builtins(script);
index fbf9c50af1a53058aca99d2761c983edfd50d580..8159bd677647ef9186323e521add3e2204764435 100644 (file)
@@ -28,6 +28,9 @@ LDADD = $(top_builddir)/lib/libpbcore.la libtest.ro
 TESTS = \
        test-null \
        test-grub2-single \
+       test-grub2-default \
+       test-grub2-default-index \
+       test-grub2-default-multiword \
        test-grub2-multiple-resolve \
        test-grub2-single-line-if \
        test-grub2-f18-ppc64 \
diff --git a/test/parser/test-grub2-default-index.c b/test/parser/test-grub2-default-index.c
new file mode 100644 (file)
index 0000000..78835cd
--- /dev/null
@@ -0,0 +1,34 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+set default=1
+menuentry 'test-option-0' {
+       linux   /vmlinux.0
+}
+menuentry 'test-option-1' {
+       linux   /vmlinux.1
+}
+menuentry 'test-option-2' {
+       linux   /vmlinux.2
+}
+#endif
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded(test);
+       test_run_parser(test, "grub2");
+
+       ctx = test->ctx;
+
+       check_boot_option_count(ctx, 3);
+       opt = get_boot_option(ctx, 1);
+
+       check_name(opt, "test-option-1");
+       check_resolved_local_resource(opt->boot_image, ctx->device,
+                                       "/vmlinux.1");
+       check_is_default(opt);
+}
diff --git a/test/parser/test-grub2-default-multiword.c b/test/parser/test-grub2-default-multiword.c
new file mode 100644 (file)
index 0000000..f7993fe
--- /dev/null
@@ -0,0 +1,30 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+set default="Multiple word option"
+menuentry 'Non-defalt option' {
+       linux /vmlinux.non-default
+}
+menuentry 'Multiple word option' {
+       linux   /vmlinux
+}
+#endif
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded(test);
+       test_run_parser(test, "grub2");
+
+       ctx = test->ctx;
+
+       check_boot_option_count(ctx, 2);
+
+       opt = get_boot_option(ctx, 1);
+       check_name(opt, "Multiple word option");
+       check_resolved_local_resource(opt->boot_image, ctx->device, "/vmlinux");
+       check_is_default(opt);
+}
diff --git a/test/parser/test-grub2-default.c b/test/parser/test-grub2-default.c
new file mode 100644 (file)
index 0000000..b3359d0
--- /dev/null
@@ -0,0 +1,27 @@
+
+#include "parser-test.h"
+
+#if 0 /* PARSER_EMBEDDED_CONFIG */
+set default="test-option"
+menuentry 'test-option' {
+       linux   /vmlinux
+}
+#endif
+
+void run_test(struct parser_test *test)
+{
+       struct discover_boot_option *opt;
+       struct discover_context *ctx;
+
+       test_read_conf_embedded(test);
+       test_run_parser(test, "grub2");
+
+       ctx = test->ctx;
+
+       check_boot_option_count(ctx, 1);
+       opt = get_boot_option(ctx, 0);
+
+       check_name(opt, "test-option");
+       check_resolved_local_resource(opt->boot_image, ctx->device, "/vmlinux");
+       check_is_default(opt);
+}