~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openbios/libopenbios/bootinfo_load.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *       <bootinfo_load.c>
 
4
 *
 
5
 *       bootinfo file loader
 
6
 *
 
7
 *   Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
 
8
 *
 
9
 *   Original XML parser by Blue Swirl <blauwirbel@gmail.com>
 
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
        /* 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);
 
169
 
 
170
        bootscript = malloc(size);
 
171
        if (bootscript == NULL) {
 
172
                DPRINTF("Can't malloc %d bytes\n", size);
 
173
                return;
 
174
        }
 
175
 
 
176
        if (!is_bootinfo(base)) {
 
177
                DPRINTF("Not a valid bootinfo memory image\n");
 
178
                free(bootscript);
 
179
                return;
 
180
        }
 
181
 
 
182
        chrp = 0;
 
183
        tag = 0;
 
184
        taglen = 0;
 
185
        script = 0;
 
186
        scriptvalid = 0;
 
187
        scriptlen = 0;
 
188
        entity = 0;
 
189
        current = 0;
 
190
        while (current < size) {
 
191
 
 
192
                c = base[current++];
 
193
 
 
194
                if (c == '<') {
 
195
                        script = 0;
 
196
                        tag = 1;
 
197
                        taglen = 0;
 
198
                } else if (c == '>') {
 
199
                        tag = 0;
 
200
                        tagbuf[taglen] = '\0';
 
201
                        if (strncasecmp(tagbuf, "chrp-boot", 9) == 0) {
 
202
                                chrp = 1;
 
203
                        } else if (chrp == 1) {
 
204
                                if (strncasecmp(tagbuf, "boot-script", 11) == 0) {
 
205
                                        script = 1;
 
206
                                        scriptlen = 0;
 
207
                                } else if (strncasecmp(tagbuf, "/boot-script", 12) == 0) {
 
208
 
 
209
                                        script = 0;
 
210
                                        bootscript[scriptlen] = '\0';
 
211
 
 
212
                                        DPRINTF("got bootscript %s\n",
 
213
                                                bootscript);
 
214
 
 
215
                                        scriptvalid = -1;
 
216
 
 
217
                                        break;
 
218
                                } else if (strncasecmp(tagbuf, "/chrp-boot", 10) == 0)
 
219
                                        break;
 
220
                        }
 
221
                } else if (tag && taglen < sizeof(tagbuf)) {
 
222
                        tagbuf[taglen++] = c;
 
223
                } else if (script && c == '&') {
 
224
                        entity = 1;
 
225
                        taglen = 0;
 
226
                } else if (entity && c ==';') {
 
227
                        entity = 0;
 
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] = ';';
 
253
                                scriptlen++;
 
254
                        }
 
255
                } else if (entity && taglen < sizeof(tagbuf)) {
 
256
                        tagbuf[taglen++] = c;
 
257
                } else if (script && scriptlen < size) {
 
258
                        bootscript[scriptlen++] = c;
 
259
                }
 
260
        }
 
261
 
 
262
        /* If the payload is bootinfo then we execute it immediately */
 
263
        if (scriptvalid) {
 
264
                DPRINTF("bootscript: %s\n", bootscript);
 
265
                feval(bootscript);
 
266
        }
 
267
        else
 
268
                DPRINTF("Unable to parse bootinfo bootscript\n");
 
269
}