From: Jeremy Kerr Date: Fri, 27 Sep 2013 06:21:53 +0000 (+0800) Subject: discover/grub2: Implement load_env X-Git-Tag: v1.0.0~402 X-Git-Url: https://git.ozlabs.org/?p=petitboot;a=commitdiff_plain;h=fcbb46482c413192756ce865a7336c5638fda6d3 discover/grub2: Implement load_env Use the new parser_request_file API to access the GRUB environment block. Signed-off-by: Jeremy Kerr --- diff --git a/discover/grub2/Makefile.am b/discover/grub2/Makefile.am index 71f3282..902f94f 100644 --- a/discover/grub2/Makefile.am +++ b/discover/grub2/Makefile.am @@ -30,6 +30,7 @@ grub2-parser.ro$(EXEEXT): $(grub2_parser_ro_OBJECTS) grub2_parser_ro_SOURCES = \ builtins.c \ + env.c \ grub2.h \ grub2.c \ lexer.l \ diff --git a/discover/grub2/builtins.c b/discover/grub2/builtins.c index 7a5d867..71ae61a 100644 --- a/discover/grub2/builtins.c +++ b/discover/grub2/builtins.c @@ -256,6 +256,10 @@ static int builtin_nop(struct grub2_script *script __attribute__((unused)), return 0; } +extern int builtin_load_env(struct grub2_script *script, + void *data __attribute__((unused)), + int argc, char *argv[]); + static struct { const char *name; grub2_function fn; @@ -296,6 +300,10 @@ static struct { .name = "false", .fn = builtin_false, }, + { + .name = "load_env", + .fn = builtin_load_env, + }, }; static const char *nops[] = { diff --git a/discover/grub2/env.c b/discover/grub2/env.c new file mode 100644 index 0000000..e28c9fe --- /dev/null +++ b/discover/grub2/env.c @@ -0,0 +1,107 @@ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "grub2.h" + +static const char *default_envfile = "grubenv"; +static const char *signature = "# GRUB Environment Block\n"; + +static int parse_buf_to_env(struct grub2_script *script, void *buf, int len) +{ + char *tmp, *line, *sep; + int siglen; + + siglen = strlen(signature); + + if (len < siglen) { + pb_log("grub environment block too small\n"); + return -1; + } + + if (memcmp(buf, signature, siglen)) { + pb_log("grub environment block has invalid signature\n"); + return -1; + } + + buf += siglen; + + for (line = strtok_r(buf, "\n", &tmp); line; + line = strtok_r(NULL, "\n", &tmp)) { + + if (*line == '#') + continue; + + sep = strchr(line, '='); + if (!sep) + continue; + if (sep == line) + continue; + + *sep = '\0'; + script_env_set(script, line, sep + 1); + } + + return 0; +} + +int builtin_load_env(struct grub2_script *script, + void *data __attribute__((unused)), + int argc, char *argv[]); + +int builtin_load_env(struct grub2_script *script, + void *data __attribute__((unused)), + int argc, char *argv[]) +{ + struct discover_device *dev = script->ctx->device; + const char *envfile; + char *buf, *envpath; + int rc, len; + + /* we only support local filesystems */ + if (!dev->mounted) { + pb_log("load_env: can't load from a non-mounted device (%s)\n", + dev->device->id); + return -1; + } + + if (argc == 3 && !strcmp(argv[1], "-f")) + envfile = argv[2]; + else + envfile = default_envfile; + + envpath = talloc_asprintf(script, "%s/%s", + script_env_get(script, "prefix") ? : "", + envfile); + + rc = parser_request_file(script->ctx, dev, envpath, &buf, &len); + + if (!rc) + rc = parse_buf_to_env(script, buf, len); + + talloc_free(buf); + + return 0; +} + +int builtin_save_env(struct grub2_script *script, + void *data __attribute__((unused)), + int argc, char *argv[]); + +int builtin_save_env(struct grub2_script *script __attribute__((unused)), + void *data __attribute__((unused)), + int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + /* todo: save */ + return 0; +} + diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am index e7146c5..165b9ae 100644 --- a/test/parser/Makefile.am +++ b/test/parser/Makefile.am @@ -33,6 +33,7 @@ TESTS = \ test-grub2-default-multiword \ test-grub2-multiple-resolve \ test-grub2-single-line-if \ + test-grub2-load-env \ test-grub2-f18-ppc64 \ test-grub2-ubuntu-13_04-x86 \ test-grub2-lexer-error \ diff --git a/test/parser/test-grub2-load-env.c b/test/parser/test-grub2-load-env.c new file mode 100644 index 0000000..2f4e96e --- /dev/null +++ b/test/parser/test-grub2-load-env.c @@ -0,0 +1,32 @@ + +#include "parser-test.h" + +#if 0 /* PARSER_EMBEDDED_CONFIG */ +load_env +menuentry 'Linux' { + linux $kernel +} +#endif + +void run_test(struct parser_test *test) +{ + struct discover_boot_option *opt; + struct discover_context *ctx; + + test_add_file_string(test, test->ctx->device, + "/boot/grub/grubenv", + "# GRUB Environment Block\n" + "kernel=vmlinux-from-env\n"); + + 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, "Linux"); + check_resolved_local_resource(opt->boot_image, ctx->device, + "/vmlinux-from-env"); +}