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 static const char *const bls_dirs[] = {
20 "/boot/loader/entries",
25 struct discover_boot_option *opt;
26 struct grub2_script *script;
31 const char *machine_id;
37 static void bls_process_pair(struct conf_context *conf, const char *name,
40 struct bls_state *state = conf->parser_info;
41 struct discover_boot_option *opt = state->opt;
42 struct boot_option *option = opt->option;
43 const char *boot_args;
45 if (streq(name, "title")) {
46 state->title = talloc_strdup(state, value);
50 if (streq(name, "version")) {
51 state->version = talloc_strdup(state, value);
55 if (streq(name, "machine-id")) {
56 state->machine_id = talloc_strdup(state, value);
60 if (streq(name, "linux")) {
61 state->image = talloc_strdup(state, value);
65 if (streq(name, "initrd")) {
66 state->initrd = talloc_strdup(state, value);
70 if (streq(name, "devicetree")) {
71 state->dtb = talloc_strdup(state, value);
75 if (streq(name, "options")) {
76 if (value[0] == '$') {
77 boot_args = script_env_get(state->script, value + 1);
81 option->boot_args = talloc_strdup(opt, boot_args);
83 option->boot_args = talloc_strdup(opt, value);
89 static bool option_is_default(struct bls_state *state,
90 struct boot_option *option)
96 var = script_env_get(state->script, "default");
100 if (!strcmp(var, option->id))
103 if (!strcmp(var, option->name))
106 idx = strtoul(var, &end, 10);
107 return end != var && *end == '\0' && idx == state->idx;
110 static void bls_finish(struct conf_context *conf)
112 struct bls_state *state = conf->parser_info;
113 struct discover_context *dc = conf->dc;
114 struct discover_boot_option *opt = state->opt;
115 struct boot_option *option = opt->option;
120 device_handler_status_dev_info(dc->handler, dc->device,
121 _("linux field not found in %s"),
126 filename = basename(state->filename);
127 filename[strlen(filename) - strlen(".conf")] = '\0';
129 option->id = talloc_strdup(option, filename);
132 option->name = talloc_strdup(option, state->title);
133 else if (state->machine_id && state->version)
134 option->name = talloc_asprintf(option, "%s %s",
137 else if (state->version)
138 option->name = talloc_strdup(option, state->version);
140 option->name = talloc_strdup(option, state->image);
142 root = script_env_get(state->script, "root");
144 opt->boot_image = create_grub2_resource(opt, conf->dc->device,
148 opt->initrd = create_grub2_resource(opt, conf->dc->device,
149 root, state->initrd);
152 opt->dtb = create_grub2_resource(opt, conf->dc->device,
155 char* args_sigfile_default = talloc_asprintf(opt,
156 "%s.cmdline.sig", state->image);
157 opt->args_sig_file = create_grub2_resource(opt, conf->dc->device,
158 root, args_sigfile_default);
159 talloc_free(args_sigfile_default);
161 option->is_default = option_is_default(state, option);
163 list_add_tail(&state->script->options, &opt->list);
164 state->script->n_options++;
166 device_handler_status_dev_info(dc->handler, dc->device,
167 _("Created menu entry from BLS file %s"),
171 static int bls_filter(const struct dirent *ent)
173 int offset = strlen(ent->d_name) - strlen(".conf");
178 return strncmp(ent->d_name + offset, ".conf", strlen(".conf")) == 0;
181 static int bls_sort(const struct dirent **ent_a, const struct dirent **ent_b)
183 return strverscmp((*ent_a)->d_name, (*ent_b)->d_name);
186 int builtin_blscfg(struct grub2_script *script,
187 void *data __attribute__((unused)),
188 int argc __attribute__((unused)),
189 char *argv[] __attribute__((unused)));
191 int builtin_blscfg(struct grub2_script *script,
192 void *data __attribute__((unused)),
193 int argc __attribute__((unused)),
194 char *argv[] __attribute__((unused)))
196 unsigned int current_idx = script->n_options;
197 struct discover_context *dc = script->ctx;
198 struct dirent **bls_entries;
199 struct conf_context *conf;
200 struct bls_state *state;
201 char *buf, *filename;
202 const char * const *dir;
207 conf = talloc_zero(dc, struct conf_context);
212 conf->get_pair = conf_get_pair_space;
213 conf->process_pair = bls_process_pair;
214 conf->finish = bls_finish;
216 blsdir = script_env_get(script, "blsdir");
218 for (dir = bls_dirs; *dir; dir++)
219 if (!parser_stat_path(dc, dc->device, *dir, &statbuf)) {
225 device_handler_status_dev_info(dc->handler, dc->device,
226 _("BLS directory wasn't found"));
230 n = parser_scandir(dc, blsdir, &bls_entries, bls_filter, bls_sort);
235 filename = talloc_asprintf(dc, "%s/%s", blsdir,
236 bls_entries[n]->d_name);
240 state = talloc_zero(conf, struct bls_state);
244 state->opt = discover_boot_option_create(dc, dc->device);
248 state->script = script;
249 state->filename = filename;
250 state->idx = current_idx++;
251 conf->parser_info = state;
253 rc = parser_request_file(dc, dc->device, filename, &buf, &len);
257 conf_parse_buf(conf, buf, len);
261 talloc_free(filename);
262 free(bls_entries[n]);
266 device_handler_status_dev_info(dc->handler, dc->device,
267 _("Scanning %s failed"),
270 free(bls_entries[n]);