|
|
1.1 root 1: /*
2: *
3: * <bootinfo_load.c>
4: *
5: * bootinfo file loader
6: *
7: * Copyright (C) 2009 Laurent Vivier ([email protected])
8: *
9: * Original XML parser by Blue Swirl <[email protected]>
10: *
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
14: *
15: */
16:
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"
22:
23: //#define DEBUG_BOOTINFO
24:
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
32:
33: static char *
34: get_device( const char *path )
35: {
36: int i;
37: static char buf[1024];
38:
39: for (i = 0; i < sizeof(buf) && path[i] && path[i] != ':'; i++)
40: buf[i] = path[i];
41: buf[i] = 0;
42:
43: return buf;
44: }
45:
46: static char *
47: get_partition( const char *path )
48: {
49: static char buf[2];
50:
51: buf[0] = '\0';
52: buf[1] = '\0';
53:
54: while ( *path && *path != ':' )
55: path++;
56:
57: if (!*path)
58: return buf;
59: path++;
60:
61: if (path[0] == ',' || !strchr(path, ',')) /* if there is not a ',' or no partition id then return */
62: return buf;
63:
64: /* Must be a partition id */
65: buf[0] = path[0];
66:
67: return buf;
68: }
69:
70: static char *
71: get_filename( const char * path , char **dirname)
72: {
73: static char buf[1024];
74: char *filename;
75:
76: while ( *path && *path != ':' )
77: path++;
78:
79: if (!*path) {
80: *dirname = NULL;
81: return NULL;
82: }
83: path++;
84:
85: while ( *path && isdigit(*path) )
86: path++;
87:
88: if (*path == ',')
89: path++;
90:
91: strncpy(buf, path, sizeof(buf));
92: buf[sizeof(buf) - 1] = 0;
93:
94: filename = strrchr(buf, '\\');
95: if (filename) {
96: *dirname = buf;
97: (*filename++) = 0;
98: } else {
99: *dirname = NULL;
100: filename = buf;
101: }
102:
103: return filename;
104: }
105:
106: int
107: is_bootinfo(char *bootinfo)
108: {
109: return (strncasecmp(bootinfo, "<chrp-boot", 10) ? 0 : -1);
110: }
111:
112: int
113: bootinfo_load(struct sys_info *info, const char *filename)
114: {
115: // Currently not implemented
116: return LOADER_NOT_SUPPORT;
117: }
118:
119: /*
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>
126:
127: CHRP system bindings are described at:
128: http://playground.sun.com/1275/bindings/chrp/chrp1_7a.ps
129: */
130:
131: void
132: bootinfo_init_program(void)
133: {
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];
144:
145: /* Parse the boot script */
146:
147: chosen = find_dev("/chosen");
148: tmp = get_property(chosen, "bootpath", &proplen);
149: memcpy(bootpath, tmp, proplen);
150: bootpath[proplen] = 0;
151:
152: DPRINTF("bootpath %s\n", bootpath);
153:
154: device = get_device(bootpath);
155: partition = get_partition(bootpath);
156: filename = get_filename(bootpath, &directory);
157:
158: feval("load-base");
159: base = (char*)cell2pointer(POP());
160:
161: feval("load-size");
162: size = POP();
163:
164: bootscript = malloc(size);
165: if (bootscript == NULL) {
166: DPRINTF("Can't malloc %d bytes\n", size);
167: return;
168: }
169:
170: if (!is_bootinfo(base)) {
171: DPRINTF("Not a valid bootinfo memory image\n");
172: free(bootscript);
173: return;
174: }
175:
176: chrp = 0;
177: tag = 0;
178: taglen = 0;
179: script = 0;
180: scriptvalid = 0;
181: scriptlen = 0;
182: entity = 0;
183: current = 0;
184: while (current < size) {
185:
186: c = base[current++];
187:
188: if (c == '<') {
189: script = 0;
190: tag = 1;
191: taglen = 0;
192: } else if (c == '>') {
193: tag = 0;
194: tagbuf[taglen] = '\0';
195: if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
196: chrp = 1;
197: } else if (chrp == 1) {
198: if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
199: script = 1;
200: scriptlen = 0;
201: } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
202:
203: script = 0;
204: bootscript[scriptlen] = '\0';
205:
206: DPRINTF("got bootscript %s\n",
207: bootscript);
208:
209: scriptvalid = -1;
210:
211: break;
212: } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
213: break;
214: }
215: } else if (tag && taglen < sizeof(tagbuf)) {
216: tagbuf[taglen++] = c;
217: } else if (script && c == '&') {
218: entity = 1;
219: taglen = 0;
220: } else if (entity && c ==';') {
221: entity = 0;
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] = ';';
247: scriptlen++;
248: }
249: } else if (entity && taglen < sizeof(tagbuf)) {
250: tagbuf[taglen++] = c;
251: } else if (script && scriptlen < size) {
252: bootscript[scriptlen++] = c;
253: }
254: }
255:
256: /* If the payload is bootinfo then we execute it immediately */
257: if (scriptvalid) {
258: DPRINTF("bootscript: %s\n", bootscript);
259: feval(bootscript);
260: }
261: else
262: DPRINTF("Unable to parse bootinfo bootscript\n");
263: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.