]> git.ozlabs.org Git - petitboot/blobdiff - discover/grub2/blscfg.c
docker: Add signed boot dependencies
[petitboot] / discover / grub2 / blscfg.c
index a1076b9db27b5002e2ba984779e881ae092170ad..d4754aa363dfa0812d2feb9b7ced5be6e03b7aa9 100644 (file)
@@ -2,6 +2,7 @@
 #define _GNU_SOURCE
 
 #include <assert.h>
+#include <ctype.h>
 #include <stdlib.h>
 #include <string.h>
 #include <dirent.h>
 #include "discover/parser-conf.h"
 #include "discover/parser.h"
 
-#define BLS_DIR "/loader/entries"
+static const char *const bls_dirs[] = {
+       "/loader/entries",
+       "/boot/loader/entries",
+       NULL
+};
 
 struct bls_state {
        struct discover_boot_option *opt;
@@ -30,54 +35,106 @@ struct bls_state {
        const char *dtb;
 };
 
+static char *field_append(struct bls_state *state, int type, char *buffer,
+                         char *start, char *end)
+{
+       char *temp = talloc_strndup(state, start, end - start + 1);
+       const char *field = temp;
+
+       if (type == GRUB2_WORD_VAR) {
+               field = script_env_get(state->script, temp);
+               if (!field)
+                       return buffer;
+       }
+
+       if (!buffer)
+               buffer = talloc_strdup(state->opt, field);
+       else
+               buffer = talloc_asprintf_append(buffer, "%s", field);
+
+       return buffer;
+}
+
+static char *expand_field(struct bls_state *state, char *value)
+{
+       char *buffer = NULL;
+       char *start = value;
+       char *end = value;
+       int type = GRUB2_WORD_TEXT;
+
+       while (*value) {
+               if (*value == '$') {
+                       if (start != end) {
+                               buffer = field_append(state, type, buffer,
+                                                     start, end);
+                               if (!buffer)
+                                       return NULL;
+                       }
+
+                       type = GRUB2_WORD_VAR;
+                       start = value + 1;
+               } else if (type == GRUB2_WORD_VAR) {
+                       if (!isalnum(*value) && *value != '_') {
+                               buffer = field_append(state, type, buffer,
+                                                     start, end);
+                               type = GRUB2_WORD_TEXT;
+                               start = value;
+                       }
+               }
+
+               end = value;
+               value++;
+       }
+
+       if (start != end) {
+               buffer = field_append(state, type, buffer,
+                                     start, end);
+               if (!buffer)
+                       return NULL;
+       }
+
+       return buffer;
+}
+
 static void bls_process_pair(struct conf_context *conf, const char *name,
                             char *value)
 {
        struct bls_state *state = conf->parser_info;
        struct discover_boot_option *opt = state->opt;
        struct boot_option *option = opt->option;
-       const char *boot_args;
 
        if (streq(name, "title")) {
-               state->title = talloc_strdup(state, value);
+               state->title = expand_field(state, value);
                return;
        }
 
        if (streq(name, "version")) {
-               state->version = talloc_strdup(state, value);
+               state->version = expand_field(state, value);
                return;
        }
 
        if (streq(name, "machine-id")) {
-               state->machine_id = talloc_strdup(state, value);
+               state->machine_id = expand_field(state, value);
                return;
        }
 
        if (streq(name, "linux")) {
-               state->image = talloc_strdup(state, value);
+               state->image = expand_field(state, value);
                return;
        }
 
        if (streq(name, "initrd")) {
-               state->initrd = talloc_strdup(state, value);
+               state->initrd = expand_field(state, value);
                return;
        }
 
        if (streq(name, "devicetree")) {
-               state->dtb = talloc_strdup(state, value);
+               state->dtb = expand_field(state, value);
                return;
        }
 
        if (streq(name, "options")) {
-               if (value[0] == '$') {
-                       boot_args = script_env_get(state->script, value + 1);
-                       if (!boot_args)
-                               return;
-
-                       option->boot_args = talloc_strdup(opt, boot_args);
-               } else {
-                       option->boot_args = talloc_strdup(opt, value);
-               }
+               option->boot_args = expand_field(state, value);
                return;
        }
 }
@@ -148,6 +205,12 @@ static void bls_finish(struct conf_context *conf)
                opt->dtb = create_grub2_resource(opt, conf->dc->device,
                                                 root, state->dtb);
 
+       char* args_sigfile_default = talloc_asprintf(opt,
+               "%s.cmdline.sig", state->image);
+       opt->args_sig_file = create_grub2_resource(opt, conf->dc->device,
+                                               root, args_sigfile_default);
+       talloc_free(args_sigfile_default);
+
        option->is_default = option_is_default(state, option);
 
        list_add_tail(&state->script->options, &opt->list);
@@ -189,8 +252,10 @@ int builtin_blscfg(struct grub2_script *script,
        struct conf_context *conf;
        struct bls_state *state;
        char *buf, *filename;
+       const char * const *dir;
        const char *blsdir;
        int n, len, rc = -1;
+       struct stat statbuf;
 
        conf = talloc_zero(dc, struct conf_context);
        if (!conf)
@@ -203,7 +268,17 @@ int builtin_blscfg(struct grub2_script *script,
 
        blsdir = script_env_get(script, "blsdir");
        if (!blsdir)
-               blsdir = BLS_DIR;
+               for (dir = bls_dirs; *dir; dir++)
+                       if (!parser_stat_path(dc, dc->device, *dir, &statbuf)) {
+                               blsdir = *dir;
+                               break;
+                       }
+
+       if (!blsdir) {
+               device_handler_status_dev_info(dc->handler, dc->device,
+                                              _("BLS directory wasn't found"));
+               goto err;
+       }
 
        n = parser_scandir(dc, blsdir, &bls_entries, bls_filter, bls_sort);
        if (n <= 0)
@@ -243,7 +318,7 @@ int builtin_blscfg(struct grub2_script *script,
        if (n > 0) {
                device_handler_status_dev_info(dc->handler, dc->device,
                                               _("Scanning %s failed"),
-                                              BLS_DIR);
+                                              blsdir);
                do {
                        free(bls_entries[n]);
                } while (n-- > 0);