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 option->is_default = option_is_default(state, option);
153 list_add_tail(&state->script->options, &opt->list);
154 state->script->n_options++;
156 device_handler_status_dev_info(dc->handler, dc->device,
157 _("Created menu entry from BLS file %s"),
161 static int bls_filter(const struct dirent *ent)
163 int offset = strlen(ent->d_name) - strlen(".conf");
168 return strncmp(ent->d_name + offset, ".conf", strlen(".conf")) == 0;
171 static int bls_sort(const struct dirent **ent_a, const struct dirent **ent_b)
173 return strverscmp((*ent_a)->d_name, (*ent_b)->d_name);
176 int builtin_blscfg(struct grub2_script *script,
177 void *data __attribute__((unused)),
178 int argc __attribute__((unused)),
179 char *argv[] __attribute__((unused)));
181 int builtin_blscfg(struct grub2_script *script,
182 void *data __attribute__((unused)),
183 int argc __attribute__((unused)),
184 char *argv[] __attribute__((unused)))
186 unsigned int current_idx = script->n_options;
187 struct discover_context *dc = script->ctx;
188 struct dirent **bls_entries;
189 struct conf_context *conf;
190 struct bls_state *state;
191 char *buf, *filename;
195 conf = talloc_zero(dc, struct conf_context);
200 conf->get_pair = conf_get_pair_space;
201 conf->process_pair = bls_process_pair;
202 conf->finish = bls_finish;
204 blsdir = script_env_get(script, "blsdir");
208 n = parser_scandir(dc, blsdir, &bls_entries, bls_filter, bls_sort);
213 filename = talloc_asprintf(dc, "%s/%s", blsdir,
214 bls_entries[n]->d_name);
218 state = talloc_zero(conf, struct bls_state);
222 state->opt = discover_boot_option_create(dc, dc->device);
226 state->script = script;
227 state->filename = filename;
228 state->idx = current_idx++;
229 conf->parser_info = state;
231 rc = parser_request_file(dc, dc->device, filename, &buf, &len);
235 conf_parse_buf(conf, buf, len);
239 talloc_free(filename);
240 free(bls_entries[n]);
244 device_handler_status_dev_info(dc->handler, dc->device,
245 _("Scanning %s failed"),
248 free(bls_entries[n]);