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 bootscript = malloc(size);
165 if (bootscript == NULL) {
166 DPRINTF("Can't malloc %d bytes\n", size);
170 if (!is_bootinfo(base)) {
171 DPRINTF("Not a valid bootinfo memory image\n");
184 while (current < size) {
192 } else if (c == '>') {
194 tagbuf[taglen] = '\0';
195 if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
197 } else if (chrp == 1) {
198 if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
201 } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
204 bootscript[scriptlen] = '\0';
206 DPRINTF("got bootscript %s\n",
212 } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
215 } else if (tag && taglen < sizeof(tagbuf)) {
216 tagbuf[taglen++] = c;
217 } else if (script && c == '&') {
220 } else if (entity && c ==';') {
222 tagbuf[taglen] = '\0';
223 if (strncasecmp(tagbuf, "lt", 2) == 0) {
224 bootscript[scriptlen++] = '<';
225 } else if (strncasecmp(tagbuf, "gt", 2) == 0) {
226 bootscript[scriptlen++] = '>';
227 } else if (strncasecmp(tagbuf, "device", 6) == 0) {
228 strcpy(bootscript + scriptlen, device);
229 scriptlen += strlen(device);
230 } else if (strncasecmp(tagbuf, "partition", 9) == 0) {
231 strcpy(bootscript + scriptlen, partition);
232 scriptlen += strlen(partition);
233 } else if (strncasecmp(tagbuf, "directory", 9) == 0) {
234 strcpy(bootscript + scriptlen, directory);
235 scriptlen += strlen(directory);
236 } else if (strncasecmp(tagbuf, "filename", 8) == 0) {
237 strcpy(bootscript + scriptlen, filename);
238 scriptlen += strlen(filename);
239 } else if (strncasecmp(tagbuf, "full-path", 9) == 0) {
240 strcpy(bootscript + scriptlen, bootpath);
241 scriptlen += strlen(bootpath);
242 } else { /* unknown, keep it */
243 bootscript[scriptlen] = '&';
244 strcpy(bootscript + scriptlen + 1, tagbuf);
245 scriptlen += taglen + 1;
246 bootscript[scriptlen] = ';';
249 } else if (entity && taglen < sizeof(tagbuf)) {
250 tagbuf[taglen++] = c;
251 } else if (script && scriptlen < size) {
252 bootscript[scriptlen++] = c;
256 /* If the payload is bootinfo then we execute it immediately */
258 DPRINTF("bootscript: %s\n", bootscript);
262 DPRINTF("Unable to parse bootinfo bootscript\n");