]> git.ozlabs.org Git - petitboot/blob - discover/kboot-parser.c
discover/grub2: Allow to separate the --id argument using a space char
[petitboot] / discover / kboot-parser.c
1 #if defined(HAVE_CONFIG_H)
2 #include "config.h"
3 #endif
4
5 #include <assert.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <i18n/i18n.h>
9
10 #include "log/log.h"
11 #include "talloc/talloc.h"
12 #include "types/types.h"
13 #include "parser-conf.h"
14 #include "parser-utils.h"
15 #include "resource.h"
16
17 static void kboot_process_pair(struct conf_context *conf, const char *name,
18                 char *value)
19 {
20         const char *const *ignored_names = conf->parser_info;
21         struct discover_boot_option *d_opt;
22         struct boot_option *opt;
23         char *pos;
24         char *args;
25         const char *initrd;
26         const char *root;
27         const char *dtb;
28
29         /* ignore bare values */
30
31         if (!name)
32                 return;
33
34         if (conf_param_in_list(ignored_names, name))
35                 return;
36
37         if (conf_set_global_option(conf, name, value))
38                 return;
39
40         /* opt must be associated with dc */
41
42         d_opt = talloc_zero(conf->dc, struct discover_boot_option);
43         d_opt->device = conf->dc->device;
44         opt = talloc_zero(d_opt, struct boot_option);
45
46         if (!opt)
47                 return;
48
49         opt->id = talloc_asprintf(opt, "%s#%s", conf->dc->device->device->id,
50                         name);
51         opt->name = talloc_strdup(opt, name);
52         d_opt->option = opt;
53
54         args = talloc_strdup(opt, "");
55         initrd = conf_get_global_option(conf, "initrd");
56         root = conf_get_global_option(conf, "root");
57         dtb = conf_get_global_option(conf, "dtb");
58
59         pos = strchr(value, ' ');
60
61         /* if there's no space, it's only a kernel image with no params */
62
63         if (!pos)
64                 goto out_add;
65         *pos = 0;
66
67         for (pos++; pos;) {
68                 char *cl_name, *cl_value;
69
70                 pos = conf_get_pair_equal(conf, pos, &cl_name, &cl_value, ' ');
71
72                 if (!cl_name) {
73                         args = talloc_asprintf_append(args, "%s ", cl_value);
74                         continue;
75                 }
76
77                 if (streq(cl_name, "initrd")) {
78                         initrd = cl_value;
79                         continue;
80                 }
81
82                 if (streq(cl_name, "root")) {
83                         root = cl_value;
84                         continue;
85                 }
86
87                 if (streq(cl_name, "dtb")) {
88                         dtb = cl_value;
89                         continue;
90                 }
91
92                 args = talloc_asprintf_append(args, "%s=%s ", cl_name,
93                         cl_value);
94         }
95
96 out_add:
97         d_opt->boot_image = create_devpath_resource(d_opt,
98                                 conf->dc->device, value);
99
100         char* args_sigfile_default = talloc_asprintf(d_opt,
101                 "%s.cmdline.sig", value);
102         d_opt->args_sig_file = create_devpath_resource(d_opt,
103                                 conf->dc->device, args_sigfile_default);
104         talloc_free(args_sigfile_default);
105
106         if (root) {
107                 opt->boot_args = talloc_asprintf(opt, "root=%s %s", root, args);
108                 talloc_free(args);
109         } else
110                 opt->boot_args = args;
111
112         opt->description = talloc_asprintf(opt, "%s %s", value,
113                         opt->boot_args);
114
115         if (initrd) {
116                 d_opt->initrd = create_devpath_resource(d_opt,
117                                 conf->dc->device, initrd);
118                 opt->description = talloc_asprintf_append(opt->description,
119                                 " initrd=%s", initrd);
120         }
121
122         if (dtb) {
123                 d_opt->dtb = create_devpath_resource(d_opt,
124                                 conf->dc->device, dtb);
125                 opt->description = talloc_asprintf_append(opt->description,
126                                 " dtb=%s", dtb);
127         }
128
129         if (conf_get_global_option(conf, "default"))
130                 opt->is_default = streq(opt->name,
131                                 conf_get_global_option(conf, "default"));
132
133         conf_strip_str(opt->boot_args);
134         conf_strip_str(opt->description);
135
136         discover_context_add_boot_option(conf->dc, d_opt);
137 }
138
139 static struct conf_global_option kboot_global_options[] = {
140         { .name = "dtb" },
141         { .name = "initrd" },
142         { .name = "root" },
143         { .name = "video" },
144         { .name = "default" },
145         { .name = NULL }
146 };
147
148 static const char *const kboot_conf_files[] = {
149         "/kboot.conf",
150         "/kboot.cnf",
151         "/etc/kboot.conf",
152         "/etc/kboot.cnf",
153         "/boot/kboot.conf",
154         "/boot/kboot.cnf",
155         "/KBOOT.CONF",
156         "/KBOOT.CNF",
157         "/ETC/KBOOT.CONF",
158         "/ETC/KBOOT.CNF",
159         "/BOOT/KBOOT.CONF",
160         "/BOOT/KBOOT.CNF",
161         NULL
162 };
163
164 static const char *const kboot_ignored_names[] = {
165         "delay",
166         "message",
167         "timeout",
168         NULL
169 };
170
171 static int kboot_parse(struct discover_context *dc)
172 {
173         struct conf_context *conf;
174         struct list *found_list;
175         const char * const *filename;
176
177         /* Support block device boot only at present */
178         if (dc->event)
179                 return -1;
180
181         conf = talloc_zero(dc, struct conf_context);
182         if (!conf)
183                 return -1;
184
185         found_list = talloc(conf, struct list);
186         if (!found_list)
187                 return -1;
188         list_init(found_list);
189
190         conf->dc = dc;
191         conf->global_options = kboot_global_options,
192         conf_init_global_options(conf);
193         conf->get_pair = conf_get_pair_equal;
194         conf->process_pair = kboot_process_pair;
195         conf->parser_info = (void *)kboot_ignored_names;
196
197         for (filename = kboot_conf_files; *filename; filename++) {
198                 int len, rc;
199                 char *buf;
200
201                 if (!parser_is_unique(dc, dc->device, *filename, found_list))
202                         continue;
203
204                 rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
205                 if (rc)
206                         continue;
207
208                 conf_parse_buf(conf, buf, len);
209                 device_handler_status_dev_info(dc->handler, dc->device,
210                                 _("Parsed kboot configuration from %s"),
211                                 *filename);
212                 talloc_free(buf);
213         }
214
215         talloc_free(conf);
216         return 0;
217 }
218
219 static struct parser kboot_parser = {
220         .name                   = "kboot",
221         .parse                  = kboot_parse,
222         .resolve_resource       = resolve_devpath_resource,
223 };
224
225 register_parser(kboot_parser);