ppc64: Don't set Kp bit on SLB
[openbios/afaerber.git] / kernel / bootstrap.c
blob546ffee4672ec5ced42b10ef2f3db6531c9b9b3e
1 /* tag: forth bootstrap environment
3 * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz
5 * See the file "COPYING" for further information about
6 * the copyright and warranty status of this work.
7 */
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>
19 #ifdef __GLIBC__
20 #define _GNU_SOURCE
21 #include <getopt.h>
22 #endif
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"
32 #define MAX_PATH_LEN 256
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 */
38 /* state variables */
39 static ucell *latest, *state, *base;
40 static ucell *memory;
41 ucell *trampoline;
43 /* local variables */
44 static int errors = 0;
45 static int segfault = 0;
46 static int verbose = 0;
48 #define MAX_SRC_FILES 128
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;
55 static char *srcbasedict;
57 /* console variables */
58 static FILE *console;
60 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
61 unsigned long base_address;
62 #endif
64 /* include path handling */
65 typedef struct include_path include;
66 struct include_path {
67 const char *path;
68 include *next;
71 static include includes = { ".", NULL };
72 static FILE *depfile;
74 static ucell * relocation_address=NULL;
75 static int relocation_length=0;
77 /* the word names are used to generate the prim words in the
78 * dictionary. This is done by the C written interpreter.
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)"
96 * dictionary related functions.
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.
104 static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
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;
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));
116 for (i=0; i<l; i++) {
118 pos=i/BITS;
119 bit=i&~(-BITS);
121 if(d1[i]==d2[i]) {
122 reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
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));
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;
143 static void write_dictionary(const char *filename)
145 FILE *f;
146 unsigned char *write_data, *walk_data;
147 int write_len;
148 dictionary_header_t *header;
149 u32 checksum=0;
152 * get memory for dictionary
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);
162 memset(write_data, 0, write_len);
165 * prepare dictionary header
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)),
187 * prepare dictionary data
190 walk_data=write_data+sizeof(dictionary_header_t);
191 memcpy (walk_data, dict, dicthead);
194 * prepare relocation data.
195 * relocation_address is zero when writing a dictionary core.
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;
213 * Calculate Checksum
216 walk_data=write_data;
217 while (walk_data<write_data+write_len) {
218 checksum+=read_long(walk_data);
219 walk_data+=sizeof(u32);
221 checksum=(u32)-checksum;
223 header->checksum=target_long(checksum);
225 if (verbose) {
226 dump_header(header);
229 f = fopen(filename, "w");
230 if (!f) {
231 printk("panic: can't write to dictionary '%s'.\n", filename);
232 exit(1);
235 fwrite(write_data, write_len, 1, f);
237 free(write_data);
238 fclose(f);
240 #ifdef CONFIG_DEBUG_DICTIONARY
241 printk("wrote dictionary to file %s.\n", filename);
242 #endif
246 * Write dictionary as a list of ucell hex values to filename. Array
247 * header and end lines are not generated.
249 * Cells with relocations are output using the expression
250 * DICTIONARY_BASE + value.
252 * Define some helpful constants.
254 static void write_dictionary_hex(const char *filename)
256 FILE *f;
257 ucell *walk;
259 f = fopen(filename, "w");
260 if (!f) {
261 printk("panic: can't write to dictionary '%s'.\n", filename);
262 exit(1);
265 for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) {
266 int pos, bit, l;
267 ucell val;
269 l = (walk - (ucell *)dict);
270 pos = l / BITS;
271 bit = l & ~(-BITS);
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);
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);
288 #ifdef CONFIG_DEBUG_DICTIONARY
289 printk("wrote dictionary to file %s.\n", filename);
290 #endif
293 static ucell read_dictionary(char *fil)
295 int ilen;
296 ucell ret;
297 char *mem;
298 FILE *f;
299 struct stat finfo;
301 if (stat(fil, &finfo))
302 return 0;
304 ilen = finfo.st_size;
306 if ((mem = malloc(ilen)) == NULL) {
307 printk("panic: not enough memory.\n");
308 exit(1);
311 f = fopen(fil, "r");
312 if (!f) {
313 printk("panic: can't open dictionary.\n");
314 exit(1);
317 if (fread(mem, ilen, 1, f) != 1) {
318 printk("panic: can't read dictionary.\n");
319 fclose(f);
320 exit(1);
322 fclose(f);
324 ret = load_dictionary(mem, ilen);
326 free(mem);
327 return ret;
332 * C Parser related functions
336 * skipws skips all whitespaces (space, tab, newline) from the input file
339 static void skipws(FILE * f)
341 int c;
342 while (!feof(f)) {
343 c = getc(f);
345 if (c == ' ' || c == '\t')
346 continue;
348 if (c == '\n') {
349 srclines[cursrc - 1]++;
350 continue;
353 ungetc(c, f);
354 break;
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.
365 static int parse(FILE * f, char *line, char delim)
367 int cnt = 0, c = 0;
369 while (!feof(f)) {
370 c = getc(f);
372 if (delim && c == delim)
373 break;
375 if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
376 break;
378 line[cnt++] = c;
381 /* Update current line number */
382 if (c == '\n') {
383 srclines[cursrc - 1]++;
386 line[cnt] = 0;
388 return cnt;
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.
396 static void parse_word(FILE * f, char *line)
398 skipws(f);
399 parse(f, line, 0);
403 static void writestring(const char *str)
405 unsigned int i;
406 for (i = 0; i < strlen(str); i++) {
407 dict[dicthead + i] = str[i];
409 dicthead += i + 1;
410 dict[dicthead - 1] = (char) strlen(str) + 128;
413 #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
414 #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
417 * reveal a word, ie. make it visible.
420 static void reveal(void)
422 *last = *latest;
426 * dictionary padding
429 static void paddict(ucell align)
431 while (dicthead % align != 0)
432 writebyte(0);
436 * generic forth word creator function.
439 static void fcreate(const char *word, ucell cfaval)
441 if (strlen(word) == 0) {
442 printk("WARNING: tried to create unnamed word.\n");
443 return;
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);
459 static ucell *buildvariable(const char *name, cell defval)
461 fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */
462 writecell(defval);
463 return (ucell *) (dict + dicthead - sizeof(cell));
466 static void buildconstant(const char *name, cell defval)
468 fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */
469 writecell(defval);
472 static void builddefer(const char *name)
474 fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */
475 writecell((ucell)0);
476 writecell((ucell)findword("(semis)"));
480 * Include file handling
483 static void add_includepath(char *path)
485 include *incl = &includes;
486 include *newpath;
488 while (incl->next)
489 incl = incl->next;
491 newpath = malloc(sizeof(include));
492 if (!newpath) {
493 printk("panic: not enough memory for include path.\n");
494 exit(1);
497 incl->next = newpath;
498 newpath->path = path;
499 newpath->next = NULL;
503 static FILE *fopen_include(const char *fil)
505 char fullpath[MAX_PATH_LEN];
506 FILE *ret;
507 include *incl = &includes;
509 while (incl) {
510 snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
512 ret = fopen(fullpath, "r");
513 if (ret != NULL) {
515 #ifdef CONFIG_DEBUG_INTERPRETER
516 printk("Including '%s'\n", name );
517 #endif
518 srcfilenames[cursrc] = strdup(fil);
519 srclines [ cursrc ] = 1;
520 srcfiles [ cursrc++ ] = ret;
522 if (depfile) {
523 fprintf(depfile, " %s", fullpath);
526 return ret;
529 incl = incl->next;
531 return NULL;
536 * Forth exception handler
539 void exception(cell no)
541 printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
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);
576 exit(1);
581 * This is the C version of the forth interpreter
584 static int interpret_source(char *fil)
586 FILE *f;
587 char tib[160];
588 cell num;
589 char *test;
591 const ucell SEMIS = (ucell)findword("(semis)");
592 const ucell LIT = (ucell)findword("(lit)");
593 const ucell DOBRANCH = (ucell)findword("dobranch");
595 if ((f = fopen_include(fil)) == NULL) {
596 printk("error while loading source file '%s'\n", fil);
597 errors++;
598 exit(1);
601 /* FIXME: We should read this file at
602 * once. No need to get it char by char
605 while (!feof(f)) {
606 xt_t res;
607 parse_word(f, tib);
609 /* if there is actually no word, we continue right away */
610 if (strlen(tib) == 0) {
611 continue;
614 /* Checking for builtin words that are needed to
615 * bootstrap the forth base dictionary.
618 if (!strcmp(tib, "(")) {
619 parse(f, tib, ')');
620 continue;
623 if (!strcmp(tib, "\\")) {
624 parse(f, tib, '\n');
625 continue;
628 if (!strcmp(tib, ":")) {
629 parse_word(f, tib);
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;
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;
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;
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;
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;
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;
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;
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);
717 continue;
718 /* we have no error detection here */
721 if (!strcasecmp(tib, "s\"")) {
722 int cnt;
723 cell loco;
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;
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);
769 continue;
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));
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
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);
804 fclose(f);
805 cursrc--;
807 return 0;
810 static int build_dictionary(void)
812 ucell lfa = 0;
813 unsigned int i;
815 /* we need a temporary place for latest outside the dictionary */
816 latest = &lfa;
818 /* starting a new dictionary: clear dicthead */
819 dicthead = 0;
821 #ifdef CONFIG_DEBUG_DICTIONARY
822 printk("building dictionary, %d primitives.\nbuilt words:",
823 sizeof(wordnames) / sizeof(void *));
824 #endif
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
834 #ifdef CONFIG_DEBUG_DICTIONARY
835 printk(".\n");
836 #endif
838 /* get last/latest and state */
839 state = buildvariable("state", 0);
840 last = buildvariable("forth-last", 0);
841 latest = buildvariable("latest", 0);
843 *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
845 base=buildvariable("base", 10);
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));
853 reveal();
854 if (verbose) {
855 printk("Dictionary initialization finished.\n");
857 return 0;
861 * functions used by primitives
864 int availchar(void)
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;
873 tmp = getc( srcfiles[cursrc-1] );
874 if (tmp != EOF) {
875 ungetc(tmp, srcfiles[cursrc-1]);
876 return -1;
879 fclose(srcfiles[--cursrc]);
881 return availchar();
884 int get_inputbyte( void )
886 int tmp;
888 if( cursrc < 1 ) {
889 interruptforth |= FORTH_INTSTAT_STOP;
890 return 0;
893 tmp = getc( srcfiles[cursrc-1] );
895 /* Update current line number */
896 if (tmp == '\n') {
897 srclines[cursrc - 1]++;
900 if (tmp != EOF) {
901 return tmp;
904 fclose(srcfiles[--cursrc]);
906 return get_inputbyte();
909 void put_outputbyte( int c )
911 if (console)
912 fputc(c, console);
916 * segmentation fault handler. linux specific?
919 static void
920 segv_handler(int signo __attribute__ ((unused)),
921 siginfo_t * si, void *context __attribute__ ((unused)))
923 static int count = 0;
924 ucell addr = 0xdeadbeef;
926 if (count) {
927 printk("Died while dumping forth dictionary core.\n");
928 goto out;
931 count++;
933 if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
934 addr = read_cell(cell2pointer(PC));
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);
942 printdstack();
943 printrstack();
945 printk("Writing dictionary core file\n");
946 write_dictionary("forth.dict.core");
948 out:
949 exit(1);
953 * allocate memory and prepare engine for memory management.
956 static void init_memory(void)
958 memset(memory, 0, MEMORY_SIZE);
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
967 PUSH(pointer2cell(memory)+sizeof(cell));
968 PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
972 void
973 include_file( const char *name )
975 FILE *file;
977 if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
978 printk("\npanic: Maximum include depth reached!\n");
979 exit(1);
982 file = fopen_include( name );
983 if( !file ) {
984 printk("\npanic: Failed opening file '%s'\n", name );
985 exit(1);
990 void
991 encode_file( const char *name )
993 FILE *file = fopen_include(name);
994 int size;
996 if( !file ) {
997 printk("\npanic: Can't open '%s'\n", name );
998 exit(1);
1000 fseek( file, 0, SEEK_END );
1001 size = ftell( file );
1002 fseek( file, 0, SEEK_SET );
1004 if (verbose) {
1005 printk("\nEncoding %s [%d bytes]\n", name, size );
1007 fread( dict + dicthead, size, 1, file );
1008 PUSH( pointer2cell(dict + dicthead) );
1009 PUSH( size );
1010 dicthead += size;
1014 static void run_dictionary(char *basedict, char *confile)
1016 if(!basedict)
1017 return;
1019 read_dictionary(basedict);
1020 PC = (ucell)findword("initialize");
1022 if (!PC) {
1023 if (verbose) {
1024 printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
1026 return;
1029 if(!srcfiles[0]) {
1030 cursrc = 1;
1031 srcfiles[cursrc-1] = stdin;
1034 dstackcnt=0;
1035 rstackcnt=0;
1037 init_memory();
1038 if (verbose)
1039 printk("Jumping to dictionary %s...\n", basedict);
1041 /* If a console file has been specified, open it */
1042 if (confile)
1043 console = fopen(confile, "w");
1045 srcbasedict = basedict;
1047 enterforth((xt_t)PC);
1049 /* Close the console file */
1050 if (console)
1051 fclose(console);
1054 static void new_dictionary(const char *source)
1056 build_dictionary();
1058 interpret_source((char *)source);
1060 if (verbose || errors > 0) {
1061 printk("interpretion finished. %d errors occured.\n",
1062 errors);
1067 * main loop
1070 #define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
1071 "This software comes with absolutely no warranty. "\
1072 "All rights reserved.\n\n"
1074 #ifdef __GLIBC__
1075 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1076 " -h|--help show this help\n" \
1077 " -V|--version print version and exit\n" \
1078 " -v|--verbose print debugging information\n" \
1079 " -I|--include dir add dir to include path\n" \
1080 " -d|--source-dictionary bootstrap.dict\n" \
1081 " use this dictionary as base\n" \
1082 " -D|--target-dictionary output.dict\n" \
1083 " write to output.dict\n" \
1084 " -c|--console output.log\n" \
1085 " write kernel console output to log file\n" \
1086 " -s|--segfault install segfault handler\n" \
1087 " -M|--dependency-dump file\n" \
1088 " dump dependencies in Makefile format\n\n" \
1089 " -x|--hexdump output format is C language hex dump\n"
1090 #else
1091 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1092 " -h show this help\n" \
1093 " -V print version and exit\n" \
1094 " -v print debugging information\n" \
1095 " -I add dir to include path\n" \
1096 " -d bootstrap.dict\n" \
1097 " use this dictionary as base\n" \
1098 " -D output.dict\n" \
1099 " write to output.dict\n" \
1100 " -c output.log\n" \
1101 " write kernel console output to log file\n" \
1102 " -s install segfault handler\n\n" \
1103 " -M file dump dependencies in Makefile format\n\n" \
1104 " -x output format is C language hex dump\n"
1105 #endif
1107 int main(int argc, char *argv[])
1109 struct sigaction sa;
1111 unsigned char *ressources=NULL; /* All memory used by us */
1112 const char *dictname = NULL;
1113 char *basedict = NULL;
1114 char *consolefile = NULL;
1115 char *depfilename = NULL;
1117 unsigned char *bootstrapdict[2];
1118 int c, cnt, hexdump = 0;
1120 const char *optstring = "VvhsI:d:D:c:M:x?";
1122 while (1) {
1123 #ifdef __GLIBC__
1124 int option_index = 0;
1125 static struct option long_options[] = {
1126 {"version", 0, NULL, 'V'},
1127 {"verbose", 0, NULL, 'v'},
1128 {"help", 0, NULL, 'h'},
1129 {"segfault", 0, NULL, 's'},
1130 {"include", 1, NULL, 'I'},
1131 {"source-dictionary", 1, NULL, 'd'},
1132 {"target-dictionary", 1, NULL, 'D'},
1133 {"console", 1, NULL, 'c'},
1134 {"dependency-dump", 1, NULL, 'M'},
1135 {"hexdump", 0, NULL, 'x'},
1139 * option handling
1142 c = getopt_long(argc, argv, optstring, long_options,
1143 &option_index);
1144 #else
1145 c = getopt(argc, argv, optstring);
1146 #endif
1147 if (c == -1)
1148 break;
1150 switch (c) {
1151 case 'V':
1152 printk("Version " OPENBIOS_VERSION_STR "\n");
1153 return 0;
1154 case 'h':
1155 case '?':
1156 printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
1157 argv[0]);
1158 return 0;
1159 case 'v':
1160 verbose = 1;
1161 break;
1162 case 's':
1163 segfault = 1;
1164 break;
1165 case 'I':
1166 #ifdef CONFIG_DEBUG_INTERPRETER
1167 printk("adding '%s' to include path\n", optarg);
1168 #endif
1169 add_includepath(optarg);
1170 break;
1171 case 'd':
1172 if (!basedict) {
1173 basedict = optarg;
1175 break;
1176 case 'D':
1177 if(!dictname) {
1178 dictname = optarg;
1180 break;
1181 case 'c':
1182 if (!consolefile) {
1183 consolefile = optarg;
1185 break;
1186 case 'M':
1187 if (!depfilename) {
1188 depfilename = optarg;
1190 break;
1191 case 'x':
1192 hexdump = 1;
1193 break;
1194 default:
1195 return 1;
1199 if (!dictname) {
1200 dictname = "bootstrap.dict";
1202 if (verbose) {
1203 printk(BANNER);
1204 printk("Using source dictionary '%s'\n", basedict);
1205 printk("Dumping final dictionary to '%s'\n", dictname);
1206 printk("Dumping dependencies to '%s'\n", depfilename);
1209 if (argc < optind) {
1210 printk(USAGE, argv[0]);
1211 return 1;
1214 if (depfilename) {
1215 depfile = fopen(depfilename, "w");
1216 if (!depfile) {
1217 printk("panic: can't write to dependency file '%s'.\n",
1218 depfilename);
1219 exit(1);
1221 fprintf(depfile, "%s:", dictname);
1225 * Get all required resources
1229 ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
1230 if (!ressources) {
1231 printk("panic: not enough memory on host system.\n");
1232 return 1;
1235 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
1236 base_address=(unsigned long)ressources;
1237 #endif
1239 memory = (ucell *)ressources;
1241 bootstrapdict[0] = ressources + MEMORY_SIZE;
1242 bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
1243 trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
1245 #ifdef CONFIG_DEBUG_INTERPRETER
1246 printf("memory: %p\n",memory);
1247 printf("dict1: %p\n",bootstrapdict[0]);
1248 printf("dict2: %p\n",bootstrapdict[1]);
1249 printf("trampoline: %p\n",trampoline);
1250 printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
1251 DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
1252 TRAMPOLINE_SIZE);
1253 #endif
1255 if (trampoline == NULL) {
1256 /* We're using side effects which is to some extent nasty */
1257 printf("WARNING: no trampoline!\n");
1258 } else {
1259 init_trampoline(trampoline);
1262 if (!segfault) {
1263 if (verbose)
1264 printk("Installing SIGSEGV handler...");
1266 sa.sa_sigaction = segv_handler;
1267 sigemptyset(&sa.sa_mask);
1268 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
1269 sigaction(SIGSEGV, &sa, NULL);
1271 if (verbose)
1272 printk("done.\n");
1276 * Now do the real work
1279 for (cnt=0; cnt<2; cnt++) {
1280 if (verbose) {
1281 printk("Compiling dictionary %d/%d\n", cnt+1, 2);
1283 dict=bootstrapdict[cnt];
1284 if(!basedict) {
1285 new_dictionary(argv[optind]);
1286 } else {
1287 for (c=argc-1; c>=optind; c--)
1288 include_file(argv[c]);
1290 run_dictionary(basedict, consolefile);
1292 if (depfile) {
1293 fprintf(depfile, "\n");
1294 fclose(depfile);
1295 depfile = NULL;
1297 if(errors)
1298 break;
1301 #ifndef CONFIG_DEBUG_INTERPRETER
1302 if (errors)
1303 printk("dictionary not dumped to file.\n");
1304 else
1305 #endif
1307 relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
1308 if (hexdump) {
1309 write_dictionary_hex(dictname);
1310 } else {
1311 write_dictionary(dictname);
1315 free(ressources);
1317 if (errors)
1318 return 1;
1319 else
1320 return 0;