discover/kboot: Fix boot_option initialisation
[petitboot] / discover / kboot-parser.c
1 #define _GNU_SOURCE
2
3 #include <assert.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "log/log.h"
8 #include "talloc/talloc.h"
9 #include "types/types.h"
10 #include "parser-conf.h"
11 #include "parser-utils.h"
12 #include "resource.h"
13
14 static void kboot_process_pair(struct conf_context *conf, const char *name,
15                 char *value)
16 {
17         const char *const *ignored_names = conf->parser_info;
18         struct discover_boot_option *d_opt;
19         struct boot_option *opt;
20         char *pos;
21         char *args;
22         const char *initrd;
23         const char *root;
24
25         /* ignore bare values */
26
27         if (!name)
28                 return;
29
30         if (conf_param_in_list(ignored_names, name))
31                 return;
32
33         if (conf_set_global_option(conf, name, value))
34                 return;
35
36         /* opt must be associated with dc */
37
38         d_opt = talloc_zero(conf->dc, struct discover_boot_option);
39         d_opt->device = conf->dc->device;
40         opt = talloc_zero(d_opt, struct boot_option);
41
42         if (!opt)
43                 return;
44
45         opt->id = talloc_asprintf(opt, "%s#%s", conf->dc->device->device->id,
46                         name);
47         opt->name = talloc_strdup(opt, name);
48         d_opt->option = opt;
49
50         args = talloc_strdup(opt, "");
51         initrd = conf_get_global_option(conf, "initrd");
52         root = conf_get_global_option(conf, "root");
53
54         pos = strchr(value, ' ');
55
56         /* if there's no space, it's only a kernel image with no params */
57
58         if (!pos)
59                 goto out_add;
60         *pos = 0;
61
62         for (pos++; pos;) {
63                 char *cl_name, *cl_value;
64
65                 pos = conf_get_pair_equal(conf, pos, &cl_name, &cl_value, ' ');
66
67                 if (!cl_name) {
68                         args = talloc_asprintf_append(args, "%s ", cl_value);
69                         continue;
70                 }
71
72                 if (streq(cl_name, "initrd")) {
73                         initrd = cl_value;
74                         continue;
75                 }
76
77                 if (streq(cl_name, "root")) {
78                         root = cl_value;
79                         continue;
80                 }
81
82                 args = talloc_asprintf_append(args, "%s=%s ", cl_name,
83                         cl_value);
84         }
85
86 out_add:
87         d_opt->boot_image = create_devpath_resource(opt,
88                                 conf->dc->device, value);
89
90         if (root) {
91                 opt->boot_args = talloc_asprintf(opt, "root=%s %s", root, args);
92                 talloc_free(args);
93         } else
94                 opt->boot_args = args;
95
96         if (initrd) {
97                 d_opt->initrd = create_devpath_resource(opt,
98                                 conf->dc->device, initrd);
99
100                 opt->description = talloc_asprintf(opt, "%s initrd=%s %s",
101                         value, initrd, opt->boot_args);
102         } else
103                 opt->description = talloc_asprintf(opt, "%s %s", value,
104                         opt->boot_args);
105
106         conf_strip_str(opt->boot_args);
107         conf_strip_str(opt->description);
108
109         discover_context_add_boot_option(conf->dc, d_opt);
110 }
111
112 static struct conf_global_option kboot_global_options[] = {
113         { .name = "initrd" },
114         { .name = "root" },
115         { .name = "video" },
116         { .name = NULL }
117 };
118
119 static const char *const kboot_conf_files[] = {
120         "/kboot.conf",
121         "/kboot.cnf",
122         "/etc/kboot.conf",
123         "/etc/kboot.cnf",
124         "/KBOOT.CONF",
125         "/KBOOT.CNF",
126         "/ETC/KBOOT.CONF",
127         "/ETC/KBOOT.CNF",
128         NULL
129 };
130
131 static const char *const kboot_ignored_names[] = {
132         "default",
133         "delay",
134         "message",
135         "timeout",
136         NULL
137 };
138
139 static int kboot_parse(struct discover_context *dc, char *buf, int len)
140 {
141         struct conf_context *conf;
142
143         conf = talloc_zero(dc, struct conf_context);
144
145         if (!conf)
146                 return 0;
147
148         conf->dc = dc;
149         conf->global_options = kboot_global_options,
150         conf_init_global_options(conf);
151         conf->get_pair = conf_get_pair_equal;
152         conf->process_pair = kboot_process_pair;
153         conf->parser_info = (void *)kboot_ignored_names,
154
155         conf_parse_buf(conf, buf, len);
156
157         talloc_free(conf);
158         return 1;
159 }
160
161 static struct parser kboot_parser = {
162         .name                   = "kboot",
163         .method                 = CONF_METHOD_LOCAL_FILE,
164         .parse                  = kboot_parse,
165         .filenames              = kboot_conf_files,
166         .resolve_resource       = resolve_devpath_resource,
167 };
168
169 register_parser(kboot_parser);