]> git.ozlabs.org Git - petitboot/blobdiff - discover/grub2/script.c
discover/udev: Don't call udev_set_log_fn()
[petitboot] / discover / grub2 / script.c
index bfca607e1bf3c9266240d6b40873daee94faf56f..48c963e7549c1982d45d1143895be4f301132e55 100644 (file)
@@ -19,6 +19,8 @@
        container_of(stmt, struct grub2_statement_menuentry, st)
 #define to_stmt_function(stmt) \
        container_of(stmt, struct grub2_statement_function, st)
+#define to_stmt_for(stmt) \
+       container_of(stmt, struct grub2_statement_for, st)
 #define to_stmt_conditional(stmt) \
        container_of(stmt, struct grub2_statement_conditional, st)
 
@@ -307,7 +309,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) {
@@ -362,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;
 
@@ -378,7 +380,7 @@ static int function_invoke(struct grub2_script *script,
 
        /* set positional parameters */
        for (i = 0; i < argc; i++) {
-               name = talloc_asprintf(script, "$%d", i);
+               name = talloc_asprintf(script, "%d", i);
                script_env_set(script, name, argv[i]);
        }
 
@@ -401,6 +403,27 @@ int statement_function_execute(struct grub2_script *script,
        return 0;
 }
 
+int statement_for_execute(struct grub2_script *script,
+               struct grub2_statement *statement)
+{
+       struct grub2_statement_for *st = to_stmt_for(statement);
+       const char *varname;
+       int i, rc = 0;
+
+       if (st->var->type == GRUB2_WORD_VAR)
+               expand_var(script, st->var);
+       varname = st->var->text;
+
+       process_expansions(script, st->list);
+
+       for (i = 0; i < st->list->argc; ++i) {
+               script_env_set(script, varname, st->list->argv[i]);
+               rc = statements_execute(script, st->body);
+       }
+
+       return rc;
+}
+
 static void init_env(struct grub2_script *script)
 {
        struct env_entry *env;
@@ -440,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,
@@ -457,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;