📄 unix.c
字号:
/* tag: hosted forth environment, executable code * * Copyright (C) 2003-2005 Patrick Mauritz, Stefan Reinauer * * See the file "COPYING" for further information about * the copyright and warranty status of this work. */#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <string.h>#include <signal.h>#define __USE_LARGEFILE64#include <fcntl.h>#include <unistd.h>#include <termios.h>#include <sys/types.h>#include <sys/stat.h>#include <stdarg.h>#ifdef __GLIBC__#define _GNU_SOURCE#include <getopt.h>#endif#include "openbios/sysinclude.h"#include "mconfig.h"#include "openbios/config.h"#include "openbios/kernel.h"#include "dict.h"#include "openbios/stack.h"#include "unix/plugins.h"#include "openbios/bindings.h"#include "blk.h"#define MEMORY_SIZE (4*1024*1024) /* 4M ram for hosted system */#define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */ #if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS==64)#define lseek lseek64#define __LFS O_LARGEFILE#else#define __LFS 0#endif/* prototypes */static void exit_terminal(void);void boot(void);/* local variables */ucell *latest, *state;ucell *memory;int diskemu;static int segfault = 0;int verbose = 0;int errno_int; /* implement for fs drivers, needed to build on Mac OS X */#if 0static void write_dictionary(char *filename){ FILE *f; xt_t initxt; initxt = findword("initialize-of"); if (!initxt) printk("warning: dictionary needs word called initialize-of\n"); f = fopen(filename, "w"); if (!f) { printk("panic: can't open dictionary.\n"); exit_terminal(); exit(1); } fwrite(DICTID, 16, 1, f); fwrite(dict, dicthead, 1, f); /* Write start address and last to relocate on load */ fwrite(&dict, sizeof(ucell), 1, f); fwrite(&last, sizeof(ucell), 1, f); fclose(f);#ifdef CONFIG_DEBUG_DICTIONARY printk("wrote dictionary to file %s.\n", filename);#endif}#endifstatic ucell read_dictionary(char *fil){ int ilen; ucell ret; char *mem; FILE *f; struct stat finfo; if (stat(fil, &finfo)) return 0; ilen = finfo.st_size; if ((mem = malloc(ilen)) == NULL) { printk("panic: not enough memory.\n"); exit_terminal(); exit(1); } f = fopen(fil, "r"); if (!f) { printk("panic: can't open dictionary.\n"); exit_terminal(); exit(1); } if (fread(mem, ilen, 1, f) != 1) { printk("panic: can't read dictionary.\n"); fclose(f); exit_terminal(); exit(1); } fclose(f); ret = load_dictionary(mem, ilen); free(mem); return ret;}/* * functions used by primitives */int availchar(void){ int tmp = getc(stdin); if (tmp != EOF) { ungetc(tmp, stdin); return -1; } return 0;}u8 inb(u32 reg){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) return ior->inb(reg);#endif printk("TRAP: io byte read @0x%x", reg); return 0xff;}u16 inw(u32 reg){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) return ior->inw(reg);#endif printk("TRAP: io word read @0x%x", reg); return 0xffff;}u32 inl(u32 reg){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) return ior->inl(reg);#endif printk("TRAP: io long read @0x%x", reg); return 0xffffffff;}void outb(u32 reg, u8 val){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) { ior->outb(reg, val); return; }#endif printk("TRAP: io byte write 0x%x -> 0x%x", val, reg);}void outw(u32 reg, u16 val){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) { ior->outw(reg, val); return; }#endif printk("TRAP: io word write 0x%x -> 0x%x", val, reg);}void outl(u32 reg, u32 val){#ifdef CONFIG_PLUGINS io_ops_t *ior = find_iorange(reg); if (ior) { ior->outl(reg, val); return; }#endif printk("TRAP: io long write 0x%x -> 0x%x", val, reg);}/* * terminal initialization and cleanup. */static struct termios saved_termios;static void init_terminal(void){ struct termios termios; tcgetattr(0, &saved_termios); tcgetattr(0, &termios); termios.c_lflag &= ~(ICANON | ECHO); termios.c_cc[VMIN] = 1; termios.c_cc[VTIME] = 3; // 300 ms tcsetattr(0, 0, &termios);}static void exit_terminal(void){ tcsetattr(0, 0, &saved_termios);}/* * segmentation fault handler. linux specific? */static voidsegv_handler(int signo __attribute__ ((unused)), siginfo_t * si, void *context __attribute__ ((unused))){ static int count = 0; ucell addr = 0xdeadbeef; if (count) { printk("Died while dumping forth dictionary core.\n"); goto out; } count++; if (PC >= (ucell) dict && PC <= (ucell) dict + dicthead) addr = *(ucell *) PC; printk("panic: segmentation violation at %x\n", (ucell)si->si_addr); printk("dict=0x%x here=0x%x(dict+0x%x) pc=0x%x(dict+0x%x)\n", (ucell)dict, (ucell)dict + dicthead, dicthead, PC, PC - (ucell) dict); printk("dstackcnt=%d rstackcnt=%d instruction=%x\n", dstackcnt, rstackcnt, addr);#ifdef CONFIG_DEBUG_DSTACK printdstack();#endif#ifdef CONFIG_DEBUG_RSTACK printrstack();#endif#if 0 printk("Writing dictionary core file\n"); write_dictionary("forth.dict.core");#endif out: exit_terminal(); exit(1);}/* * Interrupt handler. linux specific? * Restore terminal state on ctrl-C. */static voidint_handler(int signo __attribute__ ((unused)), siginfo_t * si __attribute__ ((unused)), void *context __attribute__ ((unused))){ printk("\n"); exit_terminal(); exit(1);}/* * allocate memory and prepare engine for memory management. */static void init_memory(void){ memory = malloc(MEMORY_SIZE); if (!memory) { printk("panic: not enough memory on host system.\n"); exit_terminal(); exit(1); } memset (memory, 0, MEMORY_SIZE); /* we push start and end of memory to the stack * so that it can be used by the forth word QUIT * to initialize the memory allocator */ PUSH((ucell) memory); PUSH((ucell) memory + MEMORY_SIZE);}void exception(__attribute__((unused)) cell no){ /* * this is a noop since the dictionary has to take care * itself of errors it generates outside of the bootstrap */}static voidarch_init( void ){ modules_init(); if(diskemu!=-1) blk_init(); device_end(); bind_func("platform-boot", boot);}int read_from_disk( int channel, int unit, int blk, unsigned long mphys, int size ){ // channels and units not supported yet. unsigned char *buf=(unsigned char *)mphys; if(diskemu==-1) return -1; //printk("read: ch=%d, unit=%d, blk=%ld, phys=%lx, size=%d\n", // channel, unit, blk, mphys, size); lseek(diskemu, (ducell)blk*512, SEEK_SET); read(diskemu, buf, size); return 0;}/* * main loop */#define BANNER "OpenBIOS core. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\ "This software comes with absolutely no warranty. "\ "All rights reserved.\n\n"#define USAGE "usage: %s [options] [dictionary file|source file]\n\n"int main(int argc, char *argv[]){ struct sigaction sa;#if 0 unsigned char *dictname = NULL;#endif int c; const char *optstring = "VvhsD:P:p:f:?"; while (1) {#ifdef __GLIBC__ int option_index = 0; static struct option long_options[] = { {"version", 0, NULL, 'V'}, {"verbose", 0, NULL, 'v'}, {"help", 0, NULL, 'h'},// {"dictionary", 1, NULL, 'D'}, {"segfault", 0, NULL, 's'},#ifdef CONFIG_PLUGINS {"plugin-path", 1, NULL, 'P'}, {"plugin", 1, NULL, 'p'},#endif {"file", 1, NULL, 'f'} }; c = getopt_long(argc, argv, optstring, long_options, &option_index);#else c = getopt(argc, argv, optstring);#endif if (c == -1) break; switch (c) { case 'V': printk(BANNER "Version " VERSION "\n"); return 0; case 'h': case '?': printk(BANNER "Version " VERSION "\n" USAGE, argv[0]); return 0; case 'v': verbose = 1; break; case 's': segfault = 1; break;#if 0 case 'D': printk("Dumping final dictionary to '%s'\n", optarg); dictname = optarg; break;#endif#ifdef CONFIG_PLUGINS case 'P': printk("Plugin search path is now '%s'\n", optarg); plugindir = optarg; break; case 'p': printk("Loading plugin %s\n", optarg); load_plugin(optarg); break;#endif case 'f': diskemu=open(optarg, O_RDONLY|__LFS); if(diskemu!=-1) printk("Using %s as harddisk.\n", optarg); else printk("%s not found. no harddisk node.\n", optarg); break; default: return 1; } } if (argc < optind + 1) { printk(USAGE, argv[0]); return 1; } if ((dict = (unsigned char *) malloc(DICTIONARY_SIZE)) == NULL) { printk("panic: not enough memory.\n"); return 1; } memset(dict, 0, DICTIONARY_SIZE); if (!segfault) { if (verbose) printk("Installing SIGSEGV handler..."); sa.sa_sigaction = segv_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_NODEFER; sigaction(SIGSEGV, &sa, 0); if (verbose) printk("done.\n"); } /* set terminal to do non blocking reads */ init_terminal(); if (verbose) printk("Installing SIGINT handler..."); sa.sa_sigaction = int_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_NODEFER; sigaction(SIGINT, &sa, 0); if (verbose) printk("done.\n"); read_dictionary(argv[optind]); PUSH_xt( bind_noname_func(arch_init) ); fword("PREPOST-initializer"); PC = (cell)findword("initialize-of"); if (PC) { if (verbose) { if (optind + 1 != argc) printk("Warning: only first dictionary used.\n"); printk("dictionary loaded (%d bytes).\n", dicthead); printk("Initializing memory..."); } init_memory(); if (verbose) { printk("done\n"); printk("Jumping to dictionary..."); } enterforth((xt_t)PC);#if 0 if (dictname != NULL) write_dictionary(dictname);#endif free(memory); } else { /* input file is not a dictionary */ printk("not supported.\n"); } exit_terminal(); if (diskemu!=-1) close(diskemu); free(dict); return 0;}#undef printkintprintk( const char *fmt, ... ){ int i; va_list args; va_start( args, fmt ); i = vprintf(fmt, args ); va_end( args ); return i;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -