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