<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p>It also just occurred to me that the BLS filename itself minus
the '.conf' extension should also be used as a comparison for the
is_default check from this line in the spec:</p>
<p>
<blockquote type="cite"><span style="color: rgb(0, 0, 0);
font-family: "Times New Roman"; font-size: 16.16px;
font-style: normal; font-variant-ligatures: normal;
font-variant-caps: normal; font-weight: 400; letter-spacing:
normal; orphans: 2; text-align: start; text-indent: 0px;
text-transform: none; white-space: normal; widows: 2;
word-spacing: 0px; -webkit-text-stroke-width: 0px;
background-color: rgb(255, 255, 255); text-decoration-style:
initial; text-decoration-color: initial; display: inline
!important; float: none;">The file name of the file is used
for identification of the boot item, but shall never be
presented to the user in the UI.</span></blockquote>
And possibly even used as the basis for option->id rather than
state->image?<br>
</p>
<br>
<div class="moz-cite-prefix">On 21/03/18 08:45, Brett Grandbois
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:3e40d783-f9e7-e798-819f-859f0c4ab123@opengear.com">[This
sender failed our fraud detection checks and may not be who they
appear to be. Learn about spoofing at
<a class="moz-txt-link-freetext" href="http://aka.ms/LearnAboutSpoofing">http://aka.ms/LearnAboutSpoofing</a>]
<br>
<br>
Tested it out and it works. I just noticed however that there is
no
<br>
support for default in it so somewhere in bls_finish it would be
nice to
<br>
have an option->is_default check. The concept of index doesn't
seem to
<br>
apply in BLS like it does in a list of menuentries so probably the
best
<br>
way to go is to do the default env comparison on title or
machine_id if
<br>
either exist.
<br>
<br>
I know I originally suggested it, but looking at the
implementation I
<br>
can see that having option->name be a mash up of machine_id and
version
<br>
isn't the way to go. It looks much cleaner to just have:
<br>
<br>
if title
<br>
<br>
else if machine_id
<br>
<br>
else if version
<br>
<br>
else
<br>
<br>
<br>
which then makes the default check easy has you can do it based on
an
<br>
option->name comparison afterwards.
<br>
<br>
Brett
<br>
<br>
<br>
On 19/03/18 19:27, Javier Martinez Canillas wrote:
<br>
<blockquote type="cite">The BootLoaderSpec (BLS) defines a file
format for boot configurations,
<br>
so bootloaders can parse these files and create their boot menu
entries
<br>
by using the information provided by them [0].
<br>
<br>
This allow to configure the boot items as drop-in files in a
directory
<br>
instead of having to parse and modify a bootloader configuration
file.
<br>
<br>
The GRUB 2 bootloader provides a blscfg command that parses
these files
<br>
and creates menu entries using this information. Add support for
it.
<br>
<br>
[0]:
<a class="moz-txt-link-freetext" href="https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/">https://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/</a>
<br>
<br>
Signed-off-by: Javier Martinez Canillas
<a class="moz-txt-link-rfc2396E" href="mailto:javierm@redhat.com"><javierm@redhat.com></a>
<br>
<br>
---
<br>
<br>
Hello,
<br>
<br>
From Fedora 28 there will be an option to use BootLoaderSpec
snippets to
<br>
update GRUB's boot menu entries. So I'm posting this patch to
allow this
<br>
to also work on ppc64 machines using petitboot, instead of
grub-ieee1275.
<br>
<br>
This can be tested by creating a BLS config under
/boot/loader/entries,
<br>
for example following
/boot/loader/entries/4.15.6-300.fc27.x86_64.conf:
<br>
<br>
title Fedora (4.15.6-300.fc27.x86_64) 27 (Twenty Seven)
<br>
linux /vmlinuz-4.15.6-300.fc27.x86_64
<br>
initrd /initramfs-4.15.6-300.fc27.x86_64.img
<br>
options root=/dev/mapper/fedora-root ro rd.lvm.lv=fedora/root
rd.luks.uuid=luks-0b078909-4a1c-4a57-91b8-b9f724e86a1a
rd.lvm.lv=fedora/swap rhgb quiet LANG=en_US.UTF-8
<br>
id fedora-20180214051518-4.15.6-300.fc27.x86_64.x86_64
<br>
grub_users $grub_users
<br>
grub_arg --unrestricted
<br>
grub_class kernel
<br>
<br>
And a grub.cfg that calls the blscfg command, it could just be
the following:
<br>
<br>
blscfg
<br>
<br>
Best regards,
<br>
Javier
<br>
<br>
Changes in v3:
<br>
- Populate boot option id using the linux field instead of title
field.
<br>
- Don't fill boot option name using the optional title field,
instead
<br>
fill this from optional fields that are present in the BLS
fragment.
<br>
- Add support for the devicetree field.
<br>
<br>
Changes in v2:
<br>
- Allow optional fields, only require the linux field to be
present.
<br>
- Remove unused identifier from bls_filter() struct dirent *
param.
<br>
- Remove redundant check in builtin_blscfg() while loop.
<br>
<br>
discover/grub2/Makefile.am | 1 +
<br>
discover/grub2/blscfg.c | 221
+++++++++++++++++++++++++++
<br>
discover/grub2/builtins.c | 9 +-
<br>
discover/parser.c | 16 ++
<br>
discover/parser.h | 8 +
<br>
test/parser/Makefile.am | 3 +
<br>
test/parser/test-grub2-blscfg-multiple-bls.c | 44 ++++++
<br>
test/parser/test-grub2-blscfg-opts-config.c | 29 ++++
<br>
test/parser/test-grub2-blscfg-opts-grubenv.c | 34 +++++
<br>
test/parser/utils.c | 59 +++++++
<br>
10 files changed, 423 insertions(+), 1 deletion(-)
<br>
create mode 100644 discover/grub2/blscfg.c
<br>
create mode 100644
test/parser/test-grub2-blscfg-multiple-bls.c
<br>
create mode 100644 test/parser/test-grub2-blscfg-opts-config.c
<br>
create mode 100644
test/parser/test-grub2-blscfg-opts-grubenv.c
<br>
<br>
diff --git a/discover/grub2/Makefile.am
b/discover/grub2/Makefile.am
<br>
index 130ede88e18c..b240106d7a54 100644
<br>
--- a/discover/grub2/Makefile.am
<br>
+++ b/discover/grub2/Makefile.am
<br>
@@ -15,6 +15,7 @@
<br>
noinst_PROGRAMS += discover/grub2/grub2-parser.ro
<br>
<br>
discover_grub2_grub2_parser_ro_SOURCES = \
<br>
+ discover/grub2/blscfg.c \
<br>
discover/grub2/builtins.c \
<br>
discover/grub2/env.c \
<br>
discover/grub2/grub2.h \
<br>
diff --git a/discover/grub2/blscfg.c b/discover/grub2/blscfg.c
<br>
new file mode 100644
<br>
index 000000000000..5677aa081531
<br>
--- /dev/null
<br>
+++ b/discover/grub2/blscfg.c
<br>
@@ -0,0 +1,221 @@
<br>
+
<br>
+#define _GNU_SOURCE
<br>
+
<br>
+#include <assert.h>
<br>
+#include <stdlib.h>
<br>
+#include <string.h>
<br>
+#include <dirent.h>
<br>
+
<br>
+#include <log/log.h>
<br>
+#include <file/file.h>
<br>
+#include <talloc/talloc.h>
<br>
+#include <i18n/i18n.h>
<br>
+
<br>
+#include "grub2.h"
<br>
+#include "discover/parser-conf.h"
<br>
+#include "discover/parser.h"
<br>
+
<br>
+#define BLS_DIR "/loader/entries"
<br>
+
<br>
+struct bls_state {
<br>
+ struct discover_boot_option *opt;
<br>
+ struct grub2_script *script;
<br>
+ const char *filename;
<br>
+ const char *title;
<br>
+ const char *version;
<br>
+ const char *machine_id;
<br>
+ const char *image;
<br>
+ const char *initrd;
<br>
+ const char *dtb;
<br>
+};
<br>
+
<br>
+static void bls_process_pair(struct conf_context *conf, const
char *name,
<br>
+ char *value)
<br>
+{
<br>
+ struct bls_state *state = conf->parser_info;
<br>
+ struct discover_boot_option *opt = state->opt;
<br>
+ struct boot_option *option = opt->option;
<br>
+ const char *boot_args;
<br>
+
<br>
+ if (streq(name, "title")) {
<br>
+ state->title = talloc_strdup(state, value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "version")) {
<br>
+ state->version = talloc_strdup(state, value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "machine-id")) {
<br>
+ state->machine_id = talloc_strdup(state,
value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "linux")) {
<br>
+ state->image = talloc_strdup(state, value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "initrd")) {
<br>
+ state->initrd = talloc_strdup(state, value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "devicetree")) {
<br>
+ state->dtb = talloc_strdup(state, value);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ if (streq(name, "options")) {
<br>
+ if (value[0] == '$') {
<br>
+ boot_args =
script_env_get(state->script, value + 1);
<br>
+ if (!boot_args)
<br>
+ return;
<br>
+
<br>
+ option->boot_args = talloc_strdup(opt,
boot_args);
<br>
+ } else {
<br>
+ option->boot_args = talloc_strdup(opt,
value);
<br>
+ }
<br>
+ return;
<br>
+ }
<br>
+}
<br>
+
<br>
+static void bls_finish(struct conf_context *conf)
<br>
+{
<br>
+ struct discover_device *dev = conf->dc->device;
<br>
+ struct bls_state *state = conf->parser_info;
<br>
+ struct discover_context *dc = conf->dc;
<br>
+ struct discover_boot_option *opt = state->opt;
<br>
+ struct boot_option *option = opt->option;
<br>
+ const char *root;
<br>
+
<br>
+ if (!state->image) {
<br>
+ device_handler_status_dev_info(dc->handler,
dc->device,
<br>
+ _("linux field not
found in %s"),
<br>
+
state->filename);
<br>
+ return;
<br>
+ }
<br>
+
<br>
+ option->id = talloc_asprintf(option, "%s#%s",
dev->device->id,
<br>
+ state->image);
<br>
+
<br>
+ if (state->title)
<br>
+ option->name = talloc_strdup(option,
state->title);
<br>
+ else if (state->machine_id &&
state->version)
<br>
+ option->name = talloc_asprintf(option, "%s %s",
<br>
+
state->machine_id,
<br>
+ state->version);
<br>
+ else if (state->version)
<br>
+ option->name = talloc_strdup(option,
state->version);
<br>
+ else
<br>
+ option->name = talloc_strdup(option,
option->id);
<br>
+
<br>
+ root = script_env_get(state->script, "root");
<br>
+
<br>
+ opt->boot_image = create_grub2_resource(opt,
conf->dc->device,
<br>
+ root,
state->image);
<br>
+
<br>
+ if (state->initrd)
<br>
+ opt->initrd = create_grub2_resource(opt,
conf->dc->device,
<br>
+ root,
state->initrd);
<br>
+
<br>
+ if (state->dtb)
<br>
+ opt->dtb = create_grub2_resource(opt,
conf->dc->device,
<br>
+ root,
state->dtb);
<br>
+ discover_context_add_boot_option(dc, opt);
<br>
+
<br>
+ device_handler_status_dev_info(dc->handler,
dc->device,
<br>
+ _("Created menu entry from
BLS file %s"),
<br>
+ state->filename);
<br>
+}
<br>
+
<br>
+static int bls_filter(const struct dirent *ent)
<br>
+{
<br>
+ int offset = strlen(ent->d_name) - strlen(".conf");
<br>
+
<br>
+ if (offset < 0)
<br>
+ return 0;
<br>
+
<br>
+ return strncmp(ent->d_name + offset, ".conf",
strlen(".conf")) == 0;
<br>
+}
<br>
+
<br>
+static int bls_sort(const struct dirent **ent_a, const struct
dirent **ent_b)
<br>
+{
<br>
+ return strverscmp((*ent_b)->d_name,
(*ent_a)->d_name);
<br>
+}
<br>
+
<br>
+int builtin_blscfg(struct grub2_script *script,
<br>
+ void *data __attribute__((unused)),
<br>
+ int argc __attribute__((unused)),
<br>
+ char *argv[] __attribute__((unused)));
<br>
+
<br>
+int builtin_blscfg(struct grub2_script *script,
<br>
+ void *data __attribute__((unused)),
<br>
+ int argc __attribute__((unused)),
<br>
+ char *argv[] __attribute__((unused)))
<br>
+{
<br>
+ struct discover_context *dc = script->ctx;
<br>
+ struct dirent **bls_entries;
<br>
+ struct conf_context *conf;
<br>
+ struct bls_state *state;
<br>
+ char *buf, *filename;
<br>
+ int n, len, rc = -1;
<br>
+
<br>
+ conf = talloc_zero(dc, struct conf_context);
<br>
+ if (!conf)
<br>
+ return rc;
<br>
+
<br>
+ conf->dc = dc;
<br>
+ conf->get_pair = conf_get_pair_space;
<br>
+ conf->process_pair = bls_process_pair;
<br>
+ conf->finish = bls_finish;
<br>
+
<br>
+ n = parser_scandir(dc, BLS_DIR, &bls_entries,
bls_filter, bls_sort);
<br>
+ if (n <= 0)
<br>
+ goto err;
<br>
+
<br>
+ while (n--) {
<br>
+ filename = talloc_asprintf(dc, BLS_DIR"/%s",
<br>
+
bls_entries[n]->d_name);
<br>
+ if (!filename)
<br>
+ break;
<br>
+
<br>
+ state = talloc_zero(conf, struct bls_state);
<br>
+ if (!state)
<br>
+ break;
<br>
+
<br>
+ state->opt = discover_boot_option_create(dc,
dc->device);
<br>
+ if (!state->opt)
<br>
+ break;
<br>
+
<br>
+ state->script = script;
<br>
+ state->filename = filename;
<br>
+ conf->parser_info = state;
<br>
+
<br>
+ rc = parser_request_file(dc, dc->device,
filename, &buf, &len);
<br>
+ if (rc)
<br>
+ break;
<br>
+
<br>
+ conf_parse_buf(conf, buf, len);
<br>
+
<br>
+ talloc_free(buf);
<br>
+ talloc_free(state);
<br>
+ talloc_free(filename);
<br>
+ free(bls_entries[n]);
<br>
+ }
<br>
+
<br>
+ if (n > 0) {
<br>
+ device_handler_status_dev_info(dc->handler,
dc->device,
<br>
+ _("Scanning %s
failed"),
<br>
+ BLS_DIR);
<br>
+ do {
<br>
+ free(bls_entries[n]);
<br>
+ } while (n-- > 0);
<br>
+ }
<br>
+
<br>
+ free(bls_entries);
<br>
+err:
<br>
+ talloc_free(conf);
<br>
+ return rc;
<br>
+}
<br>
diff --git a/discover/grub2/builtins.c
b/discover/grub2/builtins.c
<br>
index c16b6390225a..e42821a64a9a 100644
<br>
--- a/discover/grub2/builtins.c
<br>
+++ b/discover/grub2/builtins.c
<br>
@@ -330,7 +330,10 @@ extern int builtin_load_env(struct
grub2_script *script,
<br>
int builtin_save_env(struct grub2_script *script,
<br>
void *data __attribute__((unused)),
<br>
int argc, char *argv[]);
<br>
-
<br>
+int builtin_blscfg(struct grub2_script *script,
<br>
+ void *data __attribute__((unused)),
<br>
+ int argc __attribute__((unused)),
<br>
+ char *argv[] __attribute__((unused)));
<br>
<br>
static struct {
<br>
const char *name;
<br>
@@ -380,6 +383,10 @@ static struct {
<br>
.name = "save_env",
<br>
.fn = builtin_save_env,
<br>
},
<br>
+ {
<br>
+ .name = "blscfg",
<br>
+ .fn = builtin_blscfg,
<br>
+ }
<br>
};
<br>
<br>
static const char *nops[] = {
<br>
diff --git a/discover/parser.c b/discover/parser.c
<br>
index 5598f963e236..9fe1925d94c4 100644
<br>
--- a/discover/parser.c
<br>
+++ b/discover/parser.c
<br>
@@ -128,6 +128,22 @@ out:
<br>
return -1;
<br>
}
<br>
<br>
+int parser_scandir(struct discover_context *ctx, const char
*dirname,
<br>
+ struct dirent ***files, int (*filter)(const
struct dirent *),
<br>
+ int (*comp)(const struct dirent **, const
struct dirent **))
<br>
+{
<br>
+ char *path;
<br>
+ int n;
<br>
+
<br>
+ path = talloc_asprintf(ctx, "%s%s",
ctx->device->mount_path, dirname);
<br>
+ if (!path)
<br>
+ return -1;
<br>
+
<br>
+ n = scandir(path, files, filter, comp);
<br>
+ talloc_free(path);
<br>
+ return n;
<br>
+}
<br>
+
<br>
void iterate_parsers(struct discover_context *ctx)
<br>
{
<br>
struct p_item* i;
<br>
diff --git a/discover/parser.h b/discover/parser.h
<br>
index fc165c5aeda4..bff52e30d09f 100644
<br>
--- a/discover/parser.h
<br>
+++ b/discover/parser.h
<br>
@@ -5,6 +5,7 @@
<br>
#include <sys/types.h>
<br>
#include <sys/stat.h>
<br>
#include <unistd.h>
<br>
+#include <dirent.h>
<br>
<br>
#include "device-handler.h"
<br>
<br>
@@ -76,5 +77,12 @@ int parser_request_url(struct
discover_context *ctx, struct pb_url *url,
<br>
int parser_stat_path(struct discover_context *ctx,
<br>
struct discover_device *dev, const char *path,
<br>
struct stat *statbuf);
<br>
+/* Function used to list the files on a directory. The dirname
should
<br>
+ * be relative to the discover context device mount path. It
returns
<br>
+ * the number of files returned in files or a negative value on
error.
<br>
+ */
<br>
+int parser_scandir(struct discover_context *ctx, const char
*dirname,
<br>
+ struct dirent ***files, int (*filter)(const
struct dirent *),
<br>
+ int (*comp)(const struct dirent **, const
struct dirent **));
<br>
<br>
#endif /* _PARSER_H */
<br>
diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am
<br>
index a0795dbcf899..b943408c4942 100644
<br>
--- a/test/parser/Makefile.am
<br>
+++ b/test/parser/Makefile.am
<br>
@@ -40,6 +40,9 @@ parser_TESTS = \
<br>
test/parser/test-grub2-parser-error \
<br>
test/parser/test-grub2-test-file-ops \
<br>
test/parser/test-grub2-single-yocto \
<br>
+ test/parser/test-grub2-blscfg-multiple-bls \
<br>
+ test/parser/test-grub2-blscfg-opts-config \
<br>
+ test/parser/test-grub2-blscfg-opts-grubenv \
<br>
test/parser/test-kboot-single \
<br>
test/parser/test-yaboot-empty \
<br>
test/parser/test-yaboot-single \
<br>
diff --git a/test/parser/test-grub2-blscfg-multiple-bls.c
b/test/parser/test-grub2-blscfg-multiple-bls.c
<br>
new file mode 100644
<br>
index 000000000000..8fd218c371e8
<br>
--- /dev/null
<br>
+++ b/test/parser/test-grub2-blscfg-multiple-bls.c
<br>
@@ -0,0 +1,44 @@
<br>
+#include "parser-test.h"
<br>
+
<br>
+#if 0 /* PARSER_EMBEDDED_CONFIG */
<br>
+blscfg
<br>
+#endif
<br>
+
<br>
+void run_test(struct parser_test *test)
<br>
+{
<br>
+ struct discover_boot_option *opt;
<br>
+ struct discover_context *ctx;
<br>
+
<br>
+ test_add_file_string(test, test->ctx->device,
<br>
+
"/loader/entries/6c063c8e48904f2684abde8eea303f41-4.15.2-302.fc28.x86_64.conf",<br>
+ "title Fedora
(4.15.2-302.fc28.x86_64) 28 (Twenty Eight)\n"
<br>
+ "linux
/vmlinuz-4.15.2-302.fc28.x86_64\n"
<br>
+ "initrd
/initramfs-4.15.2-302.fc28.x86_64.img\n"
<br>
+ "options root=/dev/mapper/fedora-root
ro rd.lvm.lv=fedora/root\n\n");
<br>
+
<br>
+ test_add_file_string(test, test->ctx->device,
<br>
+
"/loader/entries/6c063c8e48904f2684abde8eea303f41-4.14.18-300.fc28.x86_64.conf",<br>
+ "title Fedora
(4.14.18-300.fc28.x86_64) 28 (Twenty Eight)\n"
<br>
+ "linux
/vmlinuz-4.14.18-300.fc28.x86_64\n"
<br>
+ "initrd
/initramfs-4.14.18-300.fc28.x86_64.img\n"
<br>
+ "options root=/dev/mapper/fedora-root
ro rd.lvm.lv=fedora/root\n");
<br>
+
<br>
+ test_read_conf_embedded(test, "/boot/grub2/grub.cfg");
<br>
+
<br>
+ test_run_parser(test, "grub2");
<br>
+
<br>
+ ctx = test->ctx;
<br>
+
<br>
+ check_boot_option_count(ctx, 2);
<br>
+ opt = get_boot_option(ctx, 0);
<br>
+
<br>
+ check_name(opt, "Fedora (4.15.2-302.fc28.x86_64) 28
(Twenty Eight)");
<br>
+ check_resolved_local_resource(opt->boot_image,
ctx->device,
<br>
+ "/vmlinuz-4.15.2-302.fc28.x86_64");
<br>
+
<br>
+ opt = get_boot_option(ctx, 1);
<br>
+
<br>
+ check_name(opt, "Fedora (4.14.18-300.fc28.x86_64) 28
(Twenty Eight)");
<br>
+ check_resolved_local_resource(opt->initrd,
ctx->device,
<br>
+ "/initramfs-4.14.18-300.fc28.x86_64.img");
<br>
+}
<br>
diff --git a/test/parser/test-grub2-blscfg-opts-config.c
b/test/parser/test-grub2-blscfg-opts-config.c
<br>
new file mode 100644
<br>
index 000000000000..856aae2adf5f
<br>
--- /dev/null
<br>
+++ b/test/parser/test-grub2-blscfg-opts-config.c
<br>
@@ -0,0 +1,29 @@
<br>
+#include "parser-test.h"
<br>
+
<br>
+#if 0 /* PARSER_EMBEDDED_CONFIG */
<br>
+set kernelopts=root=/dev/mapper/fedora-root ro
rd.lvm.lv=fedora/root
<br>
+blscfg
<br>
+#endif
<br>
+
<br>
+void run_test(struct parser_test *test)
<br>
+{
<br>
+ struct discover_boot_option *opt;
<br>
+ struct discover_context *ctx;
<br>
+
<br>
+ test_add_file_string(test, test->ctx->device,
<br>
+
"/loader/entries/6c063c8e48904f2684abde8eea303f41-4.15.2-302.fc28.x86_64.conf",<br>
+ "title Fedora
(4.15.2-302.fc28.x86_64) 28 (Twenty Eight)\n"
<br>
+ "linux
/vmlinuz-4.15.2-302.fc28.x86_64\n"
<br>
+ "initrd
/initramfs-4.15.2-302.fc28.x86_64.img\n"
<br>
+ "options $kernelopts\n");
<br>
+
<br>
+ test_read_conf_embedded(test, "/boot/grub2/grub.cfg");
<br>
+
<br>
+ test_run_parser(test, "grub2");
<br>
+
<br>
+ ctx = test->ctx;
<br>
+
<br>
+ opt = get_boot_option(ctx, 0);
<br>
+
<br>
+ check_args(opt, "root=/dev/mapper/fedora-root ro
rd.lvm.lv=fedora/root");
<br>
+}
<br>
diff --git a/test/parser/test-grub2-blscfg-opts-grubenv.c
b/test/parser/test-grub2-blscfg-opts-grubenv.c
<br>
new file mode 100644
<br>
index 000000000000..c77c589b7707
<br>
--- /dev/null
<br>
+++ b/test/parser/test-grub2-blscfg-opts-grubenv.c
<br>
@@ -0,0 +1,34 @@
<br>
+#include "parser-test.h"
<br>
+
<br>
+#if 0 /* PARSER_EMBEDDED_CONFIG */
<br>
+load_env
<br>
+blscfg
<br>
+#endif
<br>
+
<br>
+void run_test(struct parser_test *test)
<br>
+{
<br>
+ struct discover_boot_option *opt;
<br>
+ struct discover_context *ctx;
<br>
+
<br>
+ test_add_file_string(test, test->ctx->device,
<br>
+ "/boot/grub2/grubenv",
<br>
+ "# GRUB Environment Block\n"
<br>
+
"kernelopts=root=/dev/mapper/fedora-root ro
rd.lvm.lv=fedora/root\n");
<br>
+
<br>
+ test_add_file_string(test, test->ctx->device,
<br>
+
"/loader/entries/6c063c8e48904f2684abde8eea303f41-4.15.2-302.fc28.x86_64.conf",<br>
+ "title Fedora
(4.15.2-302.fc28.x86_64) 28 (Twenty Eight)\n"
<br>
+ "linux
/vmlinuz-4.15.2-302.fc28.x86_64\n"
<br>
+ "initrd
/initramfs-4.15.2-302.fc28.x86_64.img\n"
<br>
+ "options $kernelopts\n");
<br>
+
<br>
+ test_read_conf_embedded(test, "/boot/grub2/grub.cfg");
<br>
+
<br>
+ test_run_parser(test, "grub2");
<br>
+
<br>
+ ctx = test->ctx;
<br>
+
<br>
+ opt = get_boot_option(ctx, 0);
<br>
+
<br>
+ check_args(opt, "root=/dev/mapper/fedora-root ro
rd.lvm.lv=fedora/root");
<br>
+}
<br>
diff --git a/test/parser/utils.c b/test/parser/utils.c
<br>
index 8900bd72bebd..683bba7d0379 100644
<br>
--- a/test/parser/utils.c
<br>
+++ b/test/parser/utils.c
<br>
@@ -309,6 +309,65 @@ int parser_replace_file(struct
discover_context *ctx,
<br>
return 0;
<br>
}
<br>
<br>
+int parser_scandir(struct discover_context *ctx, const char
*dirname,
<br>
+ struct dirent ***files, int (*filter)(const
struct dirent *)
<br>
+ __attribute__((unused)),
<br>
+ int (*comp)(const struct dirent **, const
struct dirent **)
<br>
+ __attribute__((unused)))
<br>
+{
<br>
+ struct parser_test *test = ctx->test_data;
<br>
+ struct test_file *f;
<br>
+ char *filename;
<br>
+ struct dirent **dirents = NULL, **new_dirents;
<br>
+ int n = 0, namelen;
<br>
+
<br>
+ list_for_each_entry(&test->files, f, list) {
<br>
+ if (f->dev != ctx->device)
<br>
+ continue;
<br>
+
<br>
+ filename = strrchr(f->name, '/');
<br>
+ if (!filename)
<br>
+ continue;
<br>
+
<br>
+ namelen = strlen(filename);
<br>
+
<br>
+ if (strncmp(f->name, dirname,
strlen(f->name) - namelen))
<br>
+ continue;
<br>
+
<br>
+ if (!dirents) {
<br>
+ dirents = malloc(sizeof(struct dirent *));
<br>
+ } else {
<br>
+ new_dirents = realloc(dirents,
sizeof(struct dirent *)
<br>
+ * (n + 1));
<br>
+ if (!new_dirents)
<br>
+ goto err_cleanup;
<br>
+
<br>
+ dirents = new_dirents;
<br>
+ }
<br>
+
<br>
+ dirents[n] = malloc(sizeof(struct dirent) +
namelen + 1);
<br>
+
<br>
+ if (!dirents[n])
<br>
+ goto err_cleanup;
<br>
+
<br>
+ strcpy(dirents[n]->d_name, filename + 1);
<br>
+ n++;
<br>
+ }
<br>
+
<br>
+ *files = dirents;
<br>
+
<br>
+ return n;
<br>
+
<br>
+err_cleanup:
<br>
+ do {
<br>
+ free(dirents[n]);
<br>
+ } while (n-- > 0);
<br>
+
<br>
+ free(dirents);
<br>
+
<br>
+ return -1;
<br>
+}
<br>
+
<br>
struct load_url_result *load_url_async(void *ctx, struct
pb_url *url,
<br>
load_url_complete async_cb, void *async_data,
<br>
waiter_cb stdout_cb, void *stdout_data)
<br>
</blockquote>
<br>
_______________________________________________
<br>
Petitboot mailing list
<br>
<a class="moz-txt-link-abbreviated" href="mailto:Petitboot@lists.ozlabs.org">Petitboot@lists.ozlabs.org</a>
<br>
<a class="moz-txt-link-freetext" href="https://lists.ozlabs.org/listinfo/petitboot">https://lists.ozlabs.org/listinfo/petitboot</a>
<br>
</blockquote>
<br>
</body>
</html>