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");