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

« back to all changes in this revision

Viewing changes to roms/openbios/arch/sparc32/romvec.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
 * PROM interface support
 
3
 * Copyright 1996 The Australian National University.
 
4
 * Copyright 1996 Fujitsu Laboratories Limited
 
5
 * Copyright 1999 Pete A. Zaitcev
 
6
 * This software may be distributed under the terms of the Gnu
 
7
 * Public License version 2 or later
 
8
 */
 
9
 
 
10
#include <stdarg.h>
 
11
 
 
12
#include "openprom.h"
 
13
#include "config.h"
 
14
#include "libopenbios/bindings.h"
 
15
#include "drivers/drivers.h"
 
16
#include "libopenbios/sys_info.h"
 
17
#include "boot.h"
 
18
#include "romvec.h"
 
19
 
 
20
#ifdef CONFIG_DEBUG_OBP
 
21
#define DPRINTF(fmt, args...)                   \
 
22
    do { printk(fmt , ##args); } while (0)
 
23
#else
 
24
#define DPRINTF(fmt, args...)
 
25
#endif
 
26
 
 
27
char obp_stdin, obp_stdout;
 
28
const char *obp_stdin_path, *obp_stdout_path;
 
29
 
 
30
struct linux_arguments_v0 obp_arg;
 
31
const char *bootpath;
 
32
static const struct linux_arguments_v0 * const obp_argp = &obp_arg;
 
33
 
 
34
static void (*sync_hook)(void);
 
35
 
 
36
static struct linux_romvec romvec0;
 
37
 
 
38
static void doublewalk(__attribute__((unused)) unsigned int ptab1,
 
39
                       __attribute__((unused)) unsigned int va)
 
40
{
 
41
}
 
42
 
 
43
int obp_nextnode(int node)
 
44
{
 
45
    int peer;
 
46
 
 
47
    PUSH(node);
 
48
    fword("peer");
 
49
    peer = POP();
 
50
    DPRINTF("obp_nextnode(0x%x) = 0x%x\n", node, peer);
 
51
 
 
52
    return peer;
 
53
}
 
54
 
 
55
int obp_child(int node)
 
56
{
 
57
    int child;
 
58
 
 
59
    PUSH(node);
 
60
    fword("child");
 
61
    child = POP();
 
62
    DPRINTF("obp_child(0x%x) = 0x%x\n", node, child);
 
63
 
 
64
    return child;
 
65
}
 
66
 
 
67
int obp_proplen(int node, const char *name)
 
68
{
 
69
    int notfound;
 
70
 
 
71
    if (!node) {
 
72
        DPRINTF("obp_proplen(0x0, %s) = -1\n", name);
 
73
        return -1;
 
74
    }
 
75
 
 
76
    push_str(name);
 
77
    PUSH(node);
 
78
    fword("get-package-property");
 
79
    notfound = POP();
 
80
 
 
81
    if (notfound) {
 
82
        DPRINTF("obp_proplen(0x%x, %s) (not found)\n", node, name);
 
83
 
 
84
        return -1;
 
85
    } else {
 
86
        int len;
 
87
 
 
88
        len = POP();
 
89
        (void) POP();
 
90
        DPRINTF("obp_proplen(0x%x, %s) = %d\n", node, name, len);
 
91
 
 
92
        return len;
 
93
    }
 
94
}
 
95
 
 
96
#ifdef CONFIG_DEBUG_OBP
 
97
static int looks_like_string(const char *str, int len)
 
98
{
 
99
    int i;
 
100
    int ret = (str[len-1] == '\0');
 
101
    for (i = 0; i < len-1 && ret; i++)
 
102
    {
 
103
        int ch = str[i] & 0xFF;
 
104
        if (ch < 0x20 || ch > 0x7F)
 
105
            ret = 0;
 
106
    }
 
107
    return ret;
 
108
}
 
109
#endif
 
110
 
 
111
int obp_getprop(int node, const char *name, char *value)
 
112
{
 
113
    int notfound, found;
 
114
    int len;
 
115
    const char *str;
 
116
 
 
117
    if (!node) {
 
118
        DPRINTF("obp_getprop(0x0, %s) = -1\n", name);
 
119
        return -1;
 
120
    }
 
121
 
 
122
    if (!name) {
 
123
        // NULL name means get first property
 
124
        push_str("");
 
125
        PUSH(node);
 
126
        fword("next-property");
 
127
        found = POP();
 
128
        if (found) {
 
129
            len = POP();
 
130
            str = (char *) POP();
 
131
            DPRINTF("obp_getprop(0x%x, NULL) = %s\n", node, str);
 
132
 
 
133
            return (int)str;
 
134
        }
 
135
        DPRINTF("obp_getprop(0x%x, NULL) (not found)\n", node);
 
136
 
 
137
        return -1;
 
138
    } else {
 
139
        push_str(name);
 
140
        PUSH(node);
 
141
        fword("get-package-property");
 
142
        notfound = POP();
 
143
    }
 
144
    if (notfound) {
 
145
        DPRINTF("obp_getprop(0x%x, %s) (not found)\n", node, name);
 
146
 
 
147
        return -1;
 
148
    } else {
 
149
        len = POP();
 
150
        str = (char *) POP();
 
151
        if (len > 0)
 
152
            memcpy(value, str, len);
 
153
        else
 
154
            str = "NULL";
 
155
 
 
156
#ifdef CONFIG_DEBUG_OBP
 
157
        if (looks_like_string(str, len)) {
 
158
            DPRINTF("obp_getprop(0x%x, %s) = %s\n", node, name, str);
 
159
        } else {
 
160
            int i;
 
161
            DPRINTF("obp_getprop(0x%x, %s) = ", node, name);
 
162
            for (i = 0; i < len; i++) {
 
163
                DPRINTF("%02x%s", str[i] & 0xFF,
 
164
                        (len == 4 || i == len-1) ? "" : " ");
 
165
            }
 
166
            DPRINTF("\n");
 
167
        }
 
168
#endif
 
169
 
 
170
        return len;
 
171
    }
 
172
}
 
173
 
 
174
const char *obp_nextprop(int node, const char *name)
 
175
{
 
176
    int found;
 
177
 
 
178
    if (!name || *name == '\0') {
 
179
        // NULL name means get first property
 
180
        push_str("");
 
181
        name = "NULL";
 
182
    } else {
 
183
        push_str(name);
 
184
    }
 
185
    PUSH(node);
 
186
    fword("next-property");
 
187
    found = POP();
 
188
    if (!found) {
 
189
        DPRINTF("obp_nextprop(0x%x, %s) (not found)\n", node, name);
 
190
 
 
191
        return "";
 
192
    } else {
 
193
        char *str;
 
194
 
 
195
        POP(); /* len */
 
196
        str = (char *) POP();
 
197
 
 
198
        DPRINTF("obp_nextprop(0x%x, %s) = %s\n", node, name, str);
 
199
 
 
200
        return str;
 
201
    }
 
202
}
 
203
 
 
204
int obp_setprop(__attribute__((unused)) int node,
 
205
                       __attribute__((unused)) const char *name,
 
206
                       __attribute__((unused)) char *value,
 
207
                       __attribute__((unused)) int len)
 
208
{
 
209
    DPRINTF("obp_setprop(0x%x, %s) = %s (%d)\n", node, name, value, len);
 
210
 
 
211
    return -1;
 
212
}
 
213
 
 
214
static const struct linux_nodeops nodeops0 = {
 
215
    obp_nextnode_handler,       /* int (*no_nextnode)(int node); */
 
216
    obp_child_handler,          /* int (*no_child)(int node); */
 
217
    obp_proplen_handler,        /* int (*no_proplen)(int node, char *name); */
 
218
    obp_getprop_handler,        /* int (*no_getprop)(int node,char *name,char *val); */
 
219
    obp_setprop_handler,        /* int (*no_setprop)(int node, char *name,
 
220
                                char *val, int len); */
 
221
    obp_nextprop_handler        /* char * (*no_nextprop)(int node, char *name); */
 
222
};
 
223
 
 
224
int obp_nbgetchar(void)
 
225
{
 
226
    return getchar();
 
227
}
 
228
 
 
229
int obp_nbputchar(int ch)
 
230
{
 
231
    putchar(ch);
 
232
 
 
233
    return 0;
 
234
}
 
235
 
 
236
void obp_putstr(char *str, int len)
 
237
{
 
238
    PUSH(pointer2cell(str));
 
239
    PUSH(len);
 
240
    fword("type");
 
241
}
 
242
 
 
243
void obp_printf(const char *fmt, ...)
 
244
{
 
245
    va_list ap;
 
246
 
 
247
    va_start(ap, fmt);
 
248
    printk(fmt, ap);
 
249
    va_end(ap);
 
250
}
 
251
 
 
252
void obp_reboot(char *str)
 
253
{
 
254
    printk("rebooting (%s)\n", str);
 
255
    *reset_reg = 1;
 
256
    printk("reboot failed\n");
 
257
    for (;;) {}
 
258
}
 
259
 
 
260
void obp_abort(void)
 
261
{
 
262
    printk("abort, power off\n");
 
263
    *power_reg = 1;
 
264
    printk("power off failed\n");
 
265
    for (;;) {}
 
266
}
 
267
 
 
268
void obp_halt(void)
 
269
{
 
270
    printk("halt, power off\n");
 
271
    *power_reg = 1;
 
272
    printk("power off failed\n");
 
273
    for (;;) {}
 
274
}
 
275
 
 
276
int obp_devopen(char *str)
 
277
{
 
278
    int ret;
 
279
 
 
280
    push_str(str);
 
281
    fword("open-dev");
 
282
    ret = POP();
 
283
    DPRINTF("obp_devopen(%s) = 0x%x\n", str, ret);
 
284
 
 
285
    return ret;
 
286
}
 
287
 
 
288
int obp_devclose(int dev_desc)
 
289
{
 
290
    int ret = 1;
 
291
 
 
292
    PUSH(dev_desc);
 
293
    fword("close-dev");
 
294
 
 
295
    DPRINTF("obp_devclose(0x%x) = %d\n", dev_desc, ret);
 
296
 
 
297
    return ret;
 
298
}
 
299
 
 
300
int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf)
 
301
{
 
302
    int ret, hi, lo, bs;
 
303
 
 
304
    bs = 512;
 
305
    hi = ((uint64_t)offset * bs) >> 32;
 
306
    lo = ((uint64_t)offset * bs) & 0xffffffff;
 
307
 
 
308
    ret = obp_devseek(dev_desc, hi, lo);
 
309
 
 
310
    ret = obp_devread(dev_desc, buf, num_blks * bs) / bs;
 
311
 
 
312
    DPRINTF("obp_rdblkdev(fd 0x%x, num_blks %d, offset %d (hi %d lo %d), buf 0x%x) = %d\n", dev_desc, num_blks, offset, hi, lo, (int)buf, ret);
 
313
 
 
314
    return ret;
 
315
}
 
316
 
 
317
int obp_devread(int dev_desc, char *buf, int nbytes)
 
318
{
 
319
    int ret;
 
320
 
 
321
    PUSH((int)buf);
 
322
    PUSH(nbytes);
 
323
    push_str("read");
 
324
    PUSH(dev_desc);
 
325
    fword("$call-method");
 
326
    ret = POP();
 
327
 
 
328
    DPRINTF("obp_devread(fd 0x%x, buf 0x%x, nbytes %d) = %d\n", dev_desc, (int)buf, nbytes, ret);
 
329
 
 
330
    return ret;
 
331
}
 
332
 
 
333
int obp_devwrite(int dev_desc, char *buf, int nbytes)
 
334
{
 
335
#ifdef CONFIG_DEBUG_OBP_DEVWRITE /* disabled, makes too much noise */
 
336
    int ret;
 
337
#endif
 
338
 
 
339
    PUSH((int)buf);
 
340
    PUSH(nbytes);
 
341
    push_str("write");
 
342
    PUSH(dev_desc);
 
343
    fword("$call-method");
 
344
#ifdef CONFIG_DEBUG_OBP_DEVWRITE
 
345
    ret = POP();
 
346
    DPRINTF("obp_devwrite(fd 0x%x, buf %s, nbytes %d) = %d\n", dev_desc, buf, nbytes, ret);
 
347
#else
 
348
    POP();
 
349
#endif
 
350
 
 
351
    return nbytes;
 
352
}
 
353
 
 
354
int obp_devseek(int dev_desc, int hi, int lo)
 
355
{
 
356
    int ret;
 
357
 
 
358
    PUSH(lo);
 
359
    PUSH(hi);
 
360
    push_str("seek");
 
361
    PUSH(dev_desc);
 
362
    fword("$call-method");
 
363
    ret = POP();
 
364
 
 
365
    DPRINTF("obp_devseek(fd 0x%x, hi %d, lo %d) = %d\n", dev_desc, hi, lo, ret);
 
366
 
 
367
    return ret;
 
368
}
 
369
 
 
370
int obp_inst2pkg(int dev_desc)
 
371
{
 
372
    int ret;
 
373
 
 
374
    PUSH(dev_desc);
 
375
    fword("ihandle>non-interposed-phandle");
 
376
    ret = POP();
 
377
 
 
378
    DPRINTF("obp_inst2pkg(fd 0x%x) = 0x%x\n", dev_desc, ret);
 
379
 
 
380
    return ret;
 
381
}
 
382
 
 
383
int obp_cpustart(__attribute__((unused))unsigned int whichcpu,
 
384
                        __attribute__((unused))int ctxtbl_ptr,
 
385
                        __attribute__((unused))int thiscontext,
 
386
                        __attribute__((unused))char *prog_counter)
 
387
{
 
388
    int cpu, found;
 
389
    struct linux_prom_registers *smp_ctable = (void *)ctxtbl_ptr;
 
390
 
 
391
    DPRINTF("obp_cpustart: cpu %d, ctxptr 0x%x, ctx %d, pc 0x%x\n", whichcpu,
 
392
            smp_ctable->phys_addr, thiscontext, (unsigned int)prog_counter);
 
393
 
 
394
    found = obp_getprop(whichcpu, "mid", (char *)&cpu);
 
395
    if (found == -1)
 
396
        return -1;
 
397
    DPRINTF("cpu found, id %d -> cpu %d\n", whichcpu, cpu);
 
398
 
 
399
    return start_cpu((unsigned int)prog_counter, ((unsigned int)smp_ctable->phys_addr) >> 4,
 
400
              thiscontext, cpu);
 
401
}
 
402
 
 
403
int obp_cpustop(__attribute__((unused)) unsigned int whichcpu)
 
404
{
 
405
    DPRINTF("obp_cpustop: cpu %d\n", whichcpu);
 
406
 
 
407
    return 0;
 
408
}
 
409
 
 
410
int obp_cpuidle(__attribute__((unused)) unsigned int whichcpu)
 
411
{
 
412
    DPRINTF("obp_cpuidle: cpu %d\n", whichcpu);
 
413
 
 
414
    return 0;
 
415
}
 
416
 
 
417
int obp_cpuresume(__attribute__((unused)) unsigned int whichcpu)
 
418
{
 
419
    DPRINTF("obp_cpuresume: cpu %d\n", whichcpu);
 
420
 
 
421
    return 0;
 
422
}
 
423
 
 
424
void obp_fortheval_v2(char *str, int arg0, int arg1, int arg2, int arg3, int arg4)
 
425
{
 
426
  int dstacktmp = 0;
 
427
 
 
428
  // It seems Solaris passes up to 5 arguments which should be pushed onto the Forth
 
429
  // stack for execution. However the API doesn't provide for a way to specify the number
 
430
  // of arguments actually being passed. Hence we preserve the state of the Forth stack 
 
431
  // before, push all the arguments, execute the Forth, then restore the stack to its 
 
432
  // previous state. This enables us to have a variable number of arguments and still 
 
433
  // preserve stack state between subsequent calls.
 
434
 
 
435
  // Preserve stack state
 
436
  dstacktmp = dstackcnt;
 
437
 
 
438
  PUSH(arg4);
 
439
  PUSH(arg3);
 
440
  PUSH(arg2);
 
441
  PUSH(arg1);
 
442
  PUSH(arg0);
 
443
 
 
444
  DPRINTF("obp_fortheval_v2(%x %x %x %x %x %s)\n", arg4, arg3, arg2, arg1, arg0, str);
 
445
  push_str(str);
 
446
  fword("eval");
 
447
 
 
448
  // Restore stack state
 
449
  dstackcnt = dstacktmp;
 
450
}
 
451
 
 
452
volatile uint32_t *obp_ticks;
 
453
 
 
454
void *
 
455
init_openprom(void)
 
456
{
 
457
    /* Setup the openprom vector. Note that all functions should be invoked
 
458
       via their handler (see call-romvec.S) which acts as a proxy to save
 
459
       the globals and setup the stack correctly */
 
460
 
 
461
    // Linux wants a R/W romvec table
 
462
    romvec0.pv_magic_cookie = LINUX_OPPROM_MAGIC;
 
463
    romvec0.pv_romvers = 3;
 
464
    romvec0.pv_plugin_revision = 2;
 
465
    romvec0.pv_printrev = 0x20019;
 
466
    romvec0.pv_v0mem.v0_totphys = NULL;
 
467
    romvec0.pv_v0mem.v0_prommap = NULL;
 
468
    romvec0.pv_v0mem.v0_available = NULL;
 
469
    romvec0.pv_nodeops = &nodeops0;
 
470
    romvec0.pv_bootstr = (void *)doublewalk;
 
471
    romvec0.pv_v0devops.v0_devopen = &obp_devopen_handler;
 
472
    romvec0.pv_v0devops.v0_devclose = &obp_devclose_handler;
 
473
    romvec0.pv_v0devops.v0_rdblkdev = &obp_rdblkdev_handler;
 
474
    romvec0.pv_stdin = &obp_stdin;
 
475
    romvec0.pv_stdout = &obp_stdout;
 
476
    romvec0.pv_getchar = obp_nbgetchar_handler;
 
477
    romvec0.pv_putchar = (void (*)(int))obp_nbputchar_handler;
 
478
    romvec0.pv_nbgetchar = obp_nbgetchar_handler;
 
479
    romvec0.pv_nbputchar = obp_nbputchar_handler;
 
480
    romvec0.pv_putstr = obp_putstr_handler;
 
481
    romvec0.pv_reboot = obp_reboot_handler;
 
482
    romvec0.pv_printf = obp_printf_handler;
 
483
    romvec0.pv_abort = obp_abort_handler;
 
484
    
 
485
    /* Point to the Forth obp-ticks variable and reset */
 
486
    fword("obp-ticks");
 
487
    obp_ticks = cell2pointer(POP());
 
488
    *obp_ticks = 0;
 
489
    romvec0.pv_ticks = obp_ticks;
 
490
    
 
491
    romvec0.pv_halt = obp_halt_handler;
 
492
    romvec0.pv_synchook = &sync_hook;
 
493
    romvec0.pv_v0bootargs = &obp_argp;
 
494
    romvec0.pv_fortheval.v2_eval = obp_fortheval_v2_handler;
 
495
    romvec0.pv_v2devops.v2_inst2pkg = obp_inst2pkg_handler;
 
496
    romvec0.pv_v2devops.v2_dumb_mem_alloc = obp_dumb_memalloc_handler;
 
497
    romvec0.pv_v2devops.v2_dumb_mem_free = obp_dumb_memfree_handler;
 
498
    romvec0.pv_v2devops.v2_dumb_mmap = obp_dumb_mmap_handler;
 
499
    romvec0.pv_v2devops.v2_dumb_munmap = obp_dumb_munmap_handler;
 
500
    romvec0.pv_v2devops.v2_dev_open = obp_devopen_handler;
 
501
    romvec0.pv_v2devops.v2_dev_close = (void (*)(int))obp_devclose_handler;
 
502
    romvec0.pv_v2devops.v2_dev_read = obp_devread_handler;
 
503
    romvec0.pv_v2devops.v2_dev_write = obp_devwrite_handler;
 
504
    romvec0.pv_v2devops.v2_dev_seek = obp_devseek_handler;
 
505
 
 
506
    romvec0.pv_v2bootargs.bootpath = &bootpath;
 
507
 
 
508
    romvec0.pv_v2bootargs.bootargs = &obp_arg.argv[1];
 
509
 
 
510
    /* Point fd_stdin/fd_stdout to the Forth stdin/stdout variables */
 
511
    fword("stdin");
 
512
    romvec0.pv_v2bootargs.fd_stdin = cell2pointer(POP());
 
513
    fword("stdout");
 
514
    romvec0.pv_v2bootargs.fd_stdout = cell2pointer(POP());
 
515
 
 
516
    romvec0.v3_memalloc = obp_memalloc_handler;
 
517
 
 
518
    romvec0.v3_cpustart = obp_cpustart_handler;
 
519
    romvec0.v3_cpustop = obp_cpustop_handler;
 
520
    romvec0.v3_cpuidle = obp_cpuidle_handler;
 
521
    romvec0.v3_cpuresume = obp_cpuresume_handler;
 
522
 
 
523
    return &romvec0;
 
524
}