|
|
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.