summaryrefslogtreecommitdiffstats
path: root/discover/grub2
diff options
context:
space:
mode:
authorJavier Martinez Canillas <javierm@redhat.com>2018-06-12 12:18:34 +0200
committerSamuel Mendoza-Jonas <sam@mendozajonas.com>2018-06-18 10:56:33 +1000
commit78a98b9ebc789d9c9c701af95e65292d768eee59 (patch)
tree9a3664761d2a27c65572053ffb9380071c8cd1d2 /discover/grub2
parent6d06f0dbe1195cd8be7d3c54d02012ff16466d0c (diff)
downloadtalos-petitboot-78a98b9ebc789d9c9c701af95e65292d768eee59.tar.gz
talos-petitboot-78a98b9ebc789d9c9c701af95e65292d768eee59.zip
discover/grub: Improve BLS grub environment variables expansion
The fields from a BootLoaderSpec file can contain environment variables, in GRUB 2 these are show verbatim and are evaluated later when an entry is selected. But on Petitboot these have to be expanded before creating the GRUB 2 resources and show in the UI the values after the evaluation. The current blscfg handler had a very limited support for variables, it only had support for the options field and also didn't take into account that variables could be mixed with literal values. So for example the following fields were not expanded correctly: linux $bootprefix/vmlinuz options $kernelopts foo=bar options foo=bar $kernelopts options $kernelopts $debugopts Also change some of the tests to cover mixing variables and literals. Signed-off-by: Javier Martinez Canillas <javierm@redhat.com> Signed-off-by: Samuel Mendoza-Jonas <sam@mendozajonas.com>
Diffstat (limited to 'discover/grub2')
-rw-r--r--discover/grub2/blscfg.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/discover/grub2/blscfg.c b/discover/grub2/blscfg.c
index a381306..d4754aa 100644
--- a/discover/grub2/blscfg.c
+++ b/discover/grub2/blscfg.c
@@ -2,6 +2,7 @@
#define _GNU_SOURCE
#include <assert.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
@@ -34,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;
}
}
OpenPOWER on IntegriCloud