Generate Makefile dependencies also from Forth files
[openbios.git] / kernel / bootstrap.c
blob94aaeb80360a0a1edd5808d3bff66394d9fb8552
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.
99 static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
101 ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
102 ucell *reloc_table;
103 int pos, bit;
104 int l=(length+(sizeof(cell)-1))/sizeof(ucell), i;
106 /* prepare relocation table */
107 relocation_length=(length+BITS-1)/BITS;
108 reloc_table = malloc(relocation_length*sizeof(cell));
109 memset(reloc_table,0,relocation_length*sizeof(cell));
111 for (i=0; i<l; i++) {
113 pos=i/BITS;
114 bit=i&~(-BITS);
116 if(d1[i]==d2[i]) {
117 reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
119 // This check might bring false positives in data.
120 //if(d1[i] >= pointer2cell(dict_one) &&
121 // d1[i] <= pointer2cell(dict_one+length))
122 // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
123 } else {
124 /* This is a pointer, it needs relocation, d2==dict */
125 reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
126 d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
130 #ifdef CONFIG_DEBUG_DICTIONARY
131 printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict);
132 for (i=0; i< relocation_length ; i++)
133 printk("reloc %d %lx\n",i+1, reloc_table[i]);
134 #endif
135 relocation_address=reloc_table;
138 static void write_dictionary(const char *filename)
140 FILE *f;
141 unsigned char *write_data, *walk_data;
142 int write_len;
143 dictionary_header_t *header;
144 u32 checksum=0;
147 * get memory for dictionary
150 write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell);
151 write_data = malloc(write_len);
152 if(!write_data) {
153 printk("panic: can't allocate memory for output dictionary (%d"
154 " bytes\n", write_len);
155 exit(1);
157 memset(write_data, 0, write_len);
160 * prepare dictionary header
163 header = (dictionary_header_t *)write_data;
164 *header = (dictionary_header_t){
165 .signature = DICTID,
166 .version = 2,
167 .cellsize = sizeof(ucell),
168 #ifdef CONFIG_BIG_ENDIAN
169 .endianess = -1,
170 #else
171 .endianess = 0,
172 #endif
173 .checksum = 0,
174 .compression = 0,
175 .relocation = -1,
176 .length = target_ulong((uint32_t)dicthead),
177 .last = target_ucell((ucell)((unsigned long)last
178 - (unsigned long)dict)),
182 * prepare dictionary data
185 walk_data=write_data+sizeof(dictionary_header_t);
186 memcpy (walk_data, dict, dicthead);
189 * prepare relocation data.
190 * relocation_address is zero when writing a dictionary core.
193 if (relocation_address) {
194 #ifdef CONFIG_DEBUG_DICTIONARY
195 printk("writing %d reloc cells \n",relocation_length);
196 #endif
197 walk_data += dicthead;
198 memcpy(walk_data, relocation_address,
199 relocation_length*sizeof(cell));
200 /* free relocation information */
201 free(relocation_address);
202 relocation_address=NULL;
203 } else {
204 header->relocation=0;
208 * Calculate Checksum
211 walk_data=write_data;
212 while (walk_data<write_data+write_len) {
213 checksum+=read_long(walk_data);
214 walk_data+=sizeof(u32);
216 checksum=(u32)-checksum;
218 header->checksum=target_long(checksum);
220 if (verbose) {
221 dump_header(header);
224 f = fopen(filename, "w");
225 if (!f) {
226 printk("panic: can't write to dictionary '%s'.\n", filename);
227 exit(1);
230 fwrite(write_data, write_len, 1, f);
232 free(write_data);
233 fclose(f);
235 #ifdef CONFIG_DEBUG_DICTIONARY
236 printk("wrote dictionary to file %s.\n", filename);
237 #endif
240 static ucell read_dictionary(char *fil)
242 int ilen;
243 ucell ret;
244 char *mem;
245 FILE *f;
246 struct stat finfo;
248 if (stat(fil, &finfo))
249 return 0;
251 ilen = finfo.st_size;
253 if ((mem = malloc(ilen)) == NULL) {
254 printk("panic: not enough memory.\n");
255 exit(1);
258 f = fopen(fil, "r");
259 if (!f) {
260 printk("panic: can't open dictionary.\n");
261 exit(1);
264 if (fread(mem, ilen, 1, f) != 1) {
265 printk("panic: can't read dictionary.\n");
266 fclose(f);
267 exit(1);
269 fclose(f);
271 ret = load_dictionary(mem, ilen);
273 free(mem);
274 return ret;
279 * C Parser related functions
283 * skipws skips all whitespaces (space, tab, newline) from the input file
286 static void skipws(FILE * f)
288 int c;
289 while (!feof(f)) {
290 c = getc(f);
292 if (c == ' ' || c == '\t')
293 continue;
295 if (c == '\n') {
296 srclines[cursrc - 1]++;
297 continue;
300 ungetc(c, f);
301 break;
306 * parse gets the next word from the input stream, delimited by
307 * delim. If delim is 0, any word delimiter will end the stream
308 * word delimiters are space, tab and newline. The resulting word
309 * will be put zero delimited to the char array line.
312 static int parse(FILE * f, char *line, char delim)
314 int cnt = 0, c = 0;
316 while (!feof(f)) {
317 c = getc(f);
319 if (delim && c == delim)
320 break;
322 if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
323 break;
325 line[cnt++] = c;
328 /* Update current line number */
329 if (c == '\n') {
330 srclines[cursrc - 1]++;
333 line[cnt] = 0;
335 return cnt;
339 * parse_word is a small helper that skips whitespaces before a word.
340 * it's behaviour is similar to the forth version parse-word.
343 static void parse_word(FILE * f, char *line)
345 skipws(f);
346 parse(f, line, 0);
350 static void writestring(const char *str)
352 unsigned int i;
353 for (i = 0; i < strlen(str); i++) {
354 dict[dicthead + i] = str[i];
356 dicthead += i + 1;
357 dict[dicthead - 1] = (char) strlen(str) + 128;
360 #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
361 #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
364 * reveal a word, ie. make it visible.
367 static void reveal(void)
369 *last = *latest;
373 * dictionary padding
376 static void paddict(ucell align)
378 while (dicthead % align != 0)
379 writebyte(0);
383 * generic forth word creator function.
386 static void fcreate(const char *word, ucell cfaval)
388 if (strlen(word) == 0) {
389 printk("WARNING: tried to create unnamed word.\n");
390 return;
393 writestring(word);
394 /* get us at least 1 byte for flags */
395 writebyte(0);
396 paddict(sizeof(cell));
397 /* set flags high bit. */
398 dict[dicthead - 1] = 128;
399 /* lfa and cfa */
400 writecell(read_ucell(latest));
401 *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell));
402 writecell(cfaval);
406 static ucell *buildvariable(const char *name, cell defval)
408 fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */
409 writecell(defval);
410 return (ucell *) (dict + dicthead - sizeof(cell));
413 static void buildconstant(const char *name, cell defval)
415 fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */
416 writecell(defval);
419 static void builddefer(const char *name)
421 fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */
422 writecell((ucell)0);
423 writecell((ucell)findword("(semis)"));
427 * Include file handling
430 static void add_includepath(char *path)
432 include *incl = &includes;
433 include *newpath;
435 while (incl->next)
436 incl = incl->next;
438 newpath = malloc(sizeof(include));
439 if (!newpath) {
440 printk("panic: not enough memory for include path.\n");
441 exit(1);
444 incl->next = newpath;
445 newpath->path = path;
446 newpath->next = NULL;
450 static FILE *fopen_include(const char *fil)
452 char fullpath[MAX_PATH_LEN];
453 FILE *ret;
454 include *incl = &includes;
456 while (incl) {
457 snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
459 ret = fopen(fullpath, "r");
460 if (ret != NULL) {
462 #ifdef CONFIG_DEBUG_INTERPRETER
463 printk("Including '%s'\n", name );
464 #endif
465 srcfilenames[cursrc] = strdup(fil);
466 srclines [ cursrc ] = 1;
467 srcfiles [ cursrc++ ] = ret;
469 if (depfile) {
470 fprintf(depfile, " %s", fullpath);
473 return ret;
476 incl = incl->next;
478 return NULL;
483 * Forth exception handler
486 void exception(cell no)
488 printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
490 /* See also forth/bootstrap/interpreter.fs */
491 switch (no) {
492 case -1:
493 case -2:
494 printk("Aborted.\n");
495 break;
496 case -3:
497 printk("Stack Overflow.\n");
498 break;
499 case -4:
500 printk("Stack Underflow.\n");
501 break;
502 case -5:
503 printk("Return Stack Overflow.\n");
504 break;
505 case -6:
506 printk("Return Stack Underflow.\n");
507 break;
508 case -19:
509 printk("undefined word.\n");
510 break;
511 case -21:
512 printk("out of memory.\n");
513 break;
514 case -33:
515 printk("undefined method.\n");
516 break;
517 case -34:
518 printk("no such device.\n");
519 break;
520 default:
521 printk("error %" FMT_CELL_d " occured.\n", no);
523 exit(1);
528 * This is the C version of the forth interpreter
531 static int interpret_source(char *fil)
533 FILE *f;
534 char tib[160];
535 cell num;
536 char *test;
538 const ucell SEMIS = (ucell)findword("(semis)");
539 const ucell LIT = (ucell)findword("(lit)");
540 const ucell DOBRANCH = (ucell)findword("dobranch");
542 if ((f = fopen_include(fil)) == NULL) {
543 printk("error while loading source file '%s'\n", fil);
544 errors++;
545 exit(1);
548 /* FIXME: We should read this file at
549 * once. No need to get it char by char
552 while (!feof(f)) {
553 xt_t res;
554 parse_word(f, tib);
556 /* if there is actually no word, we continue right away */
557 if (strlen(tib) == 0) {
558 continue;
561 /* Checking for builtin words that are needed to
562 * bootstrap the forth base dictionary.
565 if (!strcmp(tib, "(")) {
566 parse(f, tib, ')');
567 continue;
570 if (!strcmp(tib, "\\")) {
571 parse(f, tib, '\n');
572 continue;
575 if (!strcmp(tib, ":")) {
576 parse_word(f, tib);
578 #ifdef CONFIG_DEBUG_INTERPRETER
579 printk("create colon word %s\n\n", tib);
580 #endif
581 fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */
582 *state = (ucell) (-1);
583 continue;
586 if (!strcmp(tib, ";")) {
587 #ifdef CONFIG_DEBUG_INTERPRETER
588 printk("finish colon definition\n\n");
589 #endif
590 writecell((cell)SEMIS);
591 *state = (ucell) 0;
592 reveal();
593 continue;
596 if (!strcasecmp(tib, "variable")) {
597 parse_word(f, tib);
598 #ifdef CONFIG_DEBUG_INTERPRETER
599 printk("defining variable %s\n\n", tib);
600 #endif
601 buildvariable(tib, 0);
602 reveal();
603 continue;
606 if (!strcasecmp(tib, "constant")) {
607 parse_word(f, tib);
608 #ifdef CONFIG_DEBUG_INTERPRETER
609 printk("defining constant %s\n\n", tib);
610 #endif
611 buildconstant(tib, POP());
612 reveal();
613 continue;
616 if (!strcasecmp(tib, "value")) {
617 parse_word(f, tib);
618 #ifdef CONFIG_DEBUG_INTERPRETER
619 printk("defining value %s\n\n", tib);
620 #endif
621 buildconstant(tib, POP());
622 reveal();
623 continue;
626 if (!strcasecmp(tib, "defer")) {
627 parse_word(f, tib);
628 #ifdef CONFIG_DEBUG_INTERPRETER
629 printk("defining defer word %s\n\n", tib);
630 #endif
631 builddefer(tib);
632 reveal();
633 continue;
636 if (!strcasecmp(tib, "include")) {
637 parse_word(f, tib);
638 #ifdef CONFIG_DEBUG_INTERPRETER
639 printk("including file %s\n\n", tib);
640 #endif
641 interpret_source(tib);
642 continue;
645 if (!strcmp(tib, "[']")) {
646 xt_t xt;
647 parse_word(f, tib);
648 xt = findword(tib);
649 if (*state == 0) {
650 #ifdef CONFIG_DEBUG_INTERPRETER
651 printk
652 ("writing address of %s to stack\n\n",
653 tib);
654 #endif
655 PUSH_xt(xt);
656 } else {
657 #ifdef CONFIG_DEBUG_INTERPRETER
658 printk("writing lit, addr(%s) to dict\n\n",
659 tib);
660 #endif
661 writecell(LIT); /* lit */
662 writecell((cell)xt);
664 continue;
665 /* we have no error detection here */
668 if (!strcasecmp(tib, "s\"")) {
669 int cnt;
670 cell loco;
672 cnt = parse(f, tib, '"');
673 #ifdef CONFIG_DEBUG_INTERPRETER
674 printk("compiling string %s\n", tib);
675 #endif
676 loco = dicthead + (6 * sizeof(cell));
677 writecell(LIT);
678 writecell(pointer2cell(dict) + loco);
679 writecell(LIT);
680 writecell((ucell)cnt);
681 writecell(DOBRANCH);
682 loco = cnt + sizeof(cell) - 1;
683 loco &= ~(sizeof(cell) - 1);
684 writecell(loco);
685 memcpy(dict + dicthead, tib, cnt);
686 dicthead += cnt;
687 paddict(sizeof(cell));
688 continue;
691 /* look if tib is in dictionary. */
692 /* should the dictionary be searched before the builtins ? */
693 res = findword(tib);
694 if (res) {
695 u8 flags = read_byte((u8*)cell2pointer(res) -
696 sizeof(cell) - 1);
697 #ifdef CONFIG_DEBUG_INTERPRETER
698 printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res);
699 #endif
700 if (!(*state) || (flags & 3)) {
701 #ifdef CONFIG_DEBUG_INTERPRETER
702 printk("executing %s, %" FMT_CELL_d
703 " (flags: %s %s)\n",
704 tib, res,
705 (flags & 1) ? "immediate" : "",
706 (flags & 2) ? "compile-only" : "");
707 #endif
708 PC = (ucell)res;
709 enterforth(res);
710 } else {
711 #ifdef CONFIG_DEBUG_INTERPRETER
712 printk("writing %s to dict\n\n", tib);
713 #endif
714 writecell((cell)res);
716 continue;
719 /* if not look if it's a number */
720 if (tib[0] == '-')
721 num = strtoll(tib, &test, read_ucell(base));
722 else
723 num = strtoull(tib, &test, read_ucell(base));
726 if (*test != 0) {
727 /* what is it?? */
728 printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib);
729 errors++;
730 #ifdef CONFIG_DEBUG_INTERPRETER
731 continue;
732 #else
733 return -1;
734 #endif
737 if (*state == 0) {
738 #ifdef CONFIG_DEBUG_INTERPRETER
739 printk("pushed %" FMT_CELL_x " to stack\n\n", num);
740 #endif
741 PUSH(num);
742 } else {
743 #ifdef CONFIG_DEBUG_INTERPRETER
744 printk("writing lit, %" FMT_CELL_x " to dict\n\n", num);
745 #endif
746 writecell(LIT); /* lit */
747 writecell(num);
751 fclose(f);
752 cursrc--;
754 return 0;
757 static int build_dictionary(void)
759 ucell lfa = 0;
760 unsigned int i;
762 /* we need a temporary place for latest outside the dictionary */
763 latest = &lfa;
765 /* starting a new dictionary: clear dicthead */
766 dicthead = 0;
768 #ifdef CONFIG_DEBUG_DICTIONARY
769 printk("building dictionary, %d primitives.\nbuilt words:",
770 sizeof(wordnames) / sizeof(void *));
771 #endif
773 for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) {
774 if (strlen(wordnames[i]) != 0) {
775 fcreate((char *) wordnames[i], i);
776 #ifdef CONFIG_DEBUG_DICTIONARY
777 printk(" %s", wordnames[i]);
778 #endif
781 #ifdef CONFIG_DEBUG_DICTIONARY
782 printk(".\n");
783 #endif
785 /* get last/latest and state */
786 state = buildvariable("state", 0);
787 last = buildvariable("forth-last", 0);
788 latest = buildvariable("latest", 0);
790 *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
792 base=buildvariable("base", 10);
794 buildconstant("/c", sizeof(u8));
795 buildconstant("/w", sizeof(u16));
796 buildconstant("/l", sizeof(u32));
797 buildconstant("/n", sizeof(ucell));
798 buildconstant("/x", sizeof(u64));
800 reveal();
801 if (verbose) {
802 printk("Dictionary initialization finished.\n");
804 return 0;
808 * functions used by primitives
811 int availchar(void)
813 int tmp;
814 if( cursrc < 1 ) {
815 interruptforth |= FORTH_INTSTAT_STOP;
816 /* return -1 in order to exit the loop in key() */
817 return -1;
820 tmp = getc( srcfiles[cursrc-1] );
821 if (tmp != EOF) {
822 ungetc(tmp, srcfiles[cursrc-1]);
823 return -1;
826 fclose(srcfiles[--cursrc]);
828 return availchar();
831 int get_inputbyte( void )
833 int tmp;
835 if( cursrc < 1 ) {
836 interruptforth |= FORTH_INTSTAT_STOP;
837 return 0;
840 tmp = getc( srcfiles[cursrc-1] );
842 /* Update current line number */
843 if (tmp == '\n') {
844 srclines[cursrc - 1]++;
847 if (tmp != EOF) {
848 return tmp;
851 fclose(srcfiles[--cursrc]);
853 return get_inputbyte();
856 void put_outputbyte( int c )
858 if (console)
859 fputc(c, console);
863 * segmentation fault handler. linux specific?
866 static void
867 segv_handler(int signo __attribute__ ((unused)),
868 siginfo_t * si, void *context __attribute__ ((unused)))
870 static int count = 0;
871 ucell addr = 0xdeadbeef;
873 if (count) {
874 printk("Died while dumping forth dictionary core.\n");
875 goto out;
878 count++;
880 if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
881 addr = read_cell(cell2pointer(PC));
883 printk("panic: segmentation violation at %p\n", (char *)si->si_addr);
884 printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n",
885 dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict));
886 printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n",
887 dstackcnt, rstackcnt, addr);
889 printdstack();
890 printrstack();
892 printk("Writing dictionary core file\n");
893 write_dictionary("forth.dict.core");
895 out:
896 exit(1);
900 * allocate memory and prepare engine for memory management.
903 static void init_memory(void)
905 memset(memory, 0, MEMORY_SIZE);
907 /* we push start and end of memory to the stack
908 * so that it can be used by the forth word QUIT
909 * to initialize the memory allocator.
910 * Add a cell to the start address so we don't end
911 * up with a start address of zero during bootstrap
914 PUSH(pointer2cell(memory)+sizeof(cell));
915 PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
919 void
920 include_file( const char *name )
922 FILE *file;
924 if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
925 printk("\npanic: Maximum include depth reached!\n");
926 exit(1);
929 file = fopen_include( name );
930 if( !file ) {
931 printk("\npanic: Failed opening file '%s'\n", name );
932 exit(1);
937 void
938 encode_file( const char *name )
940 FILE *file = fopen_include(name);
941 int size;
943 if( !file ) {
944 printk("\npanic: Can't open '%s'\n", name );
945 exit(1);
947 fseek( file, 0, SEEK_END );
948 size = ftell( file );
949 fseek( file, 0, SEEK_SET );
951 if (verbose) {
952 printk("\nEncoding %s [%d bytes]\n", name, size );
954 fread( dict + dicthead, size, 1, file );
955 PUSH( pointer2cell(dict + dicthead) );
956 PUSH( size );
957 dicthead += size;
961 static void run_dictionary(char *basedict, char *confile)
963 if(!basedict)
964 return;
966 read_dictionary(basedict);
967 PC = (ucell)findword("initialize");
969 if (!PC) {
970 if (verbose) {
971 printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
973 return;
976 if(!srcfiles[0]) {
977 cursrc = 1;
978 srcfiles[cursrc-1] = stdin;
981 dstackcnt=0;
982 rstackcnt=0;
984 init_memory();
985 if (verbose)
986 printk("Jumping to dictionary %s...\n", basedict);
988 /* If a console file has been specified, open it */
989 if (confile)
990 console = fopen(confile, "w");
992 srcbasedict = basedict;
994 enterforth((xt_t)PC);
996 /* Close the console file */
997 if (console)
998 fclose(console);
1001 static void new_dictionary(const char *source)
1003 build_dictionary();
1005 interpret_source((char *)source);
1007 if (verbose || errors > 0) {
1008 printk("interpretion finished. %d errors occured.\n",
1009 errors);
1014 * main loop
1017 #define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
1018 "This software comes with absolutely no warranty. "\
1019 "All rights reserved.\n\n"
1021 #ifdef __GLIBC__
1022 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1023 " -h|--help show this help\n" \
1024 " -V|--version print version and exit\n" \
1025 " -v|--verbose print debugging information\n" \
1026 " -I|--include dir add dir to include path\n" \
1027 " -d|--source-dictionary bootstrap.dict\n" \
1028 " use this dictionary as base\n" \
1029 " -D|--target-dictionary output.dict\n" \
1030 " write to output.dict\n" \
1031 " -c|--console output.log\n" \
1032 " write kernel console output to log file\n" \
1033 " -s|--segfault install segfault handler\n" \
1034 " -M|--dependency-dump file\n" \
1035 " dump dependencies in Makefile format\n\n"
1036 #else
1037 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1038 " -h show this help\n" \
1039 " -V print version and exit\n" \
1040 " -v print debugging information\n" \
1041 " -I add dir to include path\n" \
1042 " -d bootstrap.dict\n" \
1043 " use this dictionary as base\n" \
1044 " -D output.dict\n" \
1045 " write to output.dict\n" \
1046 " -c output.log\n" \
1047 " write kernel console output to log file\n" \
1048 " -s install segfault handler\n\n"
1049 " -M file dump dependencies in Makefile format\n\n"
1050 #endif
1052 int main(int argc, char *argv[])
1054 struct sigaction sa;
1056 unsigned char *ressources=NULL; /* All memory used by us */
1057 char *dictname = NULL;
1058 char *basedict = NULL;
1059 char *consolefile = NULL;
1060 char *depfilename = NULL;
1062 unsigned char *bootstrapdict[2];
1063 int c, cnt;
1065 const char *optstring = "VvhsI:d:D:c:M:?";
1067 while (1) {
1068 #ifdef __GLIBC__
1069 int option_index = 0;
1070 static struct option long_options[] = {
1071 {"version", 0, NULL, 'V'},
1072 {"verbose", 0, NULL, 'v'},
1073 {"help", 0, NULL, 'h'},
1074 {"segfault", 0, NULL, 's'},
1075 {"include", 1, NULL, 'I'},
1076 {"source-dictionary", 1, NULL, 'd'},
1077 {"target-dictionary", 1, NULL, 'D'},
1078 {"console", 1, NULL, 'c'},
1079 {"dependency-dump", 1, NULL, 'M'},
1083 * option handling
1086 c = getopt_long(argc, argv, optstring, long_options,
1087 &option_index);
1088 #else
1089 c = getopt(argc, argv, optstring);
1090 #endif
1091 if (c == -1)
1092 break;
1094 switch (c) {
1095 case 'V':
1096 printk("Version " OPENBIOS_VERSION_STR "\n");
1097 return 0;
1098 case 'h':
1099 case '?':
1100 printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
1101 argv[0]);
1102 return 0;
1103 case 'v':
1104 verbose = 1;
1105 break;
1106 case 's':
1107 segfault = 1;
1108 break;
1109 case 'I':
1110 #ifdef CONFIG_DEBUG_INTERPRETER
1111 printk("adding '%s' to include path\n", optarg);
1112 #endif
1113 add_includepath(optarg);
1114 break;
1115 case 'd':
1116 if (!basedict) {
1117 basedict = optarg;
1119 break;
1120 case 'D':
1121 if(!dictname) {
1122 dictname = optarg;
1124 break;
1125 case 'c':
1126 if (!consolefile) {
1127 consolefile = optarg;
1129 break;
1130 case 'M':
1131 if (!depfilename) {
1132 depfilename = optarg;
1134 break;
1135 default:
1136 return 1;
1140 if (verbose) {
1141 printk(BANNER);
1142 printk("Using source dictionary '%s'\n", basedict);
1143 printk("Dumping final dictionary to '%s'\n", dictname);
1144 printk("Dumping dependencies to '%s'\n", depfilename);
1147 if (argc < optind + 1) {
1148 printk(USAGE, argv[0]);
1149 return 1;
1152 if (depfilename) {
1153 depfile = fopen(depfilename, "w");
1154 if (!depfile) {
1155 printk("panic: can't write to dependency file '%s'.\n",
1156 depfilename);
1157 exit(1);
1159 fprintf(depfile, "%s:", dictname);
1163 * Get all required resources
1167 ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
1168 if (!ressources) {
1169 printk("panic: not enough memory on host system.\n");
1170 return 1;
1173 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
1174 base_address=(unsigned long)ressources;
1175 #endif
1177 memory = (ucell *)ressources;
1179 bootstrapdict[0] = ressources + MEMORY_SIZE;
1180 bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
1181 trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
1183 #ifdef CONFIG_DEBUG_INTERPRETER
1184 printf("memory: %p\n",memory);
1185 printf("dict1: %p\n",bootstrapdict[0]);
1186 printf("dict2: %p\n",bootstrapdict[1]);
1187 printf("trampoline: %p\n",trampoline);
1188 printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
1189 DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
1190 TRAMPOLINE_SIZE);
1191 #endif
1193 if (trampoline == NULL) {
1194 /* We're using side effects which is to some extent nasty */
1195 printf("WARNING: no trampoline!\n");
1196 } else {
1197 init_trampoline(trampoline);
1200 if (!segfault) {
1201 if (verbose)
1202 printk("Installing SIGSEGV handler...");
1204 sa.sa_sigaction = segv_handler;
1205 sigemptyset(&sa.sa_mask);
1206 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
1207 sigaction(SIGSEGV, &sa, NULL);
1209 if (verbose)
1210 printk("done.\n");
1214 * Now do the real work
1217 for (cnt=0; cnt<2; cnt++) {
1218 if (verbose) {
1219 printk("Compiling dictionary %d/%d\n", cnt+1, 2);
1221 dict=bootstrapdict[cnt];
1222 if(!basedict) {
1223 new_dictionary(argv[optind]);
1224 } else {
1225 for (c=argc-1; c>=optind; c--)
1226 include_file(argv[c]);
1228 run_dictionary(basedict, consolefile);
1230 if (depfile) {
1231 fprintf(depfile, "\n");
1232 fclose(depfile);
1233 depfile = NULL;
1235 if(errors)
1236 break;
1239 #ifndef CONFIG_DEBUG_INTERPRETER
1240 if (errors)
1241 printk("dictionary not dumped to file.\n");
1242 else
1243 #endif
1245 relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
1246 write_dictionary( dictname ? dictname : "bootstrap.dict");
1249 free(ressources);
1251 if (errors)
1252 return 1;
1253 else
1254 return 0;