ppc: Increase #address-cells for ppc64
[openbios/afaerber.git] / libopenbios / bootinfo_load.c
blobc4dbbe5b191fb35a318d15b5d9e12faa5a6916dc
1 /*
3 * <bootinfo_load.c>
5 * bootinfo file loader
7 * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
9 * Original XML parser by Blue Swirl <blauwirbel@gmail.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2
17 #include "config.h"
18 #include "libopenbios/bindings.h"
19 #include "libopenbios/bootinfo_load.h"
20 #include "libopenbios/ofmem.h"
21 #include "libc/vsprintf.h"
23 //#define DEBUG_BOOTINFO
25 #ifdef DEBUG_BOOTINFO
26 #define DPRINTF(fmt, args...) \
27 do { printk("%s: " fmt, __func__ , ##args); } while (0)
28 #else
29 #define DPRINTF(fmt, args...) \
30 do { } while (0)
31 #endif
33 static char *
34 get_device( const char *path )
36 int i;
37 static char buf[1024];
39 for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++)
40 buf[i] = path[i];
41 buf[i] = 0;
43 return buf;
46 static char *
47 get_partition( const char *path )
49 static char buf[2];
51 buf[0] = '\0';
52 buf[1] = '\0';
54 while ( *path && *path != ':' )
55 path++;
57 if (!*path)
58 return buf;
59 path++;
61 if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */
62 return buf;
64 /* Must be a partition id */
65 buf[0] = path[0];
67 return buf;
70 static char *
71 get_filename( const char * path , char **dirname)
73 static char buf[1024];
74 char *filename;
76 while ( *path && *path != ':' )
77 path++;
79 if (!*path) {
80 *dirname = NULL;
81 return NULL;
83 path++;
85 while ( *path && isdigit(*path) )
86 path++;
88 if (*path == ',')
89 path++;
91 strncpy(buf, path, sizeof(buf));
92 buf[sizeof(buf) - 1] = 0;
94 filename = strrchr(buf, '\\');
95 if (filename) {
96 *dirname = buf;
97 (*filename++) = 0;
98 } else {
99 *dirname = NULL;
100 filename = buf;
103 return filename;
107 is_bootinfo(char *bootinfo)
109 return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1);
112 int
113 bootinfo_load(struct sys_info *info, const char *filename)
115 // Currently not implemented
116 return LOADER_NOT_SUPPORT;
120 Parse SGML structure like:
121 <chrp-boot>
122 <description>Debian/GNU Linux Installation on IBM CHRP hardware</description>
123 <os-name>Debian/GNU Linux for PowerPC</os-name>
124 <boot-script>boot &device;:\install\yaboot</boot-script>
125 <icon size=64,64 color-space=3,3,2>
127 CHRP system bindings are described at:
128 http://playground.sun.com/1275/bindings/chrp/chrp1_7a.ps
131 void
132 bootinfo_init_program(void)
134 char *base;
135 int proplen;
136 phandle_t chosen;
137 int tag, taglen, script, scriptlen, scriptvalid, entity, chrp;
138 char tagbuf[128], c;
139 char *device, *filename, *directory, *partition;
140 int current, size;
141 char *bootscript;
142 char *tmp;
143 char bootpath[1024];
145 /* Parse the boot script */
147 chosen = find_dev("/chosen");
148 tmp = get_property(chosen, "bootpath", &proplen);
149 memcpy(bootpath, tmp, proplen);
150 bootpath[proplen] = 0;
152 DPRINTF("bootpath %s\n", bootpath);
154 device = get_device(bootpath);
155 partition = get_partition(bootpath);
156 filename = get_filename(bootpath, &directory);
158 feval("load-base");
159 base = (char*)cell2pointer(POP());
161 feval("load-size");
162 size = POP();
164 bootscript = malloc(size);
165 if (bootscript == NULL) {
166 DPRINTF("Can't malloc %d bytes\n", size);
167 return;
170 if (!is_bootinfo(base)) {
171 DPRINTF("Not a valid bootinfo memory image\n");
172 return;
175 chrp = 0;
176 tag = 0;
177 taglen = 0;
178 script = 0;
179 scriptvalid = 0;
180 scriptlen = 0;
181 entity = 0;
182 current = 0;
183 while (current < size) {
185 c = base[current++];
187 if (c == '<') {
188 script = 0;
189 tag = 1;
190 taglen = 0;
191 } else if (c == '>') {
192 tag = 0;
193 tagbuf[taglen] = '\0';
194 if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
195 chrp = 1;
196 } else if (chrp == 1) {
197 if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
198 script = 1;
199 scriptlen = 0;
200 } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
202 script = 0;
203 bootscript[scriptlen] = '\0';
205 DPRINTF("got bootscript %s\n",
206 bootscript);
208 scriptvalid = -1;
210 break;
211 } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
212 break;
214 } else if (tag && taglen < sizeof(tagbuf)) {
215 tagbuf[taglen++] = c;
216 } else if (script && c == '&') {
217 entity = 1;
218 taglen = 0;
219 } else if (entity && c ==';') {
220 entity = 0;
221 tagbuf[taglen] = '\0';
222 if (strncasecmp(tagbuf, "lt", 2) == 0) {
223 bootscript[scriptlen++] = '<';
224 } else if (strncasecmp(tagbuf, "gt", 2) == 0) {
225 bootscript[scriptlen++] = '>';
226 } else if (strncasecmp(tagbuf, "device", 6) == 0) {
227 strcpy(bootscript + scriptlen, device);
228 scriptlen += strlen(device);
229 } else if (strncasecmp(tagbuf, "partition", 9) == 0) {
230 strcpy(bootscript + scriptlen, partition);
231 scriptlen += strlen(partition);
232 } else if (strncasecmp(tagbuf, "directory", 9) == 0) {
233 strcpy(bootscript + scriptlen, directory);
234 scriptlen += strlen(directory);
235 } else if (strncasecmp(tagbuf, "filename", 8) == 0) {
236 strcpy(bootscript + scriptlen, filename);
237 scriptlen += strlen(filename);
238 } else if (strncasecmp(tagbuf, "full-path", 9) == 0) {
239 strcpy(bootscript + scriptlen, bootpath);
240 scriptlen += strlen(bootpath);
241 } else { /* unknown, keep it */
242 bootscript[scriptlen] = '&';
243 strcpy(bootscript + scriptlen + 1, tagbuf);
244 scriptlen += taglen + 1;
245 bootscript[scriptlen] = ';';
246 scriptlen++;
248 } else if (entity && taglen < sizeof(tagbuf)) {
249 tagbuf[taglen++] = c;
250 } else if (script && scriptlen < size) {
251 bootscript[scriptlen++] = c;
255 /* If the payload is bootinfo then we execute it immediately */
256 if (scriptvalid) {
257 DPRINTF("bootscript: %s\n", bootscript);
258 feval(bootscript);
260 else
261 DPRINTF("Unable to parse bootinfo bootscript\n");