|
|
1.1 root 1: /* tag: hosted forth environment, executable code
2: *
3: * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer
4: *
5: * See the file "COPYING" for further information about
6: * the copyright and warranty status of this work.
7: */
8:
9: #include <stdio.h>
10: #include <stdint.h>
11: #include <stdlib.h>
12: #include <string.h>
13: #include <signal.h>
14: #define __USE_LARGEFILE64
15: #include <fcntl.h>
16: #include <unistd.h>
17: #include <termios.h>
18: #include <sys/types.h>
19: #include <sys/stat.h>
20: #include <stdarg.h>
21:
22: #ifdef __GLIBC__
23: #define _GNU_SOURCE
24: #include <getopt.h>
25: #endif
26:
27: #include "sysinclude.h"
28: #include "mconfig.h"
29: #include "config.h"
30: #include "kernel/kernel.h"
31: #include "dict.h"
32: #include "kernel/stack.h"
33: #include "arch/unix/plugins.h"
34: #include "libopenbios/bindings.h"
35: #include "libopenbios/openbios.h"
36: #include "openbios-version.h"
37:
38: #include "blk.h"
39: #include "libopenbios/ofmem.h"
40:
41: #define MEMORY_SIZE (4*1024*1024) /* 4M ram for hosted system */
42: #define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */
43:
44: #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64)
45: #define lseek lseek64
46: #define __LFS O_LARGEFILE
47: #else
48: #define __LFS 0
49: #endif
50:
51: /* prototypes */
52: static void exit_terminal(void);
53: void boot(void);
54:
55: unsigned long virt_offset = 0;
56:
57: /* local variables */
58:
59: static ucell *memory;
60:
61: static int diskemu;
62:
63: static int segfault = 0;
64: static int verbose = 0;
65:
66: #if defined(CONFIG_PPC) || defined(CONFIG_SPARC64)
67: unsigned long isa_io_base;
68: #endif
69:
70: int errno_int; /* implement for fs drivers, needed to build on Mac OS X */
71:
72: ucell ofmem_claim(ucell addr, ucell size, ucell align)
73: {
74: return 0;
75: }
76:
77: #ifdef CONFIG_PPC
78: extern void flush_icache_range(char *start, char *stop);
79:
80: void flush_icache_range(char *start, char *stop)
81: {
82: }
83: #endif
84:
85: #if 0
86: static void write_dictionary(char *filename)
87: {
88: FILE *f;
89: xt_t initxt;
90:
91: initxt = findword("initialize-of");
92: if (!initxt)
93: printk("warning: dictionary needs word called initialize-of\n");
94:
95: f = fopen(filename, "w");
96: if (!f) {
97: printk("panic: can't open dictionary.\n");
98: exit_terminal();
99: exit(1);
100: }
101:
102: fwrite(DICTID, 16, 1, f);
103: fwrite(dict, dicthead, 1, f);
104:
105: /* Write start address and last to relocate on load */
106: fwrite(&dict, sizeof(ucell), 1, f);
107: fwrite(&last, sizeof(ucell), 1, f);
108:
109: fclose(f);
110:
111: #ifdef CONFIG_DEBUG_DICTIONARY
112: printk("wrote dictionary to file %s.\n", filename);
113: #endif
114: }
115: #endif
116:
117: static ucell read_dictionary(char *fil)
118: {
119: int ilen;
120: ucell ret;
121: char *mem;
122: FILE *f;
123: struct stat finfo;
124:
125: if (stat(fil, &finfo))
126: return 0;
127:
128: ilen = finfo.st_size;
129:
130: if ((mem = malloc(ilen)) == NULL) {
131: printk("panic: not enough memory.\n");
132: exit_terminal();
133: exit(1);
134: }
135:
136: f = fopen(fil, "r");
137: if (!f) {
138: printk("panic: can't open dictionary.\n");
139: exit_terminal();
140: exit(1);
141: }
142:
143: if (fread(mem, ilen, 1, f) != 1) {
144: printk("panic: can't read dictionary.\n");
145: fclose(f);
146: exit_terminal();
147: exit(1);
148: }
149: fclose(f);
150:
151: ret = load_dictionary(mem, ilen);
152:
153: free(mem);
154: return ret;
155: }
156:
157:
158: /*
159: * functions used by primitives
160: */
161:
162: int availchar(void)
163: {
164: int tmp = getc(stdin);
165: if (tmp != EOF) {
166: ungetc(tmp, stdin);
167: return -1;
168: }
169: return 0;
170: }
171:
172: u8 inb(u32 reg)
173: {
174: #ifdef CONFIG_PLUGINS
175: io_ops_t *ior = find_iorange(reg);
176: if (ior)
177: return ior->inb(reg);
178: #endif
179:
180: printk("TRAP: io byte read @0x%x", reg);
181: return 0xff;
182: }
183:
184: u16 inw(u32 reg)
185: {
186: #ifdef CONFIG_PLUGINS
187: io_ops_t *ior = find_iorange(reg);
188: if (ior)
189: return ior->inw(reg);
190: #endif
191:
192: printk("TRAP: io word read @0x%x", reg);
193: return 0xffff;
194: }
195:
196: u32 inl(u32 reg)
197: {
198: #ifdef CONFIG_PLUGINS
199: io_ops_t *ior = find_iorange(reg);
200: if (ior)
201: return ior->inl(reg);
202: #endif
203:
204: printk("TRAP: io long read @0x%x", reg);
205: return 0xffffffff;
206: }
207:
208: void outb(u32 reg, u8 val)
209: {
210: #ifdef CONFIG_PLUGINS
211: io_ops_t *ior = find_iorange(reg);
212: if (ior) {
213: ior->outb(reg, val);
214: return;
215: }
216: #endif
217:
218: printk("TRAP: io byte write 0x%x -> 0x%x", val, reg);
219: }
220:
221: void outw(u32 reg, u16 val)
222: {
223: #ifdef CONFIG_PLUGINS
224: io_ops_t *ior = find_iorange(reg);
225: if (ior) {
226: ior->outw(reg, val);
227: return;
228: }
229: #endif
230: printk("TRAP: io word write 0x%x -> 0x%x", val, reg);
231: }
232:
233: void outl(u32 reg, u32 val)
234: {
235: #ifdef CONFIG_PLUGINS
236: io_ops_t *ior = find_iorange(reg);
237: if (ior) {
238: ior->outl(reg, val);
239: return;
240: }
241: #endif
242: printk("TRAP: io long write 0x%x -> 0x%x", val, reg);
243: }
244:
245: /*
246: * terminal initialization and cleanup.
247: */
248:
249: static struct termios saved_termios;
250:
251: static void init_terminal(void)
252: {
253: struct termios termios;
254:
255: tcgetattr(0, &saved_termios);
256: tcgetattr(0, &termios);
257: termios.c_lflag &= ~(ICANON | ECHO);
258: termios.c_cc[VMIN] = 1;
259: termios.c_cc[VTIME] = 3; // 300 ms
260: tcsetattr(0, 0, &termios);
261: }
262:
263: static void exit_terminal(void)
264: {
265: tcsetattr(0, 0, &saved_termios);
266: }
267:
268: /*
269: * segmentation fault handler. linux specific?
270: */
271:
272: static void
273: segv_handler(int signo __attribute__ ((unused)),
274: siginfo_t * si, void *context __attribute__ ((unused)))
275: {
276: static int count = 0;
277: ucell addr = 0xdeadbeef;
278:
279: if (count) {
280: printk("Died while dumping forth dictionary core.\n");
281: goto out;
282: }
283:
284: count++;
285:
286: if (PC >= (ucell) dict && PC <= (ucell) dict + dicthead)
287: addr = *(ucell *) PC;
288:
289: printk("panic: segmentation violation at %x\n", (ucell)si->si_addr);
290: printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n",
291: (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict);
292: printk("dstackcnt=%d rstackcnt=%d instruction=%x\n",
293: dstackcnt, rstackcnt, addr);
294:
295: #ifdef CONFIG_DEBUG_DSTACK
296: printdstack();
297: #endif
298: #ifdef CONFIG_DEBUG_RSTACK
299: printrstack();
300: #endif
301: #if 0
302: printk("Writing dictionary core file\n");
303: write_dictionary("forth.dict.core");
304: #endif
305:
306: out:
307: exit_terminal();
308: exit(1);
309: }
310:
311: /*
312: * Interrupt handler. linux specific?
313: * Restore terminal state on ctrl-C.
314: */
315:
316: static void
317: int_handler(int signo __attribute__ ((unused)),
318: siginfo_t * si __attribute__ ((unused)),
319: void *context __attribute__ ((unused)))
320: {
321: printk("\n");
322: exit_terminal();
323: exit(1);
324: }
325:
326: /*
327: * allocate memory and prepare engine for memory management.
328: */
329:
330: static void init_memory(void)
331: {
332: memory = malloc(MEMORY_SIZE);
333: if (!memory) {
334: printk("panic: not enough memory on host system.\n");
335: exit_terminal();
336: exit(1);
337: }
338:
339: memset (memory, 0, MEMORY_SIZE);
340: /* we push start and end of memory to the stack
341: * so that it can be used by the forth word QUIT
342: * to initialize the memory allocator
343: */
344:
345: PUSH((ucell) memory);
346: PUSH((ucell) memory + MEMORY_SIZE);
347: }
348:
349: void exception(__attribute__((unused)) cell no)
350: {
351: /*
352: * this is a noop since the dictionary has to take care
353: * itself of errors it generates outside of the bootstrap
354: */
355: }
356:
357: static void
358: arch_init( void )
359: {
360: openbios_init();
361: modules_init();
362: if(diskemu!=-1)
363: blk_init();
364:
365: device_end();
366: bind_func("platform-boot", boot);
367: }
368:
369: int
370: read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size )
371: {
372: // channels and units not supported yet.
373: unsigned char *buf=(unsigned char *)mphys;
374:
375: if(diskemu==-1)
376: return -1;
377:
378: //printk("read: ch=%d, unit=%d, blk=%ld, phys=%lx, size=%d\n",
379: // channel, unit, blk, mphys, size);
380:
381: lseek(diskemu, (ducell)blk*512, SEEK_SET);
382: read(diskemu, buf, size);
383:
384: return 0;
385: }
386:
387: /*
388: * main loop
389: */
390:
391: #define BANNER "OpenBIOS core. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
392: "This software comes with absolutely no warranty. "\
393: "All rights reserved.\n\n"
394:
395:
396: #define USAGE "usage: %s [options] [dictionary file|source file]\n\n"
397:
398: int main(int argc, char *argv[])
399: {
400: struct sigaction sa;
401: #if 0
402: unsigned char *dictname = NULL;
403: #endif
404: int c;
405:
406: const char *optstring = "VvhsD:P:p:f:?";
407:
408: while (1) {
409: #ifdef __GLIBC__
410: int option_index = 0;
411: static struct option long_options[] = {
412: {"version", 0, NULL, 'V'},
413: {"verbose", 0, NULL, 'v'},
414: {"help", 0, NULL, 'h'},
415: // {"dictionary", 1, NULL, 'D'},
416: {"segfault", 0, NULL, 's'},
417: #ifdef CONFIG_PLUGINS
418: {"plugin-path", 1, NULL, 'P'},
419: {"plugin", 1, NULL, 'p'},
420: #endif
421: {"file", 1, NULL, 'f'}
422: };
423:
424: c = getopt_long(argc, argv, optstring, long_options,
425: &option_index);
426: #else
427: c = getopt(argc, argv, optstring);
428: #endif
429: if (c == -1)
430: break;
431:
432: switch (c) {
433: case 'V':
434: printk(BANNER "Version " OPENBIOS_VERSION_STR "\n");
435: return 0;
436: case 'h':
437: case '?':
438: printk(BANNER "Version " OPENBIOS_VERSION_STR "\n"
439: USAGE, argv[0]);
440: return 0;
441: case 'v':
442: verbose = 1;
443: break;
444: case 's':
445: segfault = 1;
446: break;
447: #if 0
448: case 'D':
449: printk("Dumping final dictionary to '%s'\n", optarg);
450: dictname = optarg;
451: break;
452: #endif
453: #ifdef CONFIG_PLUGINS
454: case 'P':
455: printk("Plugin search path is now '%s'\n", optarg);
456: plugindir = optarg;
457: break;
458: case 'p':
459: printk("Loading plugin %s\n", optarg);
460: load_plugin(optarg);
461: break;
462: #endif
463: case 'f':
464: diskemu=open(optarg, O_RDONLY|__LFS);
465: if(diskemu!=-1)
466: printk("Using %s as harddisk.\n", optarg);
467: else
468: printk("%s not found. no harddisk node.\n",
469: optarg);
470: break;
471: default:
472: return 1;
473: }
474: }
475:
476: if (argc < optind + 1) {
477: printk(USAGE, argv[0]);
478: return 1;
479: }
480:
481: if ((dict = (unsigned char *) malloc(DICTIONARY_SIZE)) == NULL) {
482: printk("panic: not enough memory.\n");
483: return 1;
484: }
485:
486: dictlimit = DICTIONARY_SIZE;
487: memset(dict, 0, DICTIONARY_SIZE);
488:
489: if (!segfault) {
490: if (verbose)
491: printk("Installing SIGSEGV handler...");
492:
493: sa.sa_sigaction = segv_handler;
494: sigemptyset(&sa.sa_mask);
495: sa.sa_flags = SA_SIGINFO | SA_NODEFER;
496: sigaction(SIGSEGV, &sa, NULL);
497:
498: if (verbose)
499: printk("done.\n");
500: }
501:
502: /* set terminal to do non blocking reads */
503: init_terminal();
504:
505: if (verbose)
506: printk("Installing SIGINT handler...");
507:
508: sa.sa_sigaction = int_handler;
509: sigemptyset(&sa.sa_mask);
510: sa.sa_flags = SA_SIGINFO | SA_NODEFER;
511: sigaction(SIGINT, &sa, NULL);
512:
513: if (verbose)
514: printk("done.\n");
515:
516: read_dictionary(argv[optind]);
517: forth_init();
518:
519: PUSH_xt( bind_noname_func(arch_init) );
520: fword("PREPOST-initializer");
521:
522: PC = (cell)findword("initialize-of");
523: if (PC) {
524: if (verbose) {
525: if (optind + 1 != argc)
526: printk("Warning: only first dictionary used.\n");
527:
528: printk("dictionary loaded (%d bytes).\n", dicthead);
529: printk("Initializing memory...");
530: }
531: init_memory();
532:
533: if (verbose) {
534: printk("done\n");
535:
536: printk("Jumping to dictionary...");
537: }
538:
539: enterforth((xt_t)PC);
540: #if 0
541: if (dictname != NULL)
542: write_dictionary(dictname);
543: #endif
544:
545: free(memory);
546:
547: } else { /* input file is not a dictionary */
548: printk("not supported.\n");
549: }
550:
551: exit_terminal();
552: if (diskemu!=-1)
553: close(diskemu);
554:
555: free(dict);
556: return 0;
557: }
558:
559: #undef printk
560: int
561: printk( const char *fmt, ... )
562: {
563: int i;
564:
565: va_list args;
566: va_start( args, fmt );
567: i = vprintf(fmt, args );
568: va_end( args );
569: return i;
570: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.