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
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
26 #define DPRINTF(fmt, args...) \
27 do { printk("%s: " fmt, __func__ , ##args); } while (0)
29 #define DPRINTF(fmt, args...) \
34 get_device( const char *path )
37 static char buf[1024];
39 for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++)
47 get_partition( const char *path )
54 while ( *path && *path != ':' )
61 if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */
64 /* Must be a partition id */
71 get_filename( const char * path , char **dirname)
73 static char buf[1024];
76 while ( *path && *path != ':' )
85 while ( *path && isdigit(*path) )
91 strncpy(buf, path, sizeof(buf));
92 buf[sizeof(buf) - 1] = 0;
94 filename = strrchr(buf, '\\');
107 is_bootinfo(char *bootinfo)
109 return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1);
113 bootinfo_load(struct sys_info *info, const char *filename)
115 // Currently not implemented
116 return LOADER_NOT_SUPPORT;
120 Parse SGML structure like:
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
132 bootinfo_init_program(void)
137 int tag, taglen, script, scriptlen, scriptvalid, entity, chrp;
139 char *device, *filename, *directory, *partition;
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);
159 base = (char*)cell2pointer(POP());
164 /* Some bootinfo scripts contain a binary payload after the
165 NULL-terminated Forth string such as OS 9. Restrict our
166 size to just the Forth section, otherwise we end up trying
167 to allocate memory for the entire binary which might fail. */
168 size = strnlen(base, size);
170 bootscript = malloc(size);
171 if (bootscript == NULL) {
172 DPRINTF("Can't malloc %d bytes\n", size);
176 if (!is_bootinfo(base)) {
177 DPRINTF("Not a valid bootinfo memory image\n");
190 while (current < size) {
198 } else if (c == '>') {
200 tagbuf[taglen] = '\0';
201 if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
203 } else if (chrp == 1) {
204 if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
207 } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
210 bootscript[scriptlen] = '\0';
212 DPRINTF("got bootscript %s\n",
218 } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
221 } else if (tag && taglen < sizeof(tagbuf)) {
222 tagbuf[taglen++] = c;
223 } else if (script && c == '&') {
226 } else if (entity && c ==';') {
228 tagbuf[taglen] = '\0';
229 if (strncasecmp(tagbuf, "lt", 2) == 0) {
230 bootscript[scriptlen++] = '<';
231 } else if (strncasecmp(tagbuf, "gt", 2) == 0) {
232 bootscript[scriptlen++] = '>';
233 } else if (strncasecmp(tagbuf, "device", 6) == 0) {
234 strcpy(bootscript + scriptlen, device);
235 scriptlen += strlen(device);
236 } else if (strncasecmp(tagbuf, "partition", 9) == 0) {
237 strcpy(bootscript + scriptlen, partition);
238 scriptlen += strlen(partition);
239 } else if (strncasecmp(tagbuf, "directory", 9) == 0) {
240 strcpy(bootscript + scriptlen, directory);
241 scriptlen += strlen(directory);
242 } else if (strncasecmp(tagbuf, "filename", 8) == 0) {
243 strcpy(bootscript + scriptlen, filename);
244 scriptlen += strlen(filename);
245 } else if (strncasecmp(tagbuf, "full-path", 9) == 0) {
246 strcpy(bootscript + scriptlen, bootpath);
247 scriptlen += strlen(bootpath);
248 } else { /* unknown, keep it */
249 bootscript[scriptlen] = '&';
250 strcpy(bootscript + scriptlen + 1, tagbuf);
251 scriptlen += taglen + 1;
252 bootscript[scriptlen] = ';';
255 } else if (entity && taglen < sizeof(tagbuf)) {
256 tagbuf[taglen++] = c;
257 } else if (script && scriptlen < size) {
258 bootscript[scriptlen++] = c;
262 /* If the payload is bootinfo then we execute it immediately */
264 DPRINTF("bootscript: %s\n", bootscript);
268 DPRINTF("Unable to parse bootinfo bootscript\n");