cb6a2483bc3092756e2d488a9b3e0b6588114745
[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 "paths.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
49         args = talloc_strdup(opt, "");
50         initrd = conf_get_global_option(conf, "initrd");
51         root = conf_get_global_option(conf, "root");
52
53         pos = strchr(value, ' ');
54
55         /* if there's no space, it's only a kernel image with no params */
56
57         if (!pos)
58                 goto out_add;
59         *pos = 0;
60
61         for (pos++; pos;) {
62                 char *cl_name, *cl_value;
63
64                 pos = conf_get_pair_equal(conf, pos, &cl_name, &cl_value, ' ');
65
66                 if (!cl_name) {
67                         args = talloc_asprintf_append(args, "%s ", cl_value);
68                         continue;
69                 }
70
71                 if (streq(cl_name, "initrd")) {
72                         initrd = cl_value;
73                         continue;
74                 }
75
76                 if (streq(cl_name, "root")) {
77                         root = cl_value;
78                         continue;
79                 }
80
81                 args = talloc_asprintf_append(args, "%s=%s ", cl_name,
82                         cl_value);
83         }
84
85 out_add:
86         opt->boot_image_file = resolve_path(opt, value,
87                         conf->dc->device->device_path);
88
89         if (root) {
90                 opt->boot_args = talloc_asprintf(opt, "root=%s %s", root, args);
91                 talloc_free(args);
92         } else
93                 opt->boot_args = args;
94
95         if (initrd) {
96                 opt->initrd_file = resolve_path(opt, initrd,
97                                 conf->dc->device->device_path);
98
99                 opt->description = talloc_asprintf(opt, "%s initrd=%s %s",
100                         value, initrd, opt->boot_args);
101         } else
102                 opt->description = talloc_asprintf(opt, "%s %s", value,
103                         opt->boot_args);
104
105         conf_strip_str(opt->boot_args);
106         conf_strip_str(opt->description);
107
108         discover_context_add_boot_option(conf->dc, d_opt);
109 }
110
111 static struct conf_global_option kboot_global_options[] = {
112         { .name = "initrd" },
113         { .name = "root" },
114         { .name = "video" },
115         { .name = NULL }
116 };
117
118 static const char *const kboot_conf_files[] = {
119         "/kboot.conf",
120         "/kboot.cnf",
121         "/etc/kboot.conf",
122         "/etc/kboot.cnf",
123         "/KBOOT.CONF",
124         "/KBOOT.CNF",
125         "/ETC/KBOOT.CONF",
126         "/ETC/KBOOT.CNF",
127         NULL
128 };
129
130 static const char *const kboot_ignored_names[] = {
131         "default",
132         "delay",
133         "message",
134         "timeout",
135         NULL
136 };
137
138 static int kboot_parse(struct discover_context *dc, char *buf, int len)
139 {
140         struct conf_context *conf;
141
142         conf = talloc_zero(dc, struct conf_context);
143
144         if (!conf)
145                 return 0;
146
147         conf->dc = dc;
148         conf->global_options = kboot_global_options,
149         conf_init_global_options(conf);
150         conf->get_pair = conf_get_pair_equal;
151         conf->process_pair = kboot_process_pair;
152         conf->parser_info = (void *)kboot_ignored_names,
153
154         conf_parse_buf(conf, buf, len);
155
156         talloc_free(conf);
157         return 1;
158 }
159
160 struct parser __kboot_parser = {
161         .name           = "kboot",
162         .parse          = kboot_parse,
163         .filenames      = kboot_conf_files,
164 };