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