10 #include <file/file.h>
11 #include <talloc/talloc.h>
12 #include <i18n/i18n.h>
15 #include "discover/parser-conf.h"
16 #include "discover/parser.h"
18 #define BLS_DIR "/loader/entries"
21 struct discover_boot_option *opt;
22 struct grub2_script *script;
26 const char *machine_id;
32 static void bls_process_pair(struct conf_context *conf, const char *name,
35 struct bls_state *state = conf->parser_info;
36 struct discover_boot_option *opt = state->opt;
37 struct boot_option *option = opt->option;
38 const char *boot_args;
40 if (streq(name, "title")) {
41 state->title = talloc_strdup(state, value);
45 if (streq(name, "version")) {
46 state->version = talloc_strdup(state, value);
50 if (streq(name, "machine-id")) {
51 state->machine_id = talloc_strdup(state, value);
55 if (streq(name, "linux")) {
56 state->image = talloc_strdup(state, value);
60 if (streq(name, "initrd")) {
61 state->initrd = talloc_strdup(state, value);
65 if (streq(name, "devicetree")) {
66 state->dtb = talloc_strdup(state, value);
70 if (streq(name, "options")) {
71 if (value[0] == '$') {
72 boot_args = script_env_get(state->script, value + 1);
76 option->boot_args = talloc_strdup(opt, boot_args);
78 option->boot_args = talloc_strdup(opt, value);
84 static bool option_is_default(struct grub2_script *script,
85 struct boot_option *option)
89 var = script_env_get(script, "default");
93 if (!strcmp(var, option->id))
96 return !strcmp(var, option->name);
99 static void bls_finish(struct conf_context *conf)
101 struct bls_state *state = conf->parser_info;
102 struct discover_context *dc = conf->dc;
103 struct discover_boot_option *opt = state->opt;
104 struct boot_option *option = opt->option;
109 device_handler_status_dev_info(dc->handler, dc->device,
110 _("linux field not found in %s"),
115 filename = basename(state->filename);
116 filename[strlen(filename) - strlen(".conf")] = '\0';
118 option->id = talloc_strdup(option, filename);
121 option->name = talloc_strdup(option, state->title);
122 else if (state->machine_id && state->version)
123 option->name = talloc_asprintf(option, "%s %s",
126 else if (state->version)
127 option->name = talloc_strdup(option, state->version);
129 option->name = talloc_strdup(option, state->image);
131 root = script_env_get(state->script, "root");
133 opt->boot_image = create_grub2_resource(opt, conf->dc->device,
137 opt->initrd = create_grub2_resource(opt, conf->dc->device,
138 root, state->initrd);
141 opt->dtb = create_grub2_resource(opt, conf->dc->device,
144 option->is_default = option_is_default(state->script, option);
146 discover_context_add_boot_option(dc, opt);
148 device_handler_status_dev_info(dc->handler, dc->device,
149 _("Created menu entry from BLS file %s"),
153 static int bls_filter(const struct dirent *ent)
155 int offset = strlen(ent->d_name) - strlen(".conf");
160 return strncmp(ent->d_name + offset, ".conf", strlen(".conf")) == 0;
163 static int bls_sort(const struct dirent **ent_a, const struct dirent **ent_b)
165 return strverscmp((*ent_b)->d_name, (*ent_a)->d_name);
168 int builtin_blscfg(struct grub2_script *script,
169 void *data __attribute__((unused)),
170 int argc __attribute__((unused)),
171 char *argv[] __attribute__((unused)));
173 int builtin_blscfg(struct grub2_script *script,
174 void *data __attribute__((unused)),
175 int argc __attribute__((unused)),
176 char *argv[] __attribute__((unused)))
178 struct discover_context *dc = script->ctx;
179 struct dirent **bls_entries;
180 struct conf_context *conf;
181 struct bls_state *state;
182 char *buf, *filename;
186 conf = talloc_zero(dc, struct conf_context);
191 conf->get_pair = conf_get_pair_space;
192 conf->process_pair = bls_process_pair;
193 conf->finish = bls_finish;
195 blsdir = script_env_get(script, "blsdir");
199 n = parser_scandir(dc, blsdir, &bls_entries, bls_filter, bls_sort);
204 filename = talloc_asprintf(dc, "%s/%s", blsdir,
205 bls_entries[n]->d_name);
209 state = talloc_zero(conf, struct bls_state);
213 state->opt = discover_boot_option_create(dc, dc->device);
217 state->script = script;
218 state->filename = filename;
219 conf->parser_info = state;
221 rc = parser_request_file(dc, dc->device, filename, &buf, &len);
225 conf_parse_buf(conf, buf, len);
229 talloc_free(filename);
230 free(bls_entries[n]);
234 device_handler_status_dev_info(dc->handler, dc->device,
235 _("Scanning %s failed"),
238 free(bls_entries[n]);