X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fgrub2%2Fscript.c;h=75b8aaaae474fc6348215dea26d7e963f31e4562;hp=5fb13aa4f0979e24451471df8db627c4802ee26b;hb=57293e2111fcba58a7b399cb1332012414bffeeb;hpb=bbf4805d8750a363b1ec78831ad085b8c56a1c99 diff --git a/discover/grub2/script.c b/discover/grub2/script.c index 5fb13aa..75b8aaa 100644 --- a/discover/grub2/script.c +++ b/discover/grub2/script.c @@ -1,7 +1,9 @@ #include #include +#include +#include #include #include @@ -9,6 +11,8 @@ #define to_stmt_simple(stmt) \ container_of(stmt, struct grub2_statement_simple, st) +#define to_stmt_block(stmt) \ + container_of(stmt, struct grub2_statement_block, st) #define to_stmt_if(stmt) \ container_of(stmt, struct grub2_statement_if, st) #define to_stmt_menuentry(stmt) \ @@ -31,6 +35,8 @@ struct grub2_symtab_entry { struct list_item list; }; +static const char *default_prefix = "/boot/grub"; + static struct grub2_symtab_entry *script_lookup_function( struct grub2_script *script, const char *name) { @@ -94,6 +100,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. * @@ -233,6 +257,7 @@ int statement_simple_execute(struct grub2_script *script, { struct grub2_statement_simple *st = to_stmt_simple(statement); struct grub2_symtab_entry *entry; + char *pos; int rc; if (!st->argv) @@ -243,9 +268,20 @@ int statement_simple_execute(struct grub2_script *script, if (!st->argv->argc) return 0; + /* is this a var=value assignment? */ + pos = strchr(st->argv->argv[0], '='); + if (pos) { + char *name, *value; + name = st->argv->argv[0]; + name = talloc_strndup(st, name, pos - name); + value = pos + 1; + script_env_set(script, name, value); + return 0; + } + entry = script_lookup_function(script, st->argv->argv[0]); if (!entry) { - fprintf(stderr, "undefined function '%s'\n", st->argv->argv[0]); + pb_log("grub2: undefined function '%s'\n", st->argv->argv[0]); return 1; } @@ -254,6 +290,13 @@ int statement_simple_execute(struct grub2_script *script, return rc; } +int statement_block_execute(struct grub2_script *script, + struct grub2_statement *statement) +{ + struct grub2_statement_block *st = to_stmt_block(statement); + return statements_execute(script, st->statements); +} + /* returns 0 if the statement was executed, 1 otherwise */ static int statement_conditional_execute(struct grub2_script *script, struct grub2_statement *statement, bool *executed) @@ -312,7 +355,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; @@ -357,7 +403,7 @@ static void init_env(struct grub2_script *script) env = talloc(script, struct env_entry); env->name = talloc_strdup(env, "prefix"); - env->value = talloc_strdup(env, "/"); + env->value = talloc_strdup(env, default_prefix); list_add(&script->environment, &env->list); } @@ -386,11 +432,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);