Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / kernel / bootstrap.c
1 /* tag: forth bootstrap environment
2  *
3  * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz
4  *
5  * See the file "COPYING" for further information about
6  * the copyright and warranty status of this work.
7  */
8
9 #include "sysinclude.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <signal.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <termios.h>
17 #include <sys/stat.h>
18
19 #ifdef __GLIBC__
20 #define _GNU_SOURCE
21 #include <getopt.h>
22 #endif
23
24 #include "config.h"
25 #include "kernel/stack.h"
26 #include "sysinclude.h"
27 #include "kernel/kernel.h"
28 #include "dict.h"
29 #include "cross.h"
30 #include "openbios-version.h"
31
32 #define MAX_PATH_LEN 256
33
34 #define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */
35 #define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary   */
36 #define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */
37
38 /* state variables */
39 static ucell *latest, *state, *base;
40 static ucell *memory;
41 ucell *trampoline;
42
43 /* local variables */
44 static int errors = 0;
45 static int segfault = 0;
46 static int verbose = 0;
47
48 #define MAX_SRC_FILES 128
49
50 static FILE *srcfiles[MAX_SRC_FILES];
51 static char *srcfilenames[MAX_SRC_FILES];
52 static int srclines[MAX_SRC_FILES];
53 static unsigned int cursrc = 0;
54
55 static char *srcbasedict;
56
57 /* console variables */
58 static FILE *console;
59
60 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
61 unsigned long base_address;
62 #endif
63
64 /* include path handling */
65 typedef struct include_path include;
66 struct include_path {
67         const char *path;
68         include *next;
69 };
70
71 static include includes = { ".", NULL };
72 static FILE *depfile;
73
74 static ucell * relocation_address=NULL;
75 static int     relocation_length=0;
76
77 /* the word names are used to generate the prim words in the
78  * dictionary. This is done by the C written interpreter.
79  */
80 static const char *wordnames[] = {
81         "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)",
82         "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop",
83         "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>",
84         "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*",
85         "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a",
86         "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@",
87         "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<",
88         "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute",
89         "here", "here!", "dobranch", "do?branch", "unaligned-w@",
90         "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
91         "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
92         "$include", "$encode-file", "(debug", "(debug-off)"
93 };
94
95 /*
96  * dictionary related functions.
97  */
98
99 /*
100  * Compare two dictionaries constructed at different addresses. When
101  * the cells don't match, a need for relocation is detected and the
102  * corresponding bit in reloc_table bitmap is set.
103  */
104 static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
105 {
106         ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
107         ucell *reloc_table;
108         int pos, bit;
109         int l=(length+(sizeof(cell)-1))/sizeof(ucell), i;
110
111         /* prepare relocation table */
112         relocation_length=(length+BITS-1)/BITS;
113         reloc_table = malloc(relocation_length*sizeof(cell));
114         memset(reloc_table,0,relocation_length*sizeof(cell));
115
116         for (i=0; i<l; i++) {
117
118                 pos=i/BITS;
119                 bit=i&~(-BITS);
120
121                 if(d1[i]==d2[i]) {
122                         reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
123
124                         // This check might bring false positives in data.
125                         //if(d1[i] >= pointer2cell(dict_one) &&
126                         //              d1[i] <= pointer2cell(dict_one+length))
127                         //      printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
128                 } else {
129                         /* This is a pointer, it needs relocation, d2==dict */
130                         reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
131                         d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
132                 }
133         }
134
135 #ifdef CONFIG_DEBUG_DICTIONARY
136         printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict);
137         for (i=0; i< relocation_length ; i++)
138                 printk("reloc %d %lx\n",i+1, reloc_table[i]);
139 #endif
140         relocation_address=reloc_table;
141 }
142
143 static void write_dictionary(const char *filename)
144 {
145         FILE *f;
146         unsigned char *write_data, *walk_data;
147         int  write_len;
148         dictionary_header_t *header;
149         u32 checksum=0;
150
151         /*
152          * get memory for dictionary
153          */
154
155         write_len  = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell);
156         write_data = malloc(write_len);
157         if(!write_data) {
158                 printk("panic: can't allocate memory for output dictionary (%d"
159                         " bytes\n", write_len);
160                 exit(1);
161         }
162         memset(write_data, 0, write_len);
163
164         /*
165          * prepare dictionary header
166          */
167
168         header = (dictionary_header_t *)write_data;
169         *header = (dictionary_header_t){
170                 .signature      = DICTID,
171                 .version        = 2,
172                 .cellsize       = sizeof(ucell),
173 #ifdef CONFIG_BIG_ENDIAN
174                 .endianess      = -1,
175 #else
176                 .endianess      = 0,
177 #endif
178                 .checksum       = 0,
179                 .compression    = 0,
180                 .relocation     = -1,
181                 .length         = target_ulong((uint32_t)dicthead),
182                 .last           = target_ucell((ucell)((unsigned long)last
183                                                        - (unsigned long)dict)),
184         };
185
186         /*
187          * prepare dictionary data
188          */
189
190         walk_data=write_data+sizeof(dictionary_header_t);
191         memcpy (walk_data, dict, dicthead);
192
193         /*
194          * prepare relocation data.
195          * relocation_address is zero when writing a dictionary core.
196          */
197
198         if (relocation_address) {
199 #ifdef CONFIG_DEBUG_DICTIONARY
200                 printk("writing %d reloc cells \n",relocation_length);
201 #endif
202                 walk_data += dicthead;
203                 memcpy(walk_data, relocation_address,
204                                 relocation_length*sizeof(cell));
205                 /* free relocation information */
206                 free(relocation_address);
207                 relocation_address=NULL;
208         } else {
209                 header->relocation=0;
210         }
211
212         /*
213          * Calculate Checksum
214          */
215
216         walk_data=write_data;
217         while (walk_data<write_data+write_len) {
218                 checksum+=read_long(walk_data);
219                 walk_data+=sizeof(u32);
220         }
221         checksum=(u32)-checksum;
222
223         header->checksum=target_long(checksum);
224
225         if (verbose) {
226                 dump_header(header);
227         }
228
229         f = fopen(filename, "w");
230         if (!f) {
231                 printk("panic: can't write to dictionary '%s'.\n", filename);
232                 exit(1);
233         }
234
235         fwrite(write_data, write_len, 1, f);
236
237         free(write_data);
238         fclose(f);
239
240 #ifdef CONFIG_DEBUG_DICTIONARY
241         printk("wrote dictionary to file %s.\n", filename);
242 #endif
243 }
244
245 /*
246  * Write dictionary as a list of ucell hex values to filename. Array
247  * header and end lines are not generated.
248  *
249  * Cells with relocations are output using the expression
250  * DICTIONARY_BASE + value.
251  *
252  * Define some helpful constants.
253  */
254 static void write_dictionary_hex(const char *filename)
255 {
256     FILE *f;
257     ucell *walk;
258
259     f = fopen(filename, "w");
260     if (!f) {
261         printk("panic: can't write to dictionary '%s'.\n", filename);
262         exit(1);
263     }
264
265     for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) {
266         int pos, bit, l;
267         ucell val;
268
269         l = (walk - (ucell *)dict);
270         pos = l / BITS;
271         bit = l & ~(-BITS);
272
273         val = read_ucell(walk);
274         if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) {
275             fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x
276                     ",\n", val);
277         } else {
278             fprintf(f, "0x%" FMT_CELL_x",\n", val);
279         }
280     }
281
282     fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n",
283             (ucell)((unsigned long)last - (unsigned long)dict));
284     fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n",
285             (ucell)dicthead);
286     fclose(f);
287
288 #ifdef CONFIG_DEBUG_DICTIONARY
289     printk("wrote dictionary to file %s.\n", filename);
290 #endif
291 }
292
293 static ucell read_dictionary(char *fil)
294 {
295         int ilen;
296         ucell ret;
297         char *mem;
298         FILE *f;
299         struct stat finfo;
300
301         if (stat(fil, &finfo))
302                 return 0;
303
304         ilen = finfo.st_size;
305
306         if ((mem = malloc(ilen)) == NULL) {
307                 printk("panic: not enough memory.\n");
308                 exit(1);
309         }
310
311         f = fopen(fil, "r");
312         if (!f) {
313                 printk("panic: can't open dictionary.\n");
314                 exit(1);
315         }
316
317         if (fread(mem, ilen, 1, f) != 1) {
318                 printk("panic: can't read dictionary.\n");
319                 fclose(f);
320                 exit(1);
321         }
322         fclose(f);
323
324         ret = load_dictionary(mem, ilen);
325
326         free(mem);
327         return ret;
328 }
329
330
331 /*
332  * C Parser related functions
333  */
334
335 /*
336  * skipws skips all whitespaces (space, tab, newline) from the input file
337  */
338
339 static void skipws(FILE * f)
340 {
341         int c;
342         while (!feof(f)) {
343                 c = getc(f);
344
345                 if (c == ' ' || c == '\t')
346                         continue;
347
348                 if (c == '\n') {
349                         srclines[cursrc - 1]++;
350                         continue;
351                 }
352
353                 ungetc(c, f);
354                 break;
355         }
356 }
357
358 /*
359  * parse gets the next word from the input stream, delimited by
360  * delim. If delim is 0, any word delimiter will end the stream
361  * word delimiters are space, tab and newline. The resulting word
362  * will be put zero delimited to the char array line.
363  */
364
365 static int parse(FILE * f, char *line, char delim)
366 {
367         int cnt = 0, c = 0;
368
369         while (!feof(f)) {
370                 c = getc(f);
371
372                 if (delim && c == delim)
373                         break;
374
375                 if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
376                         break;
377
378                 line[cnt++] = c;
379         }
380
381         /* Update current line number */
382         if (c == '\n') {
383                 srclines[cursrc - 1]++;
384         }
385
386         line[cnt] = 0;
387
388         return cnt;
389 }
390
391 /*
392  * parse_word is a small helper that skips whitespaces before a word.
393  * it's behaviour is similar to the forth version parse-word.
394  */
395
396 static void parse_word(FILE * f, char *line)
397 {
398         skipws(f);
399         parse(f, line, 0);
400 }
401
402
403 static void writestring(const char *str)
404 {
405         unsigned int i;
406         for (i = 0; i < strlen(str); i++) {
407                 dict[dicthead + i] = str[i];
408         }
409         dicthead += i + 1;
410         dict[dicthead - 1] = (char) strlen(str) + 128;
411 }
412
413 #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
414 #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
415
416 /*
417  * reveal a word, ie. make it visible.
418  */
419
420 static void reveal(void)
421 {
422         *last = *latest;
423 }
424
425 /*
426  * dictionary padding
427  */
428
429 static void paddict(ucell align)
430 {
431         while (dicthead % align != 0)
432                 writebyte(0);
433 }
434
435 /*
436  * generic forth word creator function.
437  */
438
439 static void fcreate(const char *word, ucell cfaval)
440 {
441         if (strlen(word) == 0) {
442                 printk("WARNING: tried to create unnamed word.\n");
443                 return;
444         }
445
446         writestring(word);
447         /* get us at least 1 byte for flags */
448         writebyte(0);
449         paddict(sizeof(cell));
450         /* set flags high bit. */
451         dict[dicthead - 1] = 128;
452         /* lfa and cfa */
453         writecell(read_ucell(latest));
454         *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell));
455         writecell(cfaval);
456 }
457
458
459 static ucell *buildvariable(const char *name, cell defval)
460 {
461         fcreate(name, DOVAR);   /* see dict.h for DOVAR and other CFA ids */
462         writecell(defval);
463         return (ucell *) (dict + dicthead - sizeof(cell));
464 }
465
466 static void buildconstant(const char *name, cell defval)
467 {
468         fcreate(name, DOCON);   /* see dict.h for DOCON and other CFA ids */
469         writecell(defval);
470 }
471
472 static void builddefer(const char *name)
473 {
474         fcreate(name, DODFR);   /* see dict.h for DODFR and other CFA ids */
475         writecell((ucell)0);
476         writecell((ucell)findword("(semis)"));
477 }
478
479 /*
480  * Include file handling
481  */
482
483 static void add_includepath(char *path)
484 {
485         include *incl = &includes;
486         include *newpath;
487
488         while (incl->next)
489                 incl = incl->next;
490
491         newpath = malloc(sizeof(include));
492         if (!newpath) {
493                 printk("panic: not enough memory for include path.\n");
494                 exit(1);
495         }
496
497         incl->next = newpath;
498         newpath->path = path;
499         newpath->next = NULL;
500 }
501
502
503 static FILE *fopen_include(const char *fil)
504 {
505         char fullpath[MAX_PATH_LEN];
506         FILE *ret;
507         include *incl = &includes;
508
509         while (incl) {
510                 snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
511
512                 ret = fopen(fullpath, "r");
513                 if (ret != NULL) {
514
515 #ifdef CONFIG_DEBUG_INTERPRETER
516                         printk("Including '%s'\n", fil);
517 #endif
518                         srcfilenames[cursrc] = strdup(fil);
519                         srclines[cursrc] = 1;
520                         srcfiles[cursrc++] = ret;
521
522                         if (depfile) {
523                                 fprintf(depfile, " %s", fullpath);
524                         }
525
526                         return ret;
527                 }
528
529                 incl = incl->next;
530         }
531         return NULL;
532 }
533
534
535 /*
536  * Forth exception handler
537  */
538
539 void exception(cell no)
540 {
541         printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
542
543         /* See also forth/bootstrap/interpreter.fs */
544         switch (no) {
545         case -1:
546         case -2:
547                 printk("Aborted.\n");
548                 break;
549         case -3:
550                 printk("Stack Overflow.\n");
551                 break;
552         case -4:
553                 printk("Stack Underflow.\n");
554                 break;
555         case -5:
556                 printk("Return Stack Overflow.\n");
557                 break;
558         case -6:
559                 printk("Return Stack Underflow.\n");
560                 break;
561         case -19:
562                 printk("undefined word.\n");
563                 break;
564         case -21:
565                 printk("out of memory.\n");
566                 break;
567         case -33:
568                 printk("undefined method.\n");
569                 break;
570         case -34:
571                 printk("no such device.\n");
572                 break;
573         default:
574                 printk("error %" FMT_CELL_d " occured.\n", no);
575         }
576         exit(1);
577 }
578
579
580 /*
581  * This is the C version of the forth interpreter
582  */
583
584 static int interpret_source(char *fil)
585 {
586         FILE *f;
587         char tib[160];
588         cell num;
589         char *test;
590
591         const ucell SEMIS = (ucell)findword("(semis)");
592         const ucell LIT = (ucell)findword("(lit)");
593         const ucell DOBRANCH = (ucell)findword("dobranch");
594
595         if ((f = fopen_include(fil)) == NULL) {
596                 printk("error while loading source file '%s'\n", fil);
597                 errors++;
598                 exit(1);
599         }
600
601         /* FIXME: We should read this file at
602          * once. No need to get it char by char
603          */
604
605         while (!feof(f)) {
606                 xt_t res;
607                 parse_word(f, tib);
608
609                 /* if there is actually no word, we continue right away */
610                 if (strlen(tib) == 0) {
611                         continue;
612                 }
613
614                 /* Checking for builtin words that are needed to
615                  * bootstrap the forth base dictionary.
616                  */
617
618                 if (!strcmp(tib, "(")) {
619                         parse(f, tib, ')');
620                         continue;
621                 }
622
623                 if (!strcmp(tib, "\\")) {
624                         parse(f, tib, '\n');
625                         continue;
626                 }
627
628                 if (!strcmp(tib, ":")) {
629                         parse_word(f, tib);
630
631 #ifdef CONFIG_DEBUG_INTERPRETER
632                         printk("create colon word %s\n\n", tib);
633 #endif
634                         fcreate(tib, DOCOL);    /* see dict.h for DOCOL and other CFA ids */
635                         *state = (ucell) (-1);
636                         continue;
637                 }
638
639                 if (!strcmp(tib, ";")) {
640 #ifdef CONFIG_DEBUG_INTERPRETER
641                         printk("finish colon definition\n\n");
642 #endif
643                         writecell((cell)SEMIS);
644                         *state = (ucell) 0;
645                         reveal();
646                         continue;
647                 }
648
649                 if (!strcasecmp(tib, "variable")) {
650                         parse_word(f, tib);
651 #ifdef CONFIG_DEBUG_INTERPRETER
652                         printk("defining variable %s\n\n", tib);
653 #endif
654                         buildvariable(tib, 0);
655                         reveal();
656                         continue;
657                 }
658
659                 if (!strcasecmp(tib, "constant")) {
660                         parse_word(f, tib);
661 #ifdef CONFIG_DEBUG_INTERPRETER
662                         printk("defining constant %s\n\n", tib);
663 #endif
664                         buildconstant(tib, POP());
665                         reveal();
666                         continue;
667                 }
668
669                 if (!strcasecmp(tib, "value")) {
670                         parse_word(f, tib);
671 #ifdef CONFIG_DEBUG_INTERPRETER
672                         printk("defining value %s\n\n", tib);
673 #endif
674                         buildconstant(tib, POP());
675                         reveal();
676                         continue;
677                 }
678
679                 if (!strcasecmp(tib, "defer")) {
680                         parse_word(f, tib);
681 #ifdef CONFIG_DEBUG_INTERPRETER
682                         printk("defining defer word %s\n\n", tib);
683 #endif
684                         builddefer(tib);
685                         reveal();
686                         continue;
687                 }
688
689                 if (!strcasecmp(tib, "include")) {
690                         parse_word(f, tib);
691 #ifdef CONFIG_DEBUG_INTERPRETER
692                         printk("including file %s\n\n", tib);
693 #endif
694                         interpret_source(tib);
695                         continue;
696                 }
697
698                 if (!strcmp(tib, "[']")) {
699                         xt_t xt;
700                         parse_word(f, tib);
701                         xt = findword(tib);
702                         if (*state == 0) {
703 #ifdef CONFIG_DEBUG_INTERPRETER
704                                 printk
705                                     ("writing address of %s to stack\n\n",
706                                      tib);
707 #endif
708                                 PUSH_xt(xt);
709                         } else {
710 #ifdef CONFIG_DEBUG_INTERPRETER
711                                 printk("writing lit, addr(%s) to dict\n\n",
712                                        tib);
713 #endif
714                                 writecell(LIT); /* lit */
715                                 writecell((cell)xt);
716                         }
717                         continue;
718                         /* we have no error detection here */
719                 }
720
721                 if (!strcasecmp(tib, "s\"")) {
722                         int cnt;
723                         cell loco;
724
725                         cnt = parse(f, tib, '"');
726 #ifdef CONFIG_DEBUG_INTERPRETER
727                         printk("compiling string %s\n", tib);
728 #endif
729                         loco = dicthead + (6 * sizeof(cell));
730                         writecell(LIT);
731                         writecell(pointer2cell(dict) + loco);
732                         writecell(LIT);
733                         writecell((ucell)cnt);
734                         writecell(DOBRANCH);
735                         loco = cnt + sizeof(cell) - 1;
736                         loco &= ~(sizeof(cell) - 1);
737                         writecell(loco);
738                         memcpy(dict + dicthead, tib, cnt);
739                         dicthead += cnt;
740                         paddict(sizeof(cell));
741                         continue;
742                 }
743
744                 /* look if tib is in dictionary. */
745                 /* should the dictionary be searched before the builtins ? */
746                 res = findword(tib);
747                 if (res) {
748                         u8 flags = read_byte((u8*)cell2pointer(res) -
749                                                 sizeof(cell) - 1);
750 #ifdef CONFIG_DEBUG_INTERPRETER
751                         printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res);
752 #endif
753                         if (!(*state) || (flags & 3)) {
754 #ifdef CONFIG_DEBUG_INTERPRETER
755                                 printk("executing %s, %" FMT_CELL_d
756                                        " (flags: %s %s)\n",
757                                        tib, res,
758                                        (flags & 1) ? "immediate" : "",
759                                        (flags & 2) ? "compile-only" : "");
760 #endif
761                                 PC = (ucell)res;
762                                 enterforth(res);
763                         } else {
764 #ifdef CONFIG_DEBUG_INTERPRETER
765                                 printk("writing %s to dict\n\n", tib);
766 #endif
767                                 writecell((cell)res);
768                         }
769                         continue;
770                 }
771
772                 /* if not look if it's a number */
773                 if (tib[0] == '-')
774                         num = strtoll(tib, &test, read_ucell(base));
775                 else
776                         num = strtoull(tib, &test, read_ucell(base));
777
778
779                 if (*test != 0) {
780                         /* what is it?? */
781                         printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib);
782                         errors++;
783 #ifdef CONFIG_DEBUG_INTERPRETER
784                         continue;
785 #else
786                         return -1;
787 #endif
788                 }
789
790                 if (*state == 0) {
791 #ifdef CONFIG_DEBUG_INTERPRETER
792                         printk("pushed %" FMT_CELL_x " to stack\n\n", num);
793 #endif
794                         PUSH(num);
795                 } else {
796 #ifdef CONFIG_DEBUG_INTERPRETER
797                         printk("writing lit, %" FMT_CELL_x " to dict\n\n", num);
798 #endif
799                         writecell(LIT); /* lit */
800                         writecell(num);
801                 }
802         }
803
804         fclose(f);
805         cursrc--;
806
807         return 0;
808 }
809
810 static int build_dictionary(void)
811 {
812         ucell lfa = 0;
813         unsigned int i;
814
815         /* we need a temporary place for latest outside the dictionary */
816         latest = &lfa;
817
818         /* starting a new dictionary: clear dicthead */
819         dicthead = 0;
820
821 #ifdef CONFIG_DEBUG_DICTIONARY
822         printk("building dictionary, %d primitives.\nbuilt words:",
823                sizeof(wordnames) / sizeof(void *));
824 #endif
825
826         for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) {
827                 if (strlen(wordnames[i]) != 0) {
828                         fcreate((char *) wordnames[i], i);
829 #ifdef CONFIG_DEBUG_DICTIONARY
830                         printk(" %s", wordnames[i]);
831 #endif
832                 }
833         }
834 #ifdef CONFIG_DEBUG_DICTIONARY
835         printk(".\n");
836 #endif
837
838         /* get last/latest and state */
839         state = buildvariable("state", 0);
840         last = buildvariable("forth-last", 0);
841         latest = buildvariable("latest", 0);
842
843         *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
844
845         base=buildvariable("base", 10);
846
847         buildconstant("/c", sizeof(u8));
848         buildconstant("/w", sizeof(u16));
849         buildconstant("/l", sizeof(u32));
850         buildconstant("/n", sizeof(ucell));
851         buildconstant("/x", sizeof(u64));
852
853         reveal();
854         if (verbose) {
855                 printk("Dictionary initialization finished.\n");
856         }
857         return 0;
858 }
859
860 /*
861  * functions used by primitives
862  */
863
864 int availchar(void)
865 {
866         int tmp;
867         if( cursrc < 1 ) {
868                 interruptforth |= FORTH_INTSTAT_STOP;
869                 /* return -1 in order to exit the loop in key() */
870                 return -1;
871         }
872
873         tmp = getc( srcfiles[cursrc-1] );
874         if (tmp != EOF) {
875                 ungetc(tmp, srcfiles[cursrc-1]);
876                 return -1;
877         }
878
879         fclose(srcfiles[--cursrc]);
880
881         return availchar();
882 }
883
884 int get_inputbyte( void )
885 {
886         int tmp;
887
888         if( cursrc < 1 ) {
889                 interruptforth |= FORTH_INTSTAT_STOP;
890                 return 0;
891         }
892
893         tmp = getc( srcfiles[cursrc-1] );
894
895         /* Update current line number */
896         if (tmp == '\n') {
897                 srclines[cursrc - 1]++;
898         }
899
900         if (tmp != EOF) {
901                 return tmp;
902         }
903
904         fclose(srcfiles[--cursrc]);
905
906         return get_inputbyte();
907 }
908
909 void put_outputbyte( int c )
910 {
911         if (console)
912                 fputc(c, console);
913 }
914
915 /*
916  *  segmentation fault handler. linux specific?
917  */
918
919 static void
920 segv_handler(int signo __attribute__ ((unused)),
921              siginfo_t * si, void *context __attribute__ ((unused)))
922 {
923         static int count = 0;
924         ucell addr = 0xdeadbeef;
925
926         if (count) {
927                 printk("Died while dumping forth dictionary core.\n");
928                 goto out;
929         }
930
931         count++;
932
933         if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
934                 addr = read_cell(cell2pointer(PC));
935
936         printk("panic: segmentation violation at %p\n", (char *)si->si_addr);
937         printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n",
938                dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict));
939         printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n",
940                dstackcnt, rstackcnt, addr);
941
942         printdstack();
943         printrstack();
944
945         printk("Writing dictionary core file\n");
946         write_dictionary("forth.dict.core");
947
948       out:
949         exit(1);
950 }
951
952 /*
953  * allocate memory and prepare engine for memory management.
954  */
955
956 static void init_memory(void)
957 {
958         memset(memory, 0, MEMORY_SIZE);
959
960         /* we push start and end of memory to the stack
961          * so that it can be used by the forth word QUIT
962          * to initialize the memory allocator.
963          * Add a cell to the start address so we don't end
964          * up with a start address of zero during bootstrap
965          */
966
967         PUSH(pointer2cell(memory)+sizeof(cell));
968         PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
969 }
970
971
972 void
973 include_file( const char *name )
974 {
975         FILE *file;
976
977         if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
978                 printk("\npanic: Maximum include depth reached!\n");
979                 exit(1);
980         }
981
982         file = fopen_include( name );
983         if( !file ) {
984                 printk("\npanic: Failed opening file '%s'\n", name );
985                 exit(1);
986         }
987 }
988
989
990 void
991 encode_file( const char *name )
992 {
993         FILE *file = fopen_include(name);
994         int size;
995
996         if( !file ) {
997                 printk("\npanic: Can't open '%s'\n", name );
998                 exit(1);
999         }
1000         fseek( file, 0, SEEK_END );
1001         size = ftell( file );
1002         fseek( file, 0, SEEK_SET );
1003
1004         if (verbose) {
1005                 printk("\nEncoding %s [%d bytes]\n", name, size );
1006         }
1007         fread( dict + dicthead, size, 1, file );
1008         PUSH( pointer2cell(dict + dicthead) );
1009         PUSH( size );
1010         dicthead += size;
1011         paddict(sizeof(cell));
1012 }
1013
1014
1015 static void run_dictionary(char *basedict, char *confile)
1016 {
1017         if(!basedict)
1018                 return;
1019
1020         read_dictionary(basedict);
1021         PC = (ucell)findword("initialize");
1022
1023         if (!PC) {
1024                 if (verbose) {
1025                         printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
1026                 }
1027                 return;
1028         }
1029
1030         if(!srcfiles[0]) {
1031                 cursrc = 1;
1032                 srcfiles[cursrc-1] = stdin;
1033         }
1034
1035         dstackcnt=0;
1036         rstackcnt=0;
1037
1038         init_memory();
1039         if (verbose)
1040                 printk("Jumping to dictionary %s...\n", basedict);
1041
1042         /* If a console file has been specified, open it */
1043         if (confile)
1044                 console = fopen(confile, "w");
1045
1046         srcbasedict = basedict; 
1047
1048         enterforth((xt_t)PC);
1049
1050         /* Close the console file */
1051         if (console)
1052                 fclose(console);
1053 }
1054
1055 static void new_dictionary(const char *source)
1056 {
1057         build_dictionary();
1058
1059         interpret_source((char *)source);
1060
1061         if (verbose || errors > 0) {
1062                 printk("interpretion finished. %d errors occured.\n",
1063                        errors);
1064         }
1065 }
1066
1067 /*
1068  * main loop
1069  */
1070
1071 #define BANNER  "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
1072                 "This software comes with absolutely no warranty. "\
1073                 "All rights reserved.\n\n"
1074
1075 #ifdef __GLIBC__
1076 #define USAGE   "Usage: %s [options] [dictionary file|source file]\n\n" \
1077                 "   -h|--help           show this help\n"               \
1078                 "   -V|--version        print version and exit\n"       \
1079                 "   -v|--verbose        print debugging information\n"  \
1080                 "   -I|--include dir    add dir to include path\n"      \
1081                 "   -d|--source-dictionary bootstrap.dict\n"            \
1082                 "                       use this dictionary as base\n"  \
1083                 "   -D|--target-dictionary output.dict\n"               \
1084                 "                       write to output.dict\n"         \
1085                 "   -c|--console output.log\n"          \
1086                 "                       write kernel console output to log file\n"      \
1087                 "   -s|--segfault       install segfault handler\n"     \
1088                 "   -M|--dependency-dump file\n"                         \
1089                 "                       dump dependencies in Makefile format\n\n" \
1090                 "   -x|--hexdump        output format is C language hex dump\n"
1091 #else
1092 #define USAGE   "Usage: %s [options] [dictionary file|source file]\n\n" \
1093                 "   -h          show this help\n"               \
1094                 "   -V          print version and exit\n"       \
1095                 "   -v          print debugging information\n"  \
1096                 "   -I          add dir to include path\n"      \
1097                 "   -d bootstrap.dict\n"                        \
1098                 "               use this dictionary as base\n"  \
1099                 "   -D output.dict\n"                           \
1100                 "               write to output.dict\n"         \
1101                 "   -c output.log\n"            \
1102                 "               write kernel console output to log file\n"      \
1103                 "   -s          install segfault handler\n\n"   \
1104                 "   -M file     dump dependencies in Makefile format\n\n" \
1105                 "   -x          output format is C language hex dump\n"
1106 #endif
1107
1108 int main(int argc, char *argv[])
1109 {
1110         struct sigaction sa;
1111
1112         unsigned char *ressources=NULL; /* All memory used by us */
1113         const char *dictname = NULL;
1114         char *basedict = NULL;
1115         char *consolefile = NULL;
1116         char *depfilename = NULL;
1117
1118         unsigned char *bootstrapdict[2];
1119         int c, cnt, hexdump = 0;
1120
1121         const char *optstring = "VvhsI:d:D:c:M:x?";
1122
1123         while (1) {
1124 #ifdef __GLIBC__
1125                 int option_index = 0;
1126                 static struct option long_options[] = {
1127                         {"version", 0, NULL, 'V'},
1128                         {"verbose", 0, NULL, 'v'},
1129                         {"help", 0, NULL, 'h'},
1130                         {"segfault", 0, NULL, 's'},
1131                         {"include", 1, NULL, 'I'},
1132                         {"source-dictionary", 1, NULL, 'd'},
1133                         {"target-dictionary", 1, NULL, 'D'},
1134                         {"console", 1, NULL, 'c'},
1135                         {"dependency-dump", 1, NULL, 'M'},
1136                         {"hexdump", 0, NULL, 'x'},
1137                 };
1138
1139                 /*
1140                  * option handling
1141                  */
1142
1143                 c = getopt_long(argc, argv, optstring, long_options,
1144                                 &option_index);
1145 #else
1146                 c = getopt(argc, argv, optstring);
1147 #endif
1148                 if (c == -1)
1149                         break;
1150
1151                 switch (c) {
1152                 case 'V':
1153                         printk("Version " OPENBIOS_VERSION_STR "\n");
1154                         return 0;
1155                 case 'h':
1156                 case '?':
1157                         printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
1158                                argv[0]);
1159                         return 0;
1160                 case 'v':
1161                         verbose = 1;
1162                         break;
1163                 case 's':
1164                         segfault = 1;
1165                         break;
1166                 case 'I':
1167 #ifdef CONFIG_DEBUG_INTERPRETER
1168                         printk("adding '%s' to include path\n", optarg);
1169 #endif
1170                         add_includepath(optarg);
1171                         break;
1172                 case 'd':
1173                         if (!basedict) {
1174                                 basedict = optarg;
1175                         }
1176                         break;
1177                 case 'D':
1178                         if(!dictname) {
1179                                 dictname = optarg;
1180                         }
1181                         break;
1182                 case 'c':
1183                         if (!consolefile) {
1184                                 consolefile = optarg;
1185                         }
1186                         break;
1187                 case 'M':
1188                         if (!depfilename) {
1189                                 depfilename = optarg;
1190                         }
1191                         break;
1192                 case 'x':
1193                         hexdump = 1;
1194                         break;
1195                 default:
1196                         return 1;
1197                 }
1198         }
1199
1200         if (!dictname) {
1201             dictname = "bootstrap.dict";
1202         }
1203         if (verbose) {
1204                 printk(BANNER);
1205                 printk("Using source dictionary '%s'\n", basedict);
1206                 printk("Dumping final dictionary to '%s'\n", dictname);
1207                 printk("Dumping dependencies to '%s'\n", depfilename);
1208         }
1209
1210         if (argc < optind) {
1211                 printk(USAGE, argv[0]);
1212                 return 1;
1213         }
1214
1215         if (depfilename) {
1216             depfile = fopen(depfilename, "w");
1217             if (!depfile) {
1218                 printk("panic: can't write to dependency file '%s'.\n",
1219                        depfilename);
1220                 exit(1);
1221             }
1222             fprintf(depfile, "%s:", dictname);
1223         }
1224
1225         /*
1226          * Get all required resources
1227          */
1228
1229
1230         ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
1231         if (!ressources) {
1232                 printk("panic: not enough memory on host system.\n");
1233                 return 1;
1234         }
1235
1236 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
1237         base_address=(unsigned long)ressources;
1238 #endif
1239
1240         memory = (ucell *)ressources;
1241
1242         bootstrapdict[0] = ressources + MEMORY_SIZE;
1243         bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
1244         trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
1245
1246 #ifdef CONFIG_DEBUG_INTERPRETER
1247         printf("memory: %p\n",memory);
1248         printf("dict1: %p\n",bootstrapdict[0]);
1249         printf("dict2: %p\n",bootstrapdict[1]);
1250         printf("trampoline: %p\n",trampoline);
1251         printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
1252                                 DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
1253                         TRAMPOLINE_SIZE);
1254 #endif
1255
1256         if (trampoline == NULL) {
1257                 /* We're using side effects which is to some extent nasty */
1258                 printf("WARNING: no trampoline!\n");
1259         } else {
1260                 init_trampoline(trampoline);
1261         }
1262
1263         if (!segfault) {
1264                 if (verbose)
1265                         printk("Installing SIGSEGV handler...");
1266
1267                 sa.sa_sigaction = segv_handler;
1268                 sigemptyset(&sa.sa_mask);
1269                 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
1270                 sigaction(SIGSEGV, &sa, NULL);
1271
1272                 if (verbose)
1273                         printk("done.\n");
1274         }
1275
1276         /*
1277          * Now do the real work
1278          */
1279
1280         for (cnt=0; cnt<2; cnt++) {
1281                 if (verbose) {
1282                         printk("Compiling dictionary %d/%d\n", cnt+1, 2);
1283                 }
1284                 dict=bootstrapdict[cnt];
1285                 if(!basedict) {
1286                         new_dictionary(argv[optind]);
1287                 } else {
1288                         for (c=argc-1; c>=optind; c--)
1289                                 include_file(argv[c]);
1290
1291                         run_dictionary(basedict, consolefile);
1292                 }
1293                 if (depfile) {
1294                         fprintf(depfile, "\n");
1295                         fclose(depfile);
1296                         depfile = NULL;
1297                 }
1298                 if(errors)
1299                         break;
1300         }
1301
1302 #ifndef CONFIG_DEBUG_INTERPRETER
1303         if (errors)
1304                 printk("dictionary not dumped to file.\n");
1305         else
1306 #endif
1307         {
1308                 relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
1309                 if (hexdump) {
1310                     write_dictionary_hex(dictname);
1311                 } else {
1312                     write_dictionary(dictname);
1313                 }
1314         }
1315
1316         free(ressources);
1317
1318         if (errors)
1319             return 1;
1320         else
1321             return 0;
1322 }