discover/kboot-parser: Look in /boot
[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         conf_strip_str(opt->boot_args);
130         conf_strip_str(opt->description);
131
132         discover_context_add_boot_option(conf->dc, d_opt);
133 }
134
135 static struct conf_global_option kboot_global_options[] = {
136         { .name = "dtb" },
137         { .name = "initrd" },
138         { .name = "root" },
139         { .name = "video" },
140         { .name = NULL }
141 };
142
143 static const char *const kboot_conf_files[] = {
144         "/kboot.conf",
145         "/kboot.cnf",
146         "/etc/kboot.conf",
147         "/etc/kboot.cnf",
148         "/boot/kboot.conf",
149         "/boot/kboot.cnf",
150         "/KBOOT.CONF",
151         "/KBOOT.CNF",
152         "/ETC/KBOOT.CONF",
153         "/ETC/KBOOT.CNF",
154         "/BOOT/KBOOT.CONF",
155         "/BOOT/KBOOT.CNF",
156         NULL
157 };
158
159 static const char *const kboot_ignored_names[] = {
160         "default",
161         "delay",
162         "message",
163         "timeout",
164         NULL
165 };
166
167 static int kboot_parse(struct discover_context *dc)
168 {
169         struct conf_context *conf;
170         const char * const *filename;
171         char *buf;
172         int len, rc;
173
174         /* Support block device boot only at present */
175         if (dc->event)
176                 return -1;
177
178         conf = talloc_zero(dc, struct conf_context);
179
180         if (!conf)
181                 return -1;
182
183         conf->dc = dc;
184         conf->global_options = kboot_global_options,
185         conf_init_global_options(conf);
186         conf->get_pair = conf_get_pair_equal;
187         conf->process_pair = kboot_process_pair;
188         conf->parser_info = (void *)kboot_ignored_names;
189
190         for (filename = kboot_conf_files; *filename; filename++) {
191                 rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
192                 if (rc)
193                         continue;
194
195                 conf_parse_buf(conf, buf, len);
196                 device_handler_status_dev_info(dc->handler, dc->device,
197                                 _("Parsed kboot configuration from %s"),
198                                 *filename);
199                 talloc_free(buf);
200         }
201
202         talloc_free(conf);
203         return 0;
204 }
205
206 static struct parser kboot_parser = {
207         .name                   = "kboot",
208         .parse                  = kboot_parse,
209         .resolve_resource       = resolve_devpath_resource,
210 };
211
212 register_parser(kboot_parser);