Added boot process information to help someone find out what really happens.
[bootos.git] / stage2 / kbootconf.c
blobb904467d7ef3b1d35e006aa45ee8584dc608c4a4
1 /* kbootcfg.c - kboot.cfg parsing
3 Copyright (C) 2010-2011 Hector Martin "marcan" <hector@marcansoft.com>
5 This code is licensed to you under the terms of the GNU GPL, version 2;
6 see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
7 */
9 /* See http://www.kernel.org/pub/linux/kernel/people/geoff/cell/ps3-linux-docs/ps3-linux-docs-08.06.09/mini-boot-conf.txt */
11 #include "types.h"
12 #include "string.h"
13 #include "kbootconf.h"
14 #include "debug.h"
16 char conf_buf[MAX_KBOOTCONF_SIZE];
18 struct kbootconf conf;
20 char *strip(char *buf)
22 while (*buf == ' ' || *buf == '\t')
23 buf++;
24 char *end = buf + strlen(buf) - 1;
25 while (*end == ' ' || *end == '\t')
26 *end-- = 0;
28 return buf;
31 void split(char *buf, char **left, char **right, char delim)
33 char *p = strchr(buf, delim);
35 if (p) {
36 *p = 0;
37 *left = strip(buf);
38 *right = strip(p+1);
39 } else {
40 *left = strip(buf);
41 *right = NULL;
45 int kbootconf_parse(void)
47 char *lp = conf_buf;
48 char *dflt = NULL;
49 char *dinitrd = NULL;
50 char *droot = NULL;
51 char tmpbuf[MAX_CMDLINE_SIZE];
52 int lineno = 1;
53 int i;
55 memset(&conf, 0, sizeof(conf));
57 conf.timeout = -1;
59 while(*lp) {
60 char *newline = strchr(lp, '\n');
61 char *next;
62 if (newline) {
63 *newline = 0;
64 next = newline+1;
65 } else {
66 next = lp+strlen(lp);
69 lp = strip(lp);
70 if (!*lp)
71 goto nextline;
73 char *left, *right;
75 split(lp, &left, &right, '=');
76 if (!right) {
77 printf("kboot.conf: parse error (line %d)\n", lineno);
78 goto nextline;
81 while(*right == '"' || *right == '\'')
82 right++;
83 char *rend = right + strlen(right) - 1;
84 while(*rend == '"' || *rend == '\'')
85 *rend-- = 0;
87 if (!strcmp(left, "timeout")) {
88 conf.timeout = my_atoi(right);
89 } else if (!strcmp(left, "default")) {
90 dflt = right;
91 } else if (!strcmp(left, "message")) {
92 conf.msgfile = right;
93 } else if (!strcmp(left, "initrd")) {
94 dinitrd = right;
95 } else if (!strcmp(left, "root")) {
96 droot = right;
97 } else if (!strcmp(left, "video")) {
98 // TODO: use
99 } else {
100 if (strlen(right) > MAX_CMDLINE_SIZE) {
101 printf("kboot.conf: maximum length exceeded (line %d)\n", lineno);
102 goto nextline;
104 conf.kernels[conf.num_kernels].label = left;
105 conf.kernels[conf.num_kernels].kernel = right;
106 char *p = strchr(right, ' ');
107 if (!p) {
108 // kernel, no arguments
109 conf.num_kernels++;
110 goto nextline;
112 *p++ = 0;
113 char *buf = p;
114 char *root = NULL;
115 char *initrd = NULL;
116 tmpbuf[0] = 0;
117 /* split commandline arguments and extract the useful bits */
118 while (*p) {
119 char *spc = strchr(p, ' ');
120 if (spc)
121 *spc++ = 0;
122 else
123 spc = p+strlen(p);
124 if (*p == 0) {
125 p = spc;
126 continue;
129 char *arg, *val;
130 split(p, &arg, &val, '=');
131 if (!val) {
132 strlcat(tmpbuf, arg, sizeof(tmpbuf));
133 strlcat(tmpbuf, " ", sizeof(tmpbuf));
134 } else if (!strcmp(arg, "root")) {
135 root = val;
136 } else if (!strcmp(arg, "initrd")) {
137 initrd = val;
138 } else {
139 strlcat(tmpbuf, arg, sizeof(tmpbuf));
140 strlcat(tmpbuf, "=", sizeof(tmpbuf));
141 strlcat(tmpbuf, val, sizeof(tmpbuf));
142 strlcat(tmpbuf, " ", sizeof(tmpbuf));
145 p = spc;
148 int len = strlen(tmpbuf);
149 if (len && tmpbuf[len-1] == ' ')
150 tmpbuf[--len] = 0;
151 len++;
153 // UGLY: tack on initrd and root onto tmpbuf, then copy it entirely
154 // on top of the original buffer (avoids having to deal with malloc)
155 conf.kernels[conf.num_kernels].parameters = buf;
156 if (initrd) {
157 strlcpy(tmpbuf+len, initrd, sizeof(tmpbuf)-len);
158 conf.kernels[conf.num_kernels].initrd = buf + len;
159 len += strlen(initrd)+1;
161 if (root) {
162 strlcpy(tmpbuf+len, root, sizeof(tmpbuf)-len);
163 conf.kernels[conf.num_kernels].root = buf + len;
164 len += strlen(root)+1;
166 memcpy(buf, tmpbuf, len);
167 conf.num_kernels++;
170 nextline:
171 lp = next;
172 lineno++;
175 conf.default_idx = 0;
176 for (i=0; i<conf.num_kernels; i++) {
177 if (dflt && !strcmp(conf.kernels[i].label, dflt))
178 conf.default_idx = i;
179 if (!conf.kernels[i].initrd && dinitrd)
180 conf.kernels[i].initrd = dinitrd;
181 if (!conf.kernels[i].root && droot)
182 conf.kernels[i].root = droot;
183 if (conf.kernels[i].initrd && !conf.kernels[i].root)
184 conf.kernels[i].root = "/dev/ram0";
187 printf("==== kboot.conf dump ====\n");
188 if (conf.timeout != -1)
189 printf("Timeout: %d\n", conf.timeout);
190 if (conf.msgfile)
191 printf("Message: %s\n", conf.msgfile);
193 for (i=0; i<conf.num_kernels; i++) {
194 printf("Entry #%d '%s'", i, conf.kernels[i].label);
195 if (conf.default_idx == i)
196 printf(" (default):\n");
197 else
198 printf(":\n");
199 printf(" Kernel: %s\n", conf.kernels[i].kernel);
200 if (conf.kernels[i].initrd)
201 printf(" Initrd: %s\n", conf.kernels[i].initrd);
202 if (conf.kernels[i].root)
203 printf(" Root: %s\n", conf.kernels[i].root);
204 if (conf.kernels[i].parameters)
205 printf(" Parameters: %s\n", conf.kernels[i].parameters);
208 printf("=========================\n");
209 return conf.num_kernels;