27b4b782306594c05cbaec0fd3b01bc826a409de
[petitboot] / yaboot-parser.c
1
2 #include "parser.h"
3 #include "params.h"
4 #include "paths.h"
5 #include "yaboot-cfg.h"
6
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <ctype.h>
15 #include <sys/param.h>
16
17 static struct device *dev;
18 static char *devpath;
19 static char *defimage;
20
21 char *
22 make_params(char *label, char *params)
23 {
24      char *p, *q;
25      static char buffer[2048];
26
27      q = buffer;
28      *q = 0;
29
30      p = cfg_get_strg(label, "literal");
31      if (p) {
32           strcpy(q, p);
33           q = strchr(q, 0);
34           if (params) {
35                if (*p)
36                     *q++ = ' ';
37                strcpy(q, params);
38           }
39           return buffer;
40      }
41
42      p = cfg_get_strg(label, "root");
43      if (p) {
44           strcpy (q, "root=");
45           strcpy (q + 5, p);
46           q = strchr (q, 0);
47           *q++ = ' ';
48      }
49      if (cfg_get_flag(label, "read-only")) {
50           strcpy (q, "ro ");
51           q += 3;
52      }
53      if (cfg_get_flag(label, "read-write")) {
54           strcpy (q, "rw ");
55           q += 3;
56      }
57      p = cfg_get_strg(label, "ramdisk");
58      if (p) {
59           strcpy (q, "ramdisk=");
60           strcpy (q + 8, p);
61           q = strchr (q, 0);
62           *q++ = ' ';
63      }
64      p = cfg_get_strg(label, "initrd-size");
65      if (p) {
66           strcpy (q, "ramdisk_size=");
67           strcpy (q + 13, p);
68           q = strchr (q, 0);
69           *q++ = ' ';
70      }
71      if (cfg_get_flag(label, "novideo")) {
72           strcpy (q, "video=ofonly");
73           q = strchr (q, 0);
74           *q++ = ' ';
75      }
76      p = cfg_get_strg (label, "append");
77      if (p) {
78           strcpy (q, p);
79           q = strchr (q, 0);
80           *q++ = ' ';
81      }
82      *q = 0;
83      if (params)
84           strcpy(q, params);
85
86      return buffer;
87 }
88
89 static int check_and_add_device(struct device *dev)
90 {
91         if (!dev->icon_file)
92                 dev->icon_file = strdup(generic_icon_file(guess_device_type()));
93
94         return !add_device(dev);
95 }
96
97 void process_image(char *label)
98 {
99         struct boot_option opt;
100         char *cfgopt;
101
102         memset(&opt, 0, sizeof(opt));
103
104         opt.name = label;
105         cfgopt = cfg_get_strg(label, "image");
106         opt.boot_image_file = resolve_path(cfgopt, devpath);
107         if (cfgopt == defimage)
108                 pb_log("This one is default. What do we do about it?\n");
109
110         cfgopt = cfg_get_strg(label, "initrd");
111         if (cfgopt)
112                 opt.initrd_file = resolve_path(cfgopt, devpath);
113
114         opt.boot_args = make_params(label, NULL);
115
116         add_boot_option(&opt);
117
118         if (opt.initrd_file)
119                 free(opt.initrd_file);
120 }
121
122 static int yaboot_parse(const char *device)
123 {
124         char *filepath;
125         char *conf_file;
126         char *tmpstr;
127         ssize_t conf_len;
128         int fd;
129         struct stat st;
130         char *label;
131
132         devpath = strdup(device);
133
134         filepath = resolve_path("/etc/yaboot.conf", devpath);
135
136         fd = open(filepath, O_RDONLY);
137         if (fd < 0) {
138                 free(filepath);
139                 filepath = resolve_path("/yaboot.conf", devpath);
140                 fd = open(filepath, O_RDONLY);
141                 
142                 if (fd < 0)
143                         return 0;
144         }
145
146         if (fstat(fd, &st)) {
147                 close(fd);
148                 return 0;
149         }
150
151         conf_file = malloc(st.st_size+1);
152         if (!conf_file) {
153                 close(fd);
154                 return 0;
155         }
156         
157         conf_len = read(fd, conf_file, st.st_size);
158         if (conf_len < 0) {
159                 close(fd);
160                 return 0;
161         }
162         conf_file[conf_len] = 0;
163
164         close(fd);
165         
166         if (cfg_parse(filepath, conf_file, conf_len)) {
167                 pb_log("Error parsing yaboot.conf\n");
168                 return 0;
169         }
170
171         free(filepath);
172
173         dev = malloc(sizeof(*dev));
174         memset(dev, 0, sizeof(*dev));
175         dev->id = strdup(devpath);
176         if (cfg_get_strg(0, "init-message")) {
177                 char *newline;
178                 dev->description = strdup(cfg_get_strg(0, "init-message"));
179                 newline = strchr(dev->description, '\n');
180                 if (newline)
181                         *newline = 0;
182         }
183         dev->icon_file = strdup(generic_icon_file(guess_device_type()));
184
185         /* If we have a 'partiton=' directive, update the default devpath
186          * to use that instead of the current device */
187         tmpstr = cfg_get_strg(0, "partition");
188         if (tmpstr) {
189                 char *endp;
190                 int partnr = strtol(tmpstr, &endp, 10);
191                 if (endp != tmpstr && !*endp) {
192                         char *new_dev, *tmp;
193
194                         new_dev = malloc(strlen(devpath) + strlen(tmpstr) + 1);
195                         if (!new_dev)
196                                 return 0;
197
198                         strcpy(new_dev, devpath);
199
200                         /* Strip digits (partition number) from string */
201                         endp = new_dev + strlen(devpath) - 1;
202                         while (isdigit(*endp))
203                                 *(endp--) = 0;
204
205                         /* and add our own... */
206                         sprintf(endp + 1, "%d", partnr);
207
208                         tmp = devpath;
209                         devpath = parse_device_path(new_dev, devpath);
210                         free(tmp);
211                         free(new_dev);
212                 }
213         }
214
215         defimage = cfg_get_default();
216         if (!defimage)
217                 return 0;
218         defimage = cfg_get_strg(defimage, "image");
219
220         label = cfg_next_image(NULL);
221         if (!label || !check_and_add_device(dev))
222                 return 0;
223
224         do {
225                 process_image(label);
226         } while ((label = cfg_next_image(label)));
227
228         return 1;
229 }
230
231 struct parser yaboot_parser = {
232         .name = "yaboot.conf parser",
233         .priority = 99,
234         .parse    = yaboot_parse
235 };