/* tag: forth bootstrap environment * * Copyright (C) 2003-2006 Stefan Reinauer, Patrick Mauritz * * See the file "COPYING" for further information about * the copyright and warranty status of this work. */ #include "sysinclude.h" #include #include #include #include #include #include #include #include #ifdef __GLIBC__ #define _GNU_SOURCE #include #endif #include "config.h" #include "kernel/stack.h" #include "sysinclude.h" #include "kernel/kernel.h" #include "dict.h" #include "cross.h" #include "openbios-version.h" #define MAX_PATH_LEN 256 #define MEMORY_SIZE (1024*1024) /* 1M ram for hosted system */ #define DICTIONARY_SIZE (256*1024) /* 256k for the dictionary */ #define TRAMPOLINE_SIZE (4*sizeof(cell)) /* 4 cells for the trampoline */ /* state variables */ static ucell *latest, *state, *base; static ucell *memory; ucell *trampoline; /* local variables */ static int errors = 0; static int segfault = 0; static int verbose = 0; #define MAX_SRC_FILES 128 static FILE *srcfiles[MAX_SRC_FILES]; static char *srcfilenames[MAX_SRC_FILES]; static int srclines[MAX_SRC_FILES]; static unsigned int cursrc = 0; static char *srcbasedict; /* console variables */ static FILE *console; #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH unsigned long base_address; #endif /* include path handling */ typedef struct include_path include; struct include_path { const char *path; include *next; }; static include includes = { ".", NULL }; static FILE *depfile; static ucell * relocation_address=NULL; static int relocation_length=0; /* the word names are used to generate the prim words in the * dictionary. This is done by the C written interpreter. */ static const char *wordnames[] = { "(semis)", "", "(lit)", "", "", "", "", "(do)", "(?do)", "(loop)", "(+loop)", "", "", "", "dup", "2dup", "?dup", "over", "2over", "pick", "drop", "2drop", "nip", "roll", "rot", "-rot", "swap", "2swap", ">r", "r>", "r@", "depth", "depth!", "rdepth", "rdepth!", "+", "-", "*", "u*", "mu/mod", "abs", "negate", "max", "min", "lshift", "rshift", ">>a", "and", "or", "xor", "invert", "d+", "d-", "m*", "um*", "@", "c@", "w@", "l@", "!", "+!", "c!", "w!", "l!", "=", ">", "<", "u>", "u<", "sp@", "move", "fill", "(emit)", "(key?)", "(key)", "execute", "here", "here!", "dobranch", "do?branch", "unaligned-w@", "unaligned-w!", "unaligned-l@", "unaligned-l!", "ioc@", "iow@", "iol@", "ioc!", "iow!", "iol!", "i", "j", "call", "sys-debug", "$include", "$encode-file", "(debug", "(debug-off)" }; /* * dictionary related functions. */ /* * Compare two dictionaries constructed at different addresses. When * the cells don't match, a need for relocation is detected and the * corresponding bit in reloc_table bitmap is set. */ static void relocation_table(unsigned char * dict_one, unsigned char *dict_two, int length) { ucell *d1=(ucell *)dict_one, *d2=(ucell *)dict_two; ucell *reloc_table; int pos, bit; int l=(length+(sizeof(cell)-1))/sizeof(ucell), i; /* prepare relocation table */ relocation_length=(length+BITS-1)/BITS; reloc_table = malloc(relocation_length*sizeof(cell)); memset(reloc_table,0,relocation_length*sizeof(cell)); for (i=0; i= pointer2cell(dict_one) && // d1[i] <= pointer2cell(dict_one+length)) // printk("\nWARNING: inconsistent relocation (%x:%x)!\n", d1[i], d2[i]); } else { /* This is a pointer, it needs relocation, d2==dict */ reloc_table[pos] |= target_ucell((ucell)1ULL << bit); d2[i] = target_ucell(target_ucell(d2[i]) - pointer2cell(d2)); } } #ifdef CONFIG_DEBUG_DICTIONARY printk("dict1 %lx dict2 %lx dict %lx\n",dict_one, dict_two, dict); for (i=0; i< relocation_length ; i++) printk("reloc %d %lx\n",i+1, reloc_table[i]); #endif relocation_address=reloc_table; } static void write_dictionary(const char *filename) { FILE *f; unsigned char *write_data, *walk_data; int write_len; dictionary_header_t *header; u32 checksum=0; /* * get memory for dictionary */ write_len = sizeof(dictionary_header_t)+dicthead+relocation_length*sizeof(cell); write_data = malloc(write_len); if(!write_data) { printk("panic: can't allocate memory for output dictionary (%d" " bytes\n", write_len); exit(1); } memset(write_data, 0, write_len); /* * prepare dictionary header */ header = (dictionary_header_t *)write_data; *header = (dictionary_header_t){ .signature = DICTID, .version = 2, .cellsize = sizeof(ucell), #ifdef CONFIG_BIG_ENDIAN .endianess = -1, #else .endianess = 0, #endif .checksum = 0, .compression = 0, .relocation = -1, .length = target_ulong((uint32_t)dicthead), .last = target_ucell((ucell)((unsigned long)last - (unsigned long)dict)), }; /* * prepare dictionary data */ walk_data=write_data+sizeof(dictionary_header_t); memcpy (walk_data, dict, dicthead); /* * prepare relocation data. * relocation_address is zero when writing a dictionary core. */ if (relocation_address) { #ifdef CONFIG_DEBUG_DICTIONARY printk("writing %d reloc cells \n",relocation_length); #endif walk_data += dicthead; memcpy(walk_data, relocation_address, relocation_length*sizeof(cell)); /* free relocation information */ free(relocation_address); relocation_address=NULL; } else { header->relocation=0; } /* * Calculate Checksum */ walk_data=write_data; while (walk_datachecksum=target_long(checksum); if (verbose) { dump_header(header); } f = fopen(filename, "w"); if (!f) { printk("panic: can't write to dictionary '%s'.\n", filename); exit(1); } fwrite(write_data, write_len, 1, f); free(write_data); fclose(f); #ifdef CONFIG_DEBUG_DICTIONARY printk("wrote dictionary to file %s.\n", filename); #endif } /* * Write dictionary as a list of ucell hex values to filename. Array * header and end lines are not generated. * * Cells with relocations are output using the expression * DICTIONARY_BASE + value. * * Define some helpful constants. */ static void write_dictionary_hex(const char *filename) { FILE *f; ucell *walk; f = fopen(filename, "w"); if (!f) { printk("panic: can't write to dictionary '%s'.\n", filename); exit(1); } for (walk = (ucell *)dict; walk < (ucell *)(dict + dicthead); walk++) { int pos, bit, l; ucell val; l = (walk - (ucell *)dict); pos = l / BITS; bit = l & ~(-BITS); val = read_ucell(walk); if (relocation_address[pos] & target_ucell((ucell)1ULL << bit)) { fprintf(f, "DICTIONARY_BASE + 0x%" FMT_CELL_x ",\n", val); } else { fprintf(f, "0x%" FMT_CELL_x",\n", val); } } fprintf(f, "#define FORTH_DICTIONARY_LAST 0x%" FMT_CELL_x"\n", (ucell)((unsigned long)last - (unsigned long)dict)); fprintf(f, "#define FORTH_DICTIONARY_END 0x%" FMT_CELL_x"\n", (ucell)dicthead); fclose(f); #ifdef CONFIG_DEBUG_DICTIONARY printk("wrote dictionary to file %s.\n", filename); #endif } static ucell read_dictionary(char *fil) { int ilen; ucell ret; char *mem; FILE *f; struct stat finfo; if (stat(fil, &finfo)) return 0; ilen = finfo.st_size; if ((mem = malloc(ilen)) == NULL) { printk("panic: not enough memory.\n"); exit(1); } f = fopen(fil, "r"); if (!f) { printk("panic: can't open dictionary.\n"); exit(1); } if (fread(mem, ilen, 1, f) != 1) { printk("panic: can't read dictionary.\n"); fclose(f); exit(1); } fclose(f); ret = load_dictionary(mem, ilen); free(mem); return ret; } /* * C Parser related functions */ /* * skipws skips all whitespaces (space, tab, newline) from the input file */ static void skipws(FILE * f) { int c; while (!feof(f)) { c = getc(f); if (c == ' ' || c == '\t') continue; if (c == '\n') { srclines[cursrc - 1]++; continue; } ungetc(c, f); break; } } /* * parse gets the next word from the input stream, delimited by * delim. If delim is 0, any word delimiter will end the stream * word delimiters are space, tab and newline. The resulting word * will be put zero delimited to the char array line. */ static int parse(FILE * f, char *line, char delim) { int cnt = 0, c = 0; while (!feof(f)) { c = getc(f); if (delim && c == delim) break; if ((!delim) && (c == ' ' || c == '\t' || c == '\n')) break; line[cnt++] = c; } /* Update current line number */ if (c == '\n') { srclines[cursrc - 1]++; } line[cnt] = 0; return cnt; } /* * parse_word is a small helper that skips whitespaces before a word. * it's behaviour is similar to the forth version parse-word. */ static void parse_word(FILE * f, char *line) { skipws(f); parse(f, line, 0); } static void writestring(const char *str) { unsigned int i; for (i = 0; i < strlen(str); i++) { dict[dicthead + i] = str[i]; } dicthead += i + 1; dict[dicthead - 1] = (char) strlen(str) + 128; } #define writebyte(value) {write_byte(dict+dicthead,value); dicthead++;} #define writecell(value) {write_cell(dict+dicthead, value); dicthead+=sizeof(cell);} /* * reveal a word, ie. make it visible. */ static void reveal(void) { *last = *latest; } /* * dictionary padding */ static void paddict(ucell align) { while (dicthead % align != 0) writebyte(0); } /* * generic forth word creator function. */ static void fcreate(const char *word, ucell cfaval) { if (strlen(word) == 0) { printk("WARNING: tried to create unnamed word.\n"); return; } writestring(word); /* get us at least 1 byte for flags */ writebyte(0); paddict(sizeof(cell)); /* set flags high bit. */ dict[dicthead - 1] = 128; /* lfa and cfa */ writecell(read_ucell(latest)); *latest = target_ucell(pointer2cell(dict) + dicthead - sizeof(cell)); writecell(cfaval); } static ucell *buildvariable(const char *name, cell defval) { fcreate(name, DOVAR); /* see dict.h for DOVAR and other CFA ids */ writecell(defval); return (ucell *) (dict + dicthead - sizeof(cell)); } static void buildconstant(const char *name, cell defval) { fcreate(name, DOCON); /* see dict.h for DOCON and other CFA ids */ writecell(defval); } static void builddefer(const char *name) { fcreate(name, DODFR); /* see dict.h for DODFR and other CFA ids */ writecell((ucell)0); writecell((ucell)findword("(semis)")); } /* * Include file handling */ static void add_includepath(char *path) { include *incl = &includes; include *newpath; while (incl->next) incl = incl->next; newpath = malloc(sizeof(include)); if (!newpath) { printk("panic: not enough memory for include path.\n"); exit(1); } incl->next = newpath; newpath->path = path; newpath->next = NULL; } static FILE *fopen_include(const char *fil) { char fullpath[MAX_PATH_LEN]; FILE *ret; include *incl = &includes; while (incl) { snprintf(fullpath, sizeof(fullpath), "%s/%s", incl->path, fil); ret = fopen(fullpath, "r"); if (ret != NULL) { #ifdef CONFIG_DEBUG_INTERPRETER printk("Including '%s'\n", fil); #endif srcfilenames[cursrc] = strdup(fil); srclines[cursrc] = 1; srcfiles[cursrc++] = ret; if (depfile) { fprintf(depfile, " %s", fullpath); } return ret; } incl = incl->next; } return NULL; } /* * Forth exception handler */ void exception(cell no) { printk("%s:%d: ", srcfilenames[cursrc - 1], srclines[cursrc - 1]); /* See also forth/bootstrap/interpreter.fs */ switch (no) { case -1: case -2: printk("Aborted.\n"); break; case -3: printk("Stack Overflow.\n"); break; case -4: printk("Stack Underflow.\n"); break; case -5: printk("Return Stack Overflow.\n"); break; case -6: printk("Return Stack Underflow.\n"); break; case -19: printk("undefined word.\n"); break; case -21: printk("out of memory.\n"); break; case -33: printk("undefined method.\n"); break; case -34: printk("no such device.\n"); break; default: printk("error %" FMT_CELL_d " occured.\n", no); } exit(1); } /* * This is the C version of the forth interpreter */ static int interpret_source(char *fil) { FILE *f; char tib[160]; cell num; char *test; const ucell SEMIS = (ucell)findword("(semis)"); const ucell LIT = (ucell)findword("(lit)"); const ucell DOBRANCH = (ucell)findword("dobranch"); if ((f = fopen_include(fil)) == NULL) { printk("error while loading source file '%s'\n", fil); errors++; exit(1); } /* FIXME: We should read this file at * once. No need to get it char by char */ while (!feof(f)) { xt_t res; parse_word(f, tib); /* if there is actually no word, we continue right away */ if (strlen(tib) == 0) { continue; } /* Checking for builtin words that are needed to * bootstrap the forth base dictionary. */ if (!strcmp(tib, "(")) { parse(f, tib, ')'); continue; } if (!strcmp(tib, "\\")) { parse(f, tib, '\n'); continue; } if (!strcmp(tib, ":")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("create colon word %s\n\n", tib); #endif fcreate(tib, DOCOL); /* see dict.h for DOCOL and other CFA ids */ *state = (ucell) (-1); continue; } if (!strcmp(tib, ";")) { #ifdef CONFIG_DEBUG_INTERPRETER printk("finish colon definition\n\n"); #endif writecell((cell)SEMIS); *state = (ucell) 0; reveal(); continue; } if (!strcasecmp(tib, "variable")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("defining variable %s\n\n", tib); #endif buildvariable(tib, 0); reveal(); continue; } if (!strcasecmp(tib, "constant")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("defining constant %s\n\n", tib); #endif buildconstant(tib, POP()); reveal(); continue; } if (!strcasecmp(tib, "value")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("defining value %s\n\n", tib); #endif buildconstant(tib, POP()); reveal(); continue; } if (!strcasecmp(tib, "defer")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("defining defer word %s\n\n", tib); #endif builddefer(tib); reveal(); continue; } if (!strcasecmp(tib, "include")) { parse_word(f, tib); #ifdef CONFIG_DEBUG_INTERPRETER printk("including file %s\n\n", tib); #endif interpret_source(tib); continue; } if (!strcmp(tib, "[']")) { xt_t xt; parse_word(f, tib); xt = findword(tib); if (*state == 0) { #ifdef CONFIG_DEBUG_INTERPRETER printk ("writing address of %s to stack\n\n", tib); #endif PUSH_xt(xt); } else { #ifdef CONFIG_DEBUG_INTERPRETER printk("writing lit, addr(%s) to dict\n\n", tib); #endif writecell(LIT); /* lit */ writecell((cell)xt); } continue; /* we have no error detection here */ } if (!strcasecmp(tib, "s\"")) { int cnt; cell loco; cnt = parse(f, tib, '"'); #ifdef CONFIG_DEBUG_INTERPRETER printk("compiling string %s\n", tib); #endif loco = dicthead + (6 * sizeof(cell)); writecell(LIT); writecell(pointer2cell(dict) + loco); writecell(LIT); writecell((ucell)cnt); writecell(DOBRANCH); loco = cnt + sizeof(cell) - 1; loco &= ~(sizeof(cell) - 1); writecell(loco); memcpy(dict + dicthead, tib, cnt); dicthead += cnt; paddict(sizeof(cell)); continue; } /* look if tib is in dictionary. */ /* should the dictionary be searched before the builtins ? */ res = findword(tib); if (res) { u8 flags = read_byte((u8*)cell2pointer(res) - sizeof(cell) - 1); #ifdef CONFIG_DEBUG_INTERPRETER printk("%s is 0x%" FMT_CELL_x "\n", tib, (ucell) res); #endif if (!(*state) || (flags & 3)) { #ifdef CONFIG_DEBUG_INTERPRETER printk("executing %s, %" FMT_CELL_d " (flags: %s %s)\n", tib, res, (flags & 1) ? "immediate" : "", (flags & 2) ? "compile-only" : ""); #endif PC = (ucell)res; enterforth(res); } else { #ifdef CONFIG_DEBUG_INTERPRETER printk("writing %s to dict\n\n", tib); #endif writecell((cell)res); } continue; } /* if not look if it's a number */ if (tib[0] == '-') num = strtoll(tib, &test, read_ucell(base)); else num = strtoull(tib, &test, read_ucell(base)); if (*test != 0) { /* what is it?? */ printk("%s:%d: %s is not defined.\n\n", srcfilenames[cursrc - 1], srclines[cursrc - 1], tib); errors++; #ifdef CONFIG_DEBUG_INTERPRETER continue; #else return -1; #endif } if (*state == 0) { #ifdef CONFIG_DEBUG_INTERPRETER printk("pushed %" FMT_CELL_x " to stack\n\n", num); #endif PUSH(num); } else { #ifdef CONFIG_DEBUG_INTERPRETER printk("writing lit, %" FMT_CELL_x " to dict\n\n", num); #endif writecell(LIT); /* lit */ writecell(num); } } fclose(f); cursrc--; return 0; } static int build_dictionary(void) { ucell lfa = 0; unsigned int i; /* we need a temporary place for latest outside the dictionary */ latest = &lfa; /* starting a new dictionary: clear dicthead */ dicthead = 0; #ifdef CONFIG_DEBUG_DICTIONARY printk("building dictionary, %d primitives.\nbuilt words:", sizeof(wordnames) / sizeof(void *)); #endif for (i = 0; i < sizeof(wordnames) / sizeof(void *); i++) { if (strlen(wordnames[i]) != 0) { fcreate((char *) wordnames[i], i); #ifdef CONFIG_DEBUG_DICTIONARY printk(" %s", wordnames[i]); #endif } } #ifdef CONFIG_DEBUG_DICTIONARY printk(".\n"); #endif /* get last/latest and state */ state = buildvariable("state", 0); last = buildvariable("forth-last", 0); latest = buildvariable("latest", 0); *latest = target_ucell(pointer2cell(latest)-2*sizeof(cell)); base=buildvariable("base", 10); buildconstant("/c", sizeof(u8)); buildconstant("/w", sizeof(u16)); buildconstant("/l", sizeof(u32)); buildconstant("/n", sizeof(ucell)); buildconstant("/x", sizeof(u64)); reveal(); if (verbose) { printk("Dictionary initialization finished.\n"); } return 0; } /* * functions used by primitives */ int availchar(void) { int tmp; if( cursrc < 1 ) { interruptforth |= FORTH_INTSTAT_STOP; /* return -1 in order to exit the loop in key() */ return -1; } tmp = getc( srcfiles[cursrc-1] ); if (tmp != EOF) { ungetc(tmp, srcfiles[cursrc-1]); return -1; } fclose(srcfiles[--cursrc]); return availchar(); } int get_inputbyte( void ) { int tmp; if( cursrc < 1 ) { interruptforth |= FORTH_INTSTAT_STOP; return 0; } tmp = getc( srcfiles[cursrc-1] ); /* Update current line number */ if (tmp == '\n') { srclines[cursrc - 1]++; } if (tmp != EOF) { return tmp; } fclose(srcfiles[--cursrc]); return get_inputbyte(); } void put_outputbyte( int c ) { if (console) fputc(c, console); } /* * segmentation fault handler. linux specific? */ static void segv_handler(int signo __attribute__ ((unused)), siginfo_t * si, void *context __attribute__ ((unused))) { static int count = 0; ucell addr = 0xdeadbeef; if (count) { printk("Died while dumping forth dictionary core.\n"); goto out; } count++; if (PC >= pointer2cell(dict) && PC <= pointer2cell(dict) + dicthead) addr = read_cell(cell2pointer(PC)); printk("panic: segmentation violation at %p\n", (char *)si->si_addr); printk("dict=%p here=%p(dict+0x%" FMT_CELL_x ") pc=0x%" FMT_CELL_x "(dict+0x%" FMT_CELL_x ")\n", dict, dict + dicthead, dicthead, PC, PC - pointer2cell(dict)); printk("dstackcnt=%d rstackcnt=%d instruction=%" FMT_CELL_x "\n", dstackcnt, rstackcnt, addr); printdstack(); printrstack(); printk("Writing dictionary core file\n"); write_dictionary("forth.dict.core"); out: exit(1); } /* * allocate memory and prepare engine for memory management. */ static void init_memory(void) { memset(memory, 0, MEMORY_SIZE); /* we push start and end of memory to the stack * so that it can be used by the forth word QUIT * to initialize the memory allocator. * Add a cell to the start address so we don't end * up with a start address of zero during bootstrap */ PUSH(pointer2cell(memory)+sizeof(cell)); PUSH(pointer2cell(memory) + MEMORY_SIZE-1); } void include_file( const char *name ) { FILE *file; if( cursrc >= sizeof(srcfiles)/sizeof(srcfiles[0]) ) { printk("\npanic: Maximum include depth reached!\n"); exit(1); } file = fopen_include( name ); if( !file ) { printk("\npanic: Failed opening file '%s'\n", name ); exit(1); } } void encode_file( const char *name ) { FILE *file = fopen_include(name); int size; if( !file ) { printk("\npanic: Can't open '%s'\n", name ); exit(1); } fseek( file, 0, SEEK_END ); size = ftell( file ); fseek( file, 0, SEEK_SET ); if (verbose) { printk("\nEncoding %s [%d bytes]\n", name, size ); } fread( dict + dicthead, size, 1, file ); PUSH( pointer2cell(dict + dicthead) ); PUSH( size ); dicthead += size; paddict(sizeof(cell)); } static void run_dictionary(char *basedict, char *confile) { if(!basedict) return; read_dictionary(basedict); PC = (ucell)findword("initialize"); if (!PC) { if (verbose) { printk("Unable to find initialize word in dictionary %s; ignoring\n", basedict); } return; } if(!srcfiles[0]) { cursrc = 1; srcfiles[cursrc-1] = stdin; } dstackcnt=0; rstackcnt=0; init_memory(); if (verbose) printk("Jumping to dictionary %s...\n", basedict); /* If a console file has been specified, open it */ if (confile) console = fopen(confile, "w"); srcbasedict = basedict; enterforth((xt_t)PC); /* Close the console file */ if (console) fclose(console); } static void new_dictionary(const char *source) { build_dictionary(); interpret_source((char *)source); if (verbose || errors > 0) { printk("interpretion finished. %d errors occured.\n", errors); } } /* * main loop */ #define BANNER "OpenBIOS bootstrap kernel. (C) 2003-2006 Patrick Mauritz, Stefan Reinauer\n"\ "This software comes with absolutely no warranty. "\ "All rights reserved.\n\n" #ifdef __GLIBC__ #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ " -h|--help show this help\n" \ " -V|--version print version and exit\n" \ " -v|--verbose print debugging information\n" \ " -I|--include dir add dir to include path\n" \ " -d|--source-dictionary bootstrap.dict\n" \ " use this dictionary as base\n" \ " -D|--target-dictionary output.dict\n" \ " write to output.dict\n" \ " -c|--console output.log\n" \ " write kernel console output to log file\n" \ " -s|--segfault install segfault handler\n" \ " -M|--dependency-dump file\n" \ " dump dependencies in Makefile format\n\n" \ " -x|--hexdump output format is C language hex dump\n" #else #define USAGE "Usage: %s [options] [dictionary file|source file]\n\n" \ " -h show this help\n" \ " -V print version and exit\n" \ " -v print debugging information\n" \ " -I add dir to include path\n" \ " -d bootstrap.dict\n" \ " use this dictionary as base\n" \ " -D output.dict\n" \ " write to output.dict\n" \ " -c output.log\n" \ " write kernel console output to log file\n" \ " -s install segfault handler\n\n" \ " -M file dump dependencies in Makefile format\n\n" \ " -x output format is C language hex dump\n" #endif int main(int argc, char *argv[]) { struct sigaction sa; unsigned char *ressources=NULL; /* All memory used by us */ const char *dictname = NULL; char *basedict = NULL; char *consolefile = NULL; char *depfilename = NULL; unsigned char *bootstrapdict[2]; int c, cnt, hexdump = 0; const char *optstring = "VvhsI:d:D:c:M:x?"; while (1) { #ifdef __GLIBC__ int option_index = 0; static struct option long_options[] = { {"version", 0, NULL, 'V'}, {"verbose", 0, NULL, 'v'}, {"help", 0, NULL, 'h'}, {"segfault", 0, NULL, 's'}, {"include", 1, NULL, 'I'}, {"source-dictionary", 1, NULL, 'd'}, {"target-dictionary", 1, NULL, 'D'}, {"console", 1, NULL, 'c'}, {"dependency-dump", 1, NULL, 'M'}, {"hexdump", 0, NULL, 'x'}, }; /* * option handling */ c = getopt_long(argc, argv, optstring, long_options, &option_index); #else c = getopt(argc, argv, optstring); #endif if (c == -1) break; switch (c) { case 'V': printk("Version " OPENBIOS_VERSION_STR "\n"); return 0; case 'h': case '?': printk("Version " OPENBIOS_VERSION_STR "\n" USAGE, argv[0]); return 0; case 'v': verbose = 1; break; case 's': segfault = 1; break; case 'I': #ifdef CONFIG_DEBUG_INTERPRETER printk("adding '%s' to include path\n", optarg); #endif add_includepath(optarg); break; case 'd': if (!basedict) { basedict = optarg; } break; case 'D': if(!dictname) { dictname = optarg; } break; case 'c': if (!consolefile) { consolefile = optarg; } break; case 'M': if (!depfilename) { depfilename = optarg; } break; case 'x': hexdump = 1; break; default: return 1; } } if (!dictname) { dictname = "bootstrap.dict"; } if (verbose) { printk(BANNER); printk("Using source dictionary '%s'\n", basedict); printk("Dumping final dictionary to '%s'\n", dictname); printk("Dumping dependencies to '%s'\n", depfilename); } if (argc < optind) { printk(USAGE, argv[0]); return 1; } if (depfilename) { depfile = fopen(depfilename, "w"); if (!depfile) { printk("panic: can't write to dependency file '%s'.\n", depfilename); exit(1); } fprintf(depfile, "%s:", dictname); } /* * Get all required resources */ ressources = malloc(MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE); if (!ressources) { printk("panic: not enough memory on host system.\n"); return 1; } #ifdef NATIVE_BITWIDTH_SMALLER_THAN_HOST_BITWIDTH base_address=(unsigned long)ressources; #endif memory = (ucell *)ressources; bootstrapdict[0] = ressources + MEMORY_SIZE; bootstrapdict[1] = ressources + MEMORY_SIZE + DICTIONARY_SIZE; trampoline = (ucell *)(ressources + MEMORY_SIZE + DICTIONARY_SIZE + DICTIONARY_SIZE); #ifdef CONFIG_DEBUG_INTERPRETER printf("memory: %p\n",memory); printf("dict1: %p\n",bootstrapdict[0]); printf("dict2: %p\n",bootstrapdict[1]); printf("trampoline: %p\n",trampoline); printf("size=%d, trampoline_size=%d\n",MEMORY_SIZE + (2 * DICTIONARY_SIZE) + TRAMPOLINE_SIZE, TRAMPOLINE_SIZE); #endif if (trampoline == NULL) { /* We're using side effects which is to some extent nasty */ printf("WARNING: no trampoline!\n"); } else { init_trampoline(trampoline); } if (!segfault) { if (verbose) printk("Installing SIGSEGV handler..."); sa.sa_sigaction = segv_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_NODEFER; sigaction(SIGSEGV, &sa, NULL); if (verbose) printk("done.\n"); } /* * Now do the real work */ for (cnt=0; cnt<2; cnt++) { if (verbose) { printk("Compiling dictionary %d/%d\n", cnt+1, 2); } dict=bootstrapdict[cnt]; if(!basedict) { new_dictionary(argv[optind]); } else { for (c=argc-1; c>=optind; c--) include_file(argv[c]); run_dictionary(basedict, consolefile); } if (depfile) { fprintf(depfile, "\n"); fclose(depfile); depfile = NULL; } if(errors) break; } #ifndef CONFIG_DEBUG_INTERPRETER if (errors) printk("dictionary not dumped to file.\n"); else #endif { relocation_table( bootstrapdict[0], bootstrapdict[1], dicthead); if (hexdump) { write_dictionary_hex(dictname); } else { write_dictionary(dictname); } } free(ressources); if (errors) return 1; else return 0; }