bf9c5eb2fe98f5f59056cad85f47e018cb31a674
[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         "/KBOOT.CONF",
149         "/KBOOT.CNF",
150         "/ETC/KBOOT.CONF",
151         "/ETC/KBOOT.CNF",
152         NULL
153 };
154
155 static const char *const kboot_ignored_names[] = {
156         "default",
157         "delay",
158         "message",
159         "timeout",
160         NULL
161 };
162
163 static int kboot_parse(struct discover_context *dc)
164 {
165         struct conf_context *conf;
166         const char * const *filename;
167         char *buf;
168         int len, rc;
169
170         /* Support block device boot only at present */
171         if (dc->event)
172                 return -1;
173
174         conf = talloc_zero(dc, struct conf_context);
175
176         if (!conf)
177                 return -1;
178
179         conf->dc = dc;
180         conf->global_options = kboot_global_options,
181         conf_init_global_options(conf);
182         conf->get_pair = conf_get_pair_equal;
183         conf->process_pair = kboot_process_pair;
184         conf->parser_info = (void *)kboot_ignored_names;
185
186         for (filename = kboot_conf_files; *filename; filename++) {
187                 rc = parser_request_file(dc, dc->device, *filename, &buf, &len);
188                 if (rc)
189                         continue;
190
191                 conf_parse_buf(conf, buf, len);
192                 device_handler_status_dev_info(dc->handler, dc->device,
193                                 _("Parsed kboot configuration from %s"),
194                                 *filename);
195                 talloc_free(buf);
196         }
197
198         talloc_free(conf);
199         return 0;
200 }
201
202 static struct parser kboot_parser = {
203         .name                   = "kboot",
204         .parse                  = kboot_parse,
205         .resolve_resource       = resolve_devpath_resource,
206 };
207
208 register_parser(kboot_parser);