Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / unix / unix.c
diff --git a/qemu/roms/openbios/arch/unix/unix.c b/qemu/roms/openbios/arch/unix/unix.c
new file mode 100644 (file)
index 0000000..1f628eb
--- /dev/null
@@ -0,0 +1,611 @@
+/* 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 "sysinclude.h"
+#include "mconfig.h"
+#include "config.h"
+#include "kernel/kernel.h"
+#include "dict.h"
+#include "kernel/stack.h"
+#include "arch/unix/plugins.h"
+#include "libopenbios/bindings.h"
+#include "libopenbios/console.h"
+#include "libopenbios/openbios.h"
+#include "openbios-version.h"
+
+#include "blk.h"
+#include "libopenbios/ofmem.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);
+
+unsigned long virt_offset = 0;
+
+/* local variables */
+
+static ucell *memory;
+
+static int diskemu;
+
+static int segfault = 0;
+static int verbose = 0;
+
+#if defined(CONFIG_PPC) || defined(CONFIG_SPARC64)
+unsigned long isa_io_base;
+#endif
+
+int errno_int; /* implement for fs drivers, needed to build on Mac OS X */
+
+ucell ofmem_claim(ucell addr, ucell size, ucell align)
+{
+    return 0;
+}
+
+#ifdef CONFIG_PPC
+extern void flush_icache_range(char *start, char *stop);
+
+void flush_icache_range(char *start, char *stop)
+{
+}
+#endif
+
+#ifdef CONFIG_PPC
+/* Expose system level is_machine helpers to make generic code easier */
+
+#include "drivers/drivers.h"
+int is_apple(void)
+{
+    return 0;
+}
+
+int is_oldworld(void)
+{
+    return 0;
+}
+
+int is_newworld(void)
+{
+    return 0;
+}
+#endif
+
+#if 0
+static 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
+}
+#endif
+
+static 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
+ */
+
+static int unix_availchar(void)
+{
+       int tmp = getc(stdin);
+       if (tmp != EOF) {
+               ungetc(tmp, stdin);
+               return -1;
+       }
+       return 0;
+}
+
+static int unix_putchar(int c)
+{
+       putc(c, stdout);
+       return c;
+}
+
+static int unix_getchar(void)
+{
+       return getc(stdin);
+}
+
+static struct _console_ops unix_console_ops = {
+       .putchar = unix_putchar,
+       .availchar = unix_availchar,
+       .getchar = unix_getchar
+};
+
+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 void
+segv_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 void
+int_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 void
+arch_init( void )
+{
+       openbios_init();
+       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 " OPENBIOS_VERSION_STR "\n");
+                       return 0;
+               case 'h':
+               case '?':
+                        printk(BANNER "Version " OPENBIOS_VERSION_STR "\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;
+       }
+
+       /* Initialise console */
+       init_console(unix_console_ops);
+
+       if ((dict = (unsigned char *) malloc(DICTIONARY_SIZE)) == NULL) {
+               printk("panic: not enough memory.\n");
+               return 1;
+       }
+
+       dictlimit = DICTIONARY_SIZE;
+       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, NULL);
+
+               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, NULL);
+
+        if (verbose)
+            printk("done.\n");
+
+       read_dictionary(argv[optind]);
+       forth_init();
+
+       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 printk
+int
+printk( const char *fmt, ... )
+{
+       int i;
+
+       va_list args;
+       va_start( args, fmt );
+       i = vprintf(fmt, args );
+       va_end( args );
+       return i;
+}