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;
27 const char *machine_id;
33 static void bls_process_pair(struct conf_context *conf, const char *name,
36 struct bls_state *state = conf->parser_info;
37 struct discover_boot_option *opt = state->opt;
38 struct boot_option *option = opt->option;
39 const char *boot_args;
41 if (streq(name, "title")) {
42 state->title = talloc_strdup(state, value);
46 if (streq(name, "version")) {
47 state->version = talloc_strdup(state, value);
51 if (streq(name, "machine-id")) {
52 state->machine_id = talloc_strdup(state, value);
56 if (streq(name, "linux")) {
57 state->image = talloc_strdup(state, value);
61 if (streq(name, "initrd")) {
62 state->initrd = talloc_strdup(state, value);
66 if (streq(name, "devicetree")) {
67 state->dtb = talloc_strdup(state, value);
71 if (streq(name, "options")) {
72 if (value[0] == '$') {
73 boot_args = script_env_get(state->script, value + 1);
77 option->boot_args = talloc_strdup(opt, boot_args);
79 option->boot_args = talloc_strdup(opt, value);
85 static bool option_is_default(struct bls_state *state,
86 struct boot_option *option)
92 var = script_env_get(state->script, "default");
96 if (!strcmp(var, option->id))
99 if (!strcmp(var, option->name))
102 idx = strtoul(var, &end, 10);
103 return end != var && *end == '\0' && idx == state->idx;
106 static void bls_finish(struct conf_context *conf)
108 struct bls_state *state = conf->parser_info;
109 struct discover_context *dc = conf->dc;
110 struct discover_boot_option *opt = state->opt;
111 struct boot_option *option = opt->option;
116 device_handler_status_dev_info(dc->handler, dc->device,
117 _("linux field not found in %s"),
122 filename = basename(state->filename);
123 filename[strlen(filename) - strlen(".conf")] = '\0';
125 option->id = talloc_strdup(option, filename);
128 option->name = talloc_strdup(option, state->title);
129 else if (state->machine_id && state->version)
130 option->name = talloc_asprintf(option, "%s %s",
133 else if (state->version)
134 option->name = talloc_strdup(option, state->version);
136 option->name = talloc_strdup(option, state->image);
138 root = script_env_get(state->script, "root");
140 opt->boot_image = create_grub2_resource(opt, conf->dc->device,
144 opt->initrd = create_grub2_resource(opt, conf->dc->device,
145 root, state->initrd);
148 opt->dtb = create_grub2_resource(opt, conf->dc->device,
151 char* args_sigfile_default = talloc_asprintf(opt,
152 "%s.cmdline.sig", state->image);
153 opt->args_sig_file = create_grub2_resource(opt, conf->dc->device,
154 root, args_sigfile_default);
155 talloc_free(args_sigfile_default);
157 option->is_default = option_is_default(state, option);
159 list_add_tail(&state->script->options, &opt->list);
160 state->script->n_options++;
162 device_handler_status_dev_info(dc->handler, dc->device,
163 _("Created menu entry from BLS file %s"),
167 static int bls_filter(const struct dirent *ent)
169 int offset = strlen(ent->d_name) - strlen(".conf");
174 return strncmp(ent->d_name + offset, ".conf", strlen(".conf")) == 0;
177 static int bls_sort(const struct dirent **ent_a, const struct dirent **ent_b)
179 return strverscmp((*ent_a)->d_name, (*ent_b)->d_name);
182 int builtin_blscfg(struct grub2_script *script,
183 void *data __attribute__((unused)),
184 int argc __attribute__((unused)),
185 char *argv[] __attribute__((unused)));
187 int builtin_blscfg(struct grub2_script *script,
188 void *data __attribute__((unused)),
189 int argc __attribute__((unused)),
190 char *argv[] __attribute__((unused)))
192 unsigned int current_idx = script->n_options;
193 struct discover_context *dc = script->ctx;
194 struct dirent **bls_entries;
195 struct conf_context *conf;
196 struct bls_state *state;
197 char *buf, *filename;
201 conf = talloc_zero(dc, struct conf_context);
206 conf->get_pair = conf_get_pair_space;
207 conf->process_pair = bls_process_pair;
208 conf->finish = bls_finish;
210 blsdir = script_env_get(script, "blsdir");
214 n = parser_scandir(dc, blsdir, &bls_entries, bls_filter, bls_sort);
219 filename = talloc_asprintf(dc, "%s/%s", blsdir,
220 bls_entries[n]->d_name);
224 state = talloc_zero(conf, struct bls_state);
228 state->opt = discover_boot_option_create(dc, dc->device);
232 state->script = script;
233 state->filename = filename;
234 state->idx = current_idx++;
235 conf->parser_info = state;
237 rc = parser_request_file(dc, dc->device, filename, &buf, &len);
241 conf_parse_buf(conf, buf, len);
245 talloc_free(filename);
246 free(bls_entries[n]);
250 device_handler_status_dev_info(dc->handler, dc->device,
251 _("Scanning %s failed"),
254 free(bls_entries[n]);