Annotation of qemu/roms/openbios/kernel/bootstrap.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.