Move the HFS filesystem handler into its own new package /packages/hfs-files.
[openbios.git] / kernel / bootstrap.c
blob90c93c1b164981ec6e3590c4370f3a80c2487b78
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 };
73 static ucell * relocation_address=NULL;
74 static int relocation_length=0;
76 /* the word names are used to generate the prim words in the
77 * dictionary. This is done by the C written interpreter.
79 static const char *wordnames[] = {
80 "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)",
81 "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop",
82 "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>",
83 "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*",
84 "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a",
85 "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@",
86 "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<",
87 "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute",
88 "here", "here!", "dobranch", "do?branch", "unaligned-w@",
89 "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@",
90 "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug",
91 "$include", "$encode-file", "(debug", "(debug-off)"
94 static void init_trampoline(void)
96 if (!trampoline) {
97 /* We're using side effects which is to some extent nasty */
98 printf("WARNING: no trampoline!\n");
99 return;
102 trampoline[0]=DOCOL;
103 trampoline[1]=0;
104 trampoline[2]=target_ucell(pointer2cell(trampoline)+3*sizeof(ucell));
105 trampoline[3]=0;
109 * dictionary related functions.
112 static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length)
114 ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two;
115 ucell *reloc_table;
116 int pos, bit;
117 int l=(length+(sizeof(cell)-1))/sizeof(ucell), i;
119 /* prepare relocation table */
120 relocation_length=(length+BITS-1)/BITS;
121 reloc_table = malloc(relocation_length*sizeof(cell));
122 memset(reloc_table,0,relocation_length*sizeof(cell));
124 for (i=0; i<l; i++) {
126 pos=i/BITS;
127 bit=i&~(-BITS);
129 if(d1[i]==d2[i]) {
130 reloc_table[pos] &= target_ucell(~((ucell)1ULL << bit));
132 // This check might bring false positives in data.
133 //if(d1[i] >= pointer2cell(dict_one) &&
134 // d1[i] <= pointer2cell(dict_one+length))
135 // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]);
136 } else {
137 /* This is a pointer, it needs relocation, d2==dict */
138 reloc_table[pos] |= target_ucell((ucell)1ULL << bit);
139 d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2));
143 #ifdef CONFIG_DEBUG_DICTIONARY
144 printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict);
145 for (i=0; i< relocation_length ; i++)
146 printk("reloc %d %lx\n",i+1, reloc_table[i]);
147 #endif
148 relocation_address=reloc_table;
151 static void write_dictionary(const char *filename)
153 FILE *f;
154 unsigned char *write_data, *walk_data;
155 int write_len;
156 dictionary_header_t *header;
157 u32 checksum=0;
160 * get memory for dictionary
163 write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell);
164 write_data = malloc(write_len);
165 if(!write_data) {
166 printk("panic: can't allocate memory for output dictionary (%d"
167 " bytes\n", write_len);
168 exit(1);
170 memset(write_data, 0, write_len);
173 * prepare dictionary header
176 header = (dictionary_header_t *)write_data;
177 *header = (dictionary_header_t){
178 .signature = DICTID,
179 .version = 2,
180 .cellsize = sizeof(ucell),
181 #ifdef CONFIG_BIG_ENDIAN
182 .endianess = -1,
183 #else
184 .endianess = 0,
185 #endif
186 .checksum = 0,
187 .compression = 0,
188 .relocation = -1,
189 .length = target_ulong((uint32_t)dicthead),
190 .last = target_ucell((ucell)((unsigned long)last
191 - (unsigned long)dict)),
195 * prepare dictionary data
198 walk_data=write_data+sizeof(dictionary_header_t);
199 memcpy (walk_data, dict, dicthead);
202 * prepare relocation data.
203 * relocation_address is zero when writing a dictionary core.
206 if (relocation_address) {
207 #ifdef CONFIG_DEBUG_DICTIONARY
208 printk("writing %d reloc cells \n",relocation_length);
209 #endif
210 walk_data += dicthead;
211 memcpy(walk_data, relocation_address,
212 relocation_length*sizeof(cell));
213 /* free relocation information */
214 free(relocation_address);
215 relocation_address=NULL;
216 } else {
217 header->relocation=0;
221 * Calculate Checksum
224 walk_data=write_data;
225 while (walk_data<write_data+write_len) {
226 checksum+=read_long(walk_data);
227 walk_data+=sizeof(u32);
229 checksum=(u32)-checksum;
231 header->checksum=target_long(checksum);
233 if (verbose) {
234 dump_header(header);
237 f = fopen(filename, "w");
238 if (!f) {
239 printk("panic: can't write to dictionary '%s'.\n", filename);
240 exit(1);
243 fwrite(write_data, write_len, 1, f);
245 free(write_data);
246 fclose(f);
248 #ifdef CONFIG_DEBUG_DICTIONARY
249 printk("wrote dictionary to file %s.\n", filename);
250 #endif
253 static ucell read_dictionary(char *fil)
255 int ilen;
256 ucell ret;
257 char *mem;
258 FILE *f;
259 struct stat finfo;
261 if (stat(fil, &finfo))
262 return 0;
264 ilen = finfo.st_size;
266 if ((mem = malloc(ilen)) == NULL) {
267 printk("panic: not enough memory.\n");
268 exit(1);
271 f = fopen(fil, "r");
272 if (!f) {
273 printk("panic: can't open dictionary.\n");
274 exit(1);
277 if (fread(mem, ilen, 1, f) != 1) {
278 printk("panic: can't read dictionary.\n");
279 fclose(f);
280 exit(1);
282 fclose(f);
284 ret = load_dictionary(mem, ilen);
286 free(mem);
287 return ret;
292 * C Parser related functions
296 * skipws skips all whitespaces (space, tab, newline) from the input file
299 static void skipws(FILE * f)
301 int c;
302 while (!feof(f)) {
303 c = getc(f);
305 if (c == ' ' || c == '\t')
306 continue;
308 if (c == '\n') {
309 srclines[cursrc - 1]++;
310 continue;
313 ungetc(c, f);
314 break;
319 * parse gets the next word from the input stream, delimited by
320 * delim. If delim is 0, any word delimiter will end the stream
321 * word delimiters are space, tab and newline. The resulting word
322 * will be put zero delimited to the char array line.
325 static int parse(FILE * f, char *line, char delim)
327 int cnt = 0, c = 0;
329 while (!feof(f)) {
330 c = getc(f);
332 if (delim && c == delim)
333 break;
335 if ((!delim) && (c == ' ' || c == '\t' || c == '\n'))
336 break;
338 line[cnt++] = c;
341 /* Update current line number */
342 if (c == '\n') {
343 srclines[cursrc - 1]++;
346 line[cnt] = 0;
348 return cnt;
352 * parse_word is a small helper that skips whitespaces before a word.
353 * it's behaviour is similar to the forth version parse-word.
356 static void parse_word(FILE * f, char *line)
358 skipws(f);
359 parse(f, line, 0);
363 static void writestring(const char *str)
365 unsigned int i;
366 for (i = 0; i < strlen(str); i++) {
367 dict[dicthead + i] = str[i];
369 dicthead += i + 1;
370 dict[dicthead - 1] = (char) strlen(str) + 128;
373 #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;}
374 #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);}
377 * reveal a word, ie. make it visible.
380 static void reveal(void)
382 *last = *latest;
386 * dictionary padding
389 static void paddict(ucell align)
391 while (dicthead % align != 0)
392 writebyte(0);
396 * generic forth word creator function.
399 static void fcreate(const char *word, ucell cfaval)
401 if (strlen(word) == 0) {
402 printk("WARNING: tried to create unnamed word.\n");
403 return;
406 writestring(word);
407 /* get us at least 1 byte for flags */
408 writebyte(0);
409 paddict(sizeof(cell));
410 /* set flags high bit. */
411 dict[dicthead - 1] = 128;
412 /* lfa and cfa */
413 writecell(read_ucell(latest));
414 *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell));
415 writecell(cfaval);
419 static ucell *buildvariable(const char *name, cell defval)
421 fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */
422 writecell(defval);
423 return (ucell *) (dict + dicthead - sizeof(cell));
426 static void buildconstant(const char *name, cell defval)
428 fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */
429 writecell(defval);
432 static void builddefer(const char *name)
434 fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */
435 writecell((ucell)0);
436 writecell((ucell)findword("(semis)"));
440 * Include file handling
443 static void add_includepath(char *path)
445 include *incl = &includes;
446 include *newpath;
448 while (incl->next)
449 incl = incl->next;
451 newpath = malloc(sizeof(include));
452 if (!newpath) {
453 printk("panic: not enough memory for include path.\n");
454 exit(1);
457 incl->next = newpath;
458 newpath->path = path;
459 newpath->next = NULL;
463 static FILE *fopen_include(const char *fil)
465 char fullpath[MAX_PATH_LEN];
466 FILE *ret;
467 include *incl = &includes;
469 while (incl) {
470 snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil);
472 ret = fopen(fullpath, "r");
473 if (ret != NULL) {
475 #ifdef CONFIG_DEBUG_INTERPRETER
476 printk("Including '%s'\n", name );
477 #endif
478 srcfilenames [ cursrc ] = malloc(strlen(fil) + 1);
479 strcpy(srcfilenames[ cursrc ], fil);
480 srclines [ cursrc ] = 1;
481 srcfiles [ cursrc++ ] = ret;
483 return ret;
486 incl = incl->next;
488 return NULL;
493 * Forth exception handler
496 void exception(cell no)
498 printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]);
500 /* See also forth/bootstrap/interpreter.fs */
501 switch (no) {
502 case -1:
503 case -2:
504 printk("Aborted.\n");
505 break;
506 case -3:
507 printk("Stack Overflow.\n");
508 break;
509 case -4:
510 printk("Stack Underflow.\n");
511 break;
512 case -5:
513 printk("Return Stack Overflow.\n");
514 break;
515 case -6:
516 printk("Return Stack Underflow.\n");
517 break;
518 case -19:
519 printk("undefined word.\n");
520 break;
521 case -21:
522 printk("out of memory.\n");
523 break;
524 case -33:
525 printk("undefined method.\n");
526 break;
527 case -34:
528 printk("no such device.\n");
529 break;
530 default:
531 printk("error %" FMT_CELL_d " occured.\n", no);
533 exit(1);
538 * This is the C version of the forth interpreter
541 static int interpret_source(char *fil)
543 FILE *f;
544 char tib[160];
545 cell num;
546 char *test;
548 const ucell SEMIS = (ucell)findword("(semis)");
549 const ucell LIT = (ucell)findword("(lit)");
550 const ucell DOBRANCH = (ucell)findword("dobranch");
552 if ((f = fopen_include(fil)) == NULL) {
553 printk("error while loading source file '%s'\n", fil);
554 errors++;
555 exit(1);
558 /* FIXME: We should read this file at
559 * once. No need to get it char by char
562 while (!feof(f)) {
563 xt_t res;
564 parse_word(f, tib);
566 /* if there is actually no word, we continue right away */
567 if (strlen(tib) == 0) {
568 continue;
571 /* Checking for builtin words that are needed to
572 * bootstrap the forth base dictionary.
575 if (!strcmp(tib, "(")) {
576 parse(f, tib, ')');
577 continue;
580 if (!strcmp(tib, "\\")) {
581 parse(f, tib, '\n');
582 continue;
585 if (!strcmp(tib, ":")) {
586 parse_word(f, tib);
588 #ifdef CONFIG_DEBUG_INTERPRETER
589 printk("create colon word %s\n\n", tib);
590 #endif
591 fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */
592 *state = (ucell) (-1);
593 continue;
596 if (!strcmp(tib, ";")) {
597 #ifdef CONFIG_DEBUG_INTERPRETER
598 printk("finish colon definition\n\n");
599 #endif
600 writecell((cell)SEMIS);
601 *state = (ucell) 0;
602 reveal();
603 continue;
606 if (!strcasecmp(tib, "variable")) {
607 parse_word(f, tib);
608 #ifdef CONFIG_DEBUG_INTERPRETER
609 printk("defining variable %s\n\n", tib);
610 #endif
611 buildvariable(tib, 0);
612 reveal();
613 continue;
616 if (!strcasecmp(tib, "constant")) {
617 parse_word(f, tib);
618 #ifdef CONFIG_DEBUG_INTERPRETER
619 printk("defining constant %s\n\n", tib);
620 #endif
621 buildconstant(tib, POP());
622 reveal();
623 continue;
626 if (!strcasecmp(tib, "value")) {
627 parse_word(f, tib);
628 #ifdef CONFIG_DEBUG_INTERPRETER
629 printk("defining value %s\n\n", tib);
630 #endif
631 buildconstant(tib, POP());
632 reveal();
633 continue;
636 if (!strcasecmp(tib, "defer")) {
637 parse_word(f, tib);
638 #ifdef CONFIG_DEBUG_INTERPRETER
639 printk("defining defer word %s\n\n", tib);
640 #endif
641 builddefer(tib);
642 reveal();
643 continue;
646 if (!strcasecmp(tib, "include")) {
647 parse_word(f, tib);
648 #ifdef CONFIG_DEBUG_INTERPRETER
649 printk("including file %s\n\n", tib);
650 #endif
651 interpret_source(tib);
652 continue;
655 if (!strcmp(tib, "[']")) {
656 xt_t xt;
657 parse_word(f, tib);
658 xt = findword(tib);
659 if (*state == 0) {
660 #ifdef CONFIG_DEBUG_INTERPRETER
661 printk
662 ("writing address of %s to stack\n\n",
663 tib);
664 #endif
665 PUSH_xt(xt);
666 } else {
667 #ifdef CONFIG_DEBUG_INTERPRETER
668 printk("writing lit, addr(%s) to dict\n\n",
669 tib);
670 #endif
671 writecell(LIT); /* lit */
672 writecell((cell)xt);
674 continue;
675 /* we have no error detection here */
678 if (!strcasecmp(tib, "s\"")) {
679 int cnt;
680 cell loco;
682 cnt = parse(f, tib, '"');
683 #ifdef CONFIG_DEBUG_INTERPRETER
684 printk("compiling string %s\n", tib);
685 #endif
686 loco = dicthead + (6 * sizeof(cell));
687 writecell(LIT);
688 writecell(pointer2cell(dict) + loco);
689 writecell(LIT);
690 writecell((ucell)cnt);
691 writecell(DOBRANCH);
692 loco = cnt + sizeof(cell) - 1;
693 loco &= ~(sizeof(cell) - 1);
694 writecell(loco);
695 memcpy(dict + dicthead, tib, cnt);
696 dicthead += cnt;
697 paddict(sizeof(cell));
698 continue;
701 /* look if tib is in dictionary. */
702 /* should the dictionary be searched before the builtins ? */
703 res = findword(tib);
704 if (res) {
705 u8 flags = read_byte((u8*)cell2pointer(res) -
706 sizeof(cell) - 1);
707 #ifdef CONFIG_DEBUG_INTERPRETER
708 printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res);
709 #endif
710 if (!(*state) || (flags & 3)) {
711 #ifdef CONFIG_DEBUG_INTERPRETER
712 printk("executing %s, %" FMT_CELL_d
713 " (flags: %s %s)\n",
714 tib, res,
715 (flags & 1) ? "immediate" : "",
716 (flags & 2) ? "compile-only" : "");
717 #endif
718 PC = (ucell)res;
719 enterforth(res);
720 } else {
721 #ifdef CONFIG_DEBUG_INTERPRETER
722 printk("writing %s to dict\n\n", tib);
723 #endif
724 writecell((cell)res);
726 continue;
729 /* if not look if it's a number */
730 if (tib[0] == '-')
731 num = strtoll(tib, &test, read_ucell(base));
732 else
733 num = strtoull(tib, &test, read_ucell(base));
736 if (*test != 0) {
737 /* what is it?? */
738 printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib);
739 errors++;
740 #ifdef CONFIG_DEBUG_INTERPRETER
741 continue;
742 #else
743 return -1;
744 #endif
747 if (*state == 0) {
748 #ifdef CONFIG_DEBUG_INTERPRETER
749 printk("pushed %" FMT_CELL_x " to stack\n\n", num);
750 #endif
751 PUSH(num);
752 } else {
753 #ifdef CONFIG_DEBUG_INTERPRETER
754 printk("writing lit, %" FMT_CELL_x " to dict\n\n", num);
755 #endif
756 writecell(LIT); /* lit */
757 writecell(num);
761 fclose(f);
762 cursrc--;
764 return 0;
767 static int build_dictionary(void)
769 ucell lfa = 0;
770 unsigned int i;
772 /* we need a temporary place for latest outside the dictionary */
773 latest = &lfa;
775 /* starting a new dictionary: clear dicthead */
776 dicthead = 0;
778 #ifdef CONFIG_DEBUG_DICTIONARY
779 printk("building dictionary, %d primitives.\nbuilt words:",
780 sizeof(wordnames) / sizeof(void *));
781 #endif
783 for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) {
784 if (strlen(wordnames[i]) != 0) {
785 fcreate((char *) wordnames[i], i);
786 #ifdef CONFIG_DEBUG_DICTIONARY
787 printk(" %s", wordnames[i]);
788 #endif
791 #ifdef CONFIG_DEBUG_DICTIONARY
792 printk(".\n");
793 #endif
795 /* get last/latest and state */
796 state = buildvariable("state", 0);
797 last = buildvariable("forth-last", 0);
798 latest = buildvariable("latest", 0);
800 *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell));
802 base=buildvariable("base", 10);
804 buildconstant("/c", sizeof(u8));
805 buildconstant("/w", sizeof(u16));
806 buildconstant("/l", sizeof(u32));
807 buildconstant("/n", sizeof(ucell));
808 buildconstant("/x", sizeof(u64));
810 reveal();
811 if (verbose) {
812 printk("Dictionary initialization finished.\n");
814 return 0;
818 * functions used by primitives
821 int availchar(void)
823 int tmp;
824 if( cursrc < 1 ) {
825 interruptforth |= FORTH_INTSTAT_STOP;
826 /* return -1 in order to exit the loop in key() */
827 return -1;
830 tmp = getc( srcfiles[cursrc-1] );
831 if (tmp != EOF) {
832 ungetc(tmp, srcfiles[cursrc-1]);
833 return -1;
836 fclose(srcfiles[--cursrc]);
838 return availchar();
841 int get_inputbyte( void )
843 int tmp;
845 if( cursrc < 1 ) {
846 interruptforth |= FORTH_INTSTAT_STOP;
847 return 0;
850 tmp = getc( srcfiles[cursrc-1] );
852 /* Update current line number */
853 if (tmp == '\n') {
854 srclines[cursrc - 1]++;
857 if (tmp != EOF) {
858 return tmp;
861 fclose(srcfiles[--cursrc]);
863 return get_inputbyte();
866 void put_outputbyte( int c )
868 if (console)
869 fputc(c, console);
873 * segmentation fault handler. linux specific?
876 static void
877 segv_handler(int signo __attribute__ ((unused)),
878 siginfo_t * si, void *context __attribute__ ((unused)))
880 static int count = 0;
881 ucell addr = 0xdeadbeef;
883 if (count) {
884 printk("Died while dumping forth dictionary core.\n");
885 goto out;
888 count++;
890 if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead)
891 addr = read_cell(cell2pointer(PC));
893 printk("panic: segmentation violation at %p\n", (char *)si->si_addr);
894 printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n",
895 dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict));
896 printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n",
897 dstackcnt, rstackcnt, addr);
899 printdstack();
900 printrstack();
902 printk("Writing dictionary core file\n");
903 write_dictionary("forth.dict.core");
905 out:
906 exit(1);
910 * allocate memory and prepare engine for memory management.
913 static void init_memory(void)
915 memset(memory, 0, MEMORY_SIZE);
917 /* we push start and end of memory to the stack
918 * so that it can be used by the forth word QUIT
919 * to initialize the memory allocator.
920 * Add a cell to the start address so we don't end
921 * up with a start address of zero during bootstrap
924 PUSH(pointer2cell(memory)+sizeof(cell));
925 PUSH(pointer2cell(memory) + MEMORY_SIZE-1);
929 void
930 include_file( const char *name )
932 FILE *file;
934 if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) {
935 printk("\npanic: Maximum include depth reached!\n");
936 exit(1);
939 file = fopen_include( name );
940 if( !file ) {
941 printk("\npanic: Failed opening file '%s'\n", name );
942 exit(1);
947 void
948 encode_file( const char *name )
950 FILE *file = fopen_include(name);
951 int size;
953 if( !file ) {
954 printk("\npanic: Can't open '%s'\n", name );
955 exit(1);
957 fseek( file, 0, SEEK_END );
958 size = ftell( file );
959 fseek( file, 0, SEEK_SET );
961 if (verbose) {
962 printk("\nEncoding %s [%d bytes]\n", name, size );
964 fread( dict + dicthead, size, 1, file );
965 PUSH( pointer2cell(dict + dicthead) );
966 PUSH( size );
967 dicthead += size;
971 static void run_dictionary(char *basedict, char *confile)
973 if(!basedict)
974 return;
976 read_dictionary(basedict);
977 PC = (ucell)findword("initialize");
979 if (!PC) {
980 if (verbose) {
981 printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict);
983 return;
986 if(!srcfiles[0]) {
987 cursrc = 1;
988 srcfiles[cursrc-1] = stdin;
991 dstackcnt=0;
992 rstackcnt=0;
994 init_memory();
995 if (verbose)
996 printk("Jumping to dictionary %s...\n", basedict);
998 /* If a console file has been specified, open it */
999 if (confile)
1000 console = fopen(confile, "w");
1002 srcbasedict = basedict;
1004 enterforth((xt_t)PC);
1006 /* Close the console file */
1007 if (console)
1008 fclose(console);
1011 static void new_dictionary(const char *source)
1013 build_dictionary();
1015 interpret_source((char *)source);
1017 if (verbose || errors > 0) {
1018 printk("interpretion finished. %d errors occured.\n",
1019 errors);
1024 * main loop
1027 #define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\
1028 "This software comes with absolutely no warranty. "\
1029 "All rights reserved.\n\n"
1031 #ifdef __GLIBC__
1032 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1033 " -h|--help show this help\n" \
1034 " -V|--version print version and exit\n" \
1035 " -v|--verbose print debugging information\n" \
1036 " -I|--include dir add dir to include path\n" \
1037 " -d|--source-dictionary bootstrap.dict\n" \
1038 " use this dictionary as base\n" \
1039 " -D|--target-dictionary output.dict\n" \
1040 " write to output.dict\n" \
1041 " -c|--console output.log\n" \
1042 " write kernel console output to log file\n" \
1043 " -s|--segfault install segfault handler\n\n"
1044 #else
1045 #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \
1046 " -h show this help\n" \
1047 " -V print version and exit\n" \
1048 " -v print debugging information\n" \
1049 " -I add dir to include path\n" \
1050 " -d bootstrap.dict\n" \
1051 " use this dictionary as base\n" \
1052 " -D output.dict\n" \
1053 " write to output.dict\n" \
1054 " -c output.log\n" \
1055 " write kernel console output to log file\n" \
1056 " -s install segfault handler\n\n"
1058 #endif
1060 int main(int argc, char *argv[])
1062 struct sigaction sa;
1064 unsigned char *ressources=NULL; /* All memory used by us */
1065 char *dictname = NULL;
1066 char *basedict = NULL;
1067 char *consolefile = NULL;
1069 unsigned char *bootstrapdict[2];
1070 int c, cnt;
1072 const char *optstring = "VvhsI:d:D:c:?";
1074 while (1) {
1075 #ifdef __GLIBC__
1076 int option_index = 0;
1077 static struct option long_options[] = {
1078 {"version", 0, NULL, 'V'},
1079 {"verbose", 0, NULL, 'v'},
1080 {"help", 0, NULL, 'h'},
1081 {"segfault", 0, NULL, 's'},
1082 {"include", 1, NULL, 'I'},
1083 {"source-dictionary", 1, NULL, 'd'},
1084 {"target-dictionary", 1, NULL, 'D'},
1085 {"console", 1, NULL, 'c'},
1089 * option handling
1092 c = getopt_long(argc, argv, optstring, long_options,
1093 &option_index);
1094 #else
1095 c = getopt(argc, argv, optstring);
1096 #endif
1097 if (c == -1)
1098 break;
1100 switch (c) {
1101 case 'V':
1102 printk("Version " OPENBIOS_VERSION_STR "\n");
1103 return 0;
1104 case 'h':
1105 case '?':
1106 printk("Version " OPENBIOS_VERSION_STR "\n" USAGE,
1107 argv[0]);
1108 return 0;
1109 case 'v':
1110 verbose = 1;
1111 break;
1112 case 's':
1113 segfault = 1;
1114 break;
1115 case 'I':
1116 #ifdef CONFIG_DEBUG_INTERPRETER
1117 printk("adding '%s' to include path\n", optarg);
1118 #endif
1119 add_includepath(optarg);
1120 break;
1121 case 'd':
1122 if (!basedict) {
1123 basedict = optarg;
1125 break;
1126 case 'D':
1127 if(!dictname) {
1128 dictname = optarg;
1130 break;
1131 case 'c':
1132 if (!consolefile) {
1133 consolefile = optarg;
1135 break;
1136 default:
1137 return 1;
1141 if (verbose) {
1142 printk(BANNER);
1143 printk("Using source dictionary '%s'\n", basedict);
1144 printk("Dumping final dictionary to '%s'\n", dictname);
1147 if (argc < optind + 1) {
1148 printk(USAGE, argv[0]);
1149 return 1;
1154 * Get all required resources
1158 ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE);
1159 if (!ressources) {
1160 printk("panic: not enough memory on host system.\n");
1161 return 1;
1164 #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH
1165 base_address=(unsigned long)ressources;
1166 #endif
1168 memory = (ucell *)ressources;
1170 bootstrapdict[0] = ressources + MEMORY_SIZE;
1171 bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE;
1172 trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE);
1174 #ifdef CONFIG_DEBUG_INTERPRETER
1175 printf("memory: %p\n",memory);
1176 printf("dict1: %p\n",bootstrapdict[0]);
1177 printf("dict2: %p\n",bootstrapdict[1]);
1178 printf("trampoline: %p\n",trampoline);
1179 printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 *
1180 DICTIONARY_SIZE) + TRAMPOLINE_SIZE,
1181 TRAMPOLINE_SIZE);
1182 #endif
1184 init_trampoline();
1186 if (!segfault) {
1187 if (verbose)
1188 printk("Installing SIGSEGV handler...");
1190 sa.sa_sigaction = segv_handler;
1191 sigemptyset(&sa.sa_mask);
1192 sa.sa_flags = SA_SIGINFO | SA_NODEFER;
1193 sigaction(SIGSEGV, &sa, NULL);
1195 if (verbose)
1196 printk("done.\n");
1200 * Now do the real work
1203 for (cnt=0; cnt<2; cnt++) {
1204 if (verbose) {
1205 printk("Compiling dictionary %d/%d\n", cnt+1, 2);
1207 dict=bootstrapdict[cnt];
1208 if(!basedict) {
1209 new_dictionary(argv[optind]);
1210 } else {
1211 for (c=argc-1; c>=optind; c--)
1212 include_file(argv[c]);
1214 run_dictionary(basedict, consolefile);
1216 if(errors)
1217 break;
1220 #ifndef CONFIG_DEBUG_INTERPRETER
1221 if (errors)
1222 printk("dictionary not dumped to file.\n");
1223 else
1224 #endif
1226 relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead);
1227 write_dictionary( dictname ? dictname : "bootstrap.dict");
1230 free(ressources);
1232 if (errors)
1233 return 1;
1234 else
1235 return 0;