Annotation of coherent/d/conf/tboot/gift.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * gift.c -- Prepare a gift of information for the program currently loaded.
        !             3:  *
        !             4:  * To pass a new data structure into the kernel:
        !             5:  *
        !             6:  * 1. Define your new data structure in typed.h.  You will probably want
        !             7:  *    to define some supporting routines for your data structure.  These
        !             8:  *    should go in a file by themselves.  Be sure to add the file to the
        !             9:  *    tboot Makefile.
        !            10:  * 
        !            11:  * 2. Write a routine that takes at least an ffp, which will generate your
        !            12:  *    data structure and write it into the ffp.  The routine should return 0
        !            13:  *    if it ran out of space in the FIFO.  Other return values are permissible,
        !            14:  *    but ignored.  Add arguments to prepare_gift() as needed.  It is called
        !            15:  *    only from the end of execute() in execute.c.
        !            16:  *
        !            17:  * 3. Add a call to your routine to prepare_gift() in the section marked
        !            18:  *    FILL THE BOX.  This is an if statement with || seperated calls.  The
        !            19:  *    most important data structures should be called first, because later
        !            20:  *    calls will be skipped if the FIFO fills.
        !            21:  *
        !            22:  * 4. In the kernel (probably in a driver) you will want to add a loop to
        !            23:  *    look through the gift for your data structure:
        !            24:  *
        !            25:  *    FIFO *ffp;
        !            26:  *    typed_space *tp;
        !            27:  *
        !            28:  *    ffp = fifo_open(&boot_gift, 0);  -- Open gift for reading. 
        !            29:  * 
        !            30:  *    if (F_NULL == ffp) {
        !            31:  *       indicate_error("Could not open boot_gift.");
        !            32:  *    } else {
        !            33:  *        while (T_NULL != (tp = fifo_read(ffp))) {    -- While not EOFIFO.
        !            34:  *           if (T_MYTYPE == tp->ts_type) {    -- Is this my type?
        !            35:  *               my_handler(tp->ts_data);      -- Process the data.
        !            36:  *           }
        !            37:  *        }
        !            38:  *    }
        !            39:  *
        !            40:  *    Be sure to include fifo.c and typed.h into your kernel.
        !            41:  *       
        !            42:  */
        !            43: #include <string.h>
        !            44: #include <sys/fdisk.h>
        !            45: #include <sys/typed.h>
        !            46: #include "tboot.h"
        !            47: 
        !            48: 
        !            49: #define GIFTBOX        4096 /* Size of the gift box (maximum size of gift.)  */
        !            50: 
        !            51: 
        !            52: /* We have to build the gift in the local segment and then copy it in
        !            53:  * place.  In a better world, the gift could be built in place.
        !            54:  */
        !            55: TYPED_SPACE(local_gift, GIFTBOX, T_FIFO_SIC); /* Static In-Core Fifo.  */
        !            56: 
        !            57: 
        !            58: /* Prepare a gift of information for the program currently loaded.
        !            59:  *
        !            60:  * The gift is a Static In-Core FIFO whose objects are typed spaces.
        !            61:  *
        !            62:  * argv is the command vector needed by gift_argf().
        !            63:  *
        !            64:  * It should be placed in memory at data_seg:offset.
        !            65:  */
        !            66: void
        !            67: prepare_gift(data_seg, offset, argv)
        !            68:        uint16 data_seg;
        !            69:        uint16 offset;
        !            70:        char *argv[];
        !            71: {
        !            72:        FIFO *ffp;              /* Fifo pointer for a handle.  */
        !            73:        typed_space gift_header;        /* Header for destination box.  */
        !            74:        char buff[sizeof("65536")];     /* For outputting base 10 integers.  */
        !            75: 
        !            76:        /* Value of ds register, initialized in Startup.s.  */
        !            77:        extern uint16 myds;
        !            78: 
        !            79:        /* Find out how big a gift we may offer.  */
        !            80:        ffcopy(&gift_header, myds, offset, data_seg, sizeof(typed_space));
        !            81:        if (gift_header.ts_size > local_gift.ts_size) {
        !            82:                puts("WARNING: argument structures larger than ");
        !            83:                itobase((int) local_gift.ts_size, buff, 10);
        !            84:                puts(buff);
        !            85:                puts(" bytes are not currently supported.\r\n");
        !            86:                puts("Truncating down from ");
        !            87:                itobase((int) gift_header.ts_size, buff, 10);
        !            88:                puts(buff);
        !            89:                puts(".\r\n");
        !            90:                puts("This is probably harmless.\r\n");
        !            91:        } else {
        !            92:                /* Requested gift is smaller than what we can offer.  */
        !            93:                local_gift.ts_size = gift_header.ts_size;
        !            94:        }
        !            95: 
        !            96:        /* ASSERTION: local_gift is now no larger than boot_gift.  */
        !            97: 
        !            98:        /* Open the local gift box.  */
        !            99:        if (F_NULL == (ffp = fifo_open(&local_gift, 1))) {
        !           100:                puts("prepare_gift():  Can't open local_gift for writing.\r\n");
        !           101:                puts("prepare_gift():  No information will be passed.\r\n");
        !           102:                return;
        !           103:        }
        !           104: 
        !           105:        /* FILL THE BOX.  */
        !           106:        /* Stop filling in if we run out of space.  */
        !           107:        if ((0 == gift_drive_params(ffp)) ||
        !           108:            (0 == gift_rootdev(ffp)) ||
        !           109:            (0 == gift_argf(ffp, argv))
        !           110:           ) {
        !           111:                puts("prepare_gift(): WARNING: not enough room for all arguments.\r\n");
        !           112:                puts("Only ");
        !           113:                itobase((int) ((char *)ffp->f_offset - (char *)ffp->f_space), buff, 10);
        !           114:                puts(buff);
        !           115:                puts(" bytes submitted.\r\n");
        !           116:        }
        !           117: 
        !           118:        fifo_close(ffp);
        !           119: 
        !           120:        /* Copy the gift into the loaded program.  */
        !           121:        ffcopy(offset, data_seg, &local_gift, myds,
        !           122:                (uint16) local_gift.ts_size);
        !           123: } /* prepare_gift() */
        !           124: 
        !           125: 
        !           126: /* Load the BIOS parameters loaded up by the startup code.  */
        !           127: int
        !           128: gift_drive_params(ffp)
        !           129:        FIFO *ffp;
        !           130: {
        !           131:        int i;
        !           132:        int num_of_drives;
        !           133:        struct reg r;
        !           134:        BIOS_DISK diskparms;
        !           135:        
        !           136:        
        !           137:        num_of_drives = get_num_of_drives();
        !           138: 
        !           139:        if (verbose_flag) {
        !           140:                puts("Found 0x");
        !           141:                print16(num_of_drives);
        !           142:                puts(" drives.\r\n");
        !           143:        }
        !           144: 
        !           145:        for (i = 0; i < num_of_drives; ++i) {
        !           146:         
        !           147:                r.r_ax = DISK_PARAMS;
        !           148:                r.r_dx = HARD_DRIVE + i;
        !           149:        
        !           150:                intcall(&r, &r, DISKINT);       /* Ask the BIOS.  */
        !           151: 
        !           152:                diskparms.dp_drive = i;
        !           153: 
        !           154:                /* ch is the lower 8 bits of number of cylinders.
        !           155:                 * The high two bits of cl are the top two bits of
        !           156:                 * 10 bit number of cylinders.
        !           157:                 *
        !           158:                 * The cylinder count is actually 1 short.
        !           159:                 */
        !           160:                diskparms.dp_cylinders = (uint16) (
        !           161:                          ((LOW(r.r_cx) >> 6) * 256) + /* Top two bits...  */
        !           162:                          (HIGH(r.r_cx) + 1)
        !           163:                        );
        !           164: 
        !           165:        
        !           166:                /* The head count is actually 1 short.  */
        !           167: 
        !           168:                diskparms.dp_heads = ((uint16) HIGH(r.r_dx)) + 1;
        !           169:        
        !           170:                /* Only the lower 6 bits of cl are the sectors per track.  */
        !           171:                
        !           172:                diskparms.dp_sectors = (uint16) (SIXBITS & LOW(r.r_cx));
        !           173: 
        !           174:                /* Store these parameters for delivery.  */
        !           175:                if (T_NULL == fifo_write_untyped(ffp,
        !           176:                                                 &diskparms,
        !           177:                                                 (int32) sizeof(BIOS_DISK),
        !           178:                                                 T_BIOS_DISK)
        !           179:                   ) {
        !           180:                        puts("gift_drive_params() ran out of space.");
        !           181:                        return(0);
        !           182:                }
        !           183: 
        !           184:        } /* for i = 0 to num_of_drives - 1 */
        !           185: 
        !           186:        return(1);      /* We didn't run out of space.  */
        !           187: 
        !           188: } /* gift_drive_params() */
        !           189: 
        !           190: /*
        !           191:  * We'd really rather have a dynamic in-core fifo, but they are not
        !           192:  * yet implimented.  We'll have to settle for a fixed length argument list.
        !           193:  */
        !           194: TYPED_SPACE(argf, BLOCK, T_FIFO_SIC);
        !           195: 
        !           196: /*
        !           197:  * To read this item from bootgift, use the procedure outlined above in
        !           198:  * point 4 to find the entry marked T_STR_ARGF.  You must then explicitly
        !           199:  * recast it with RETYPE(tp->ts_data, T_FIFO_SIC).  Then you can open it
        !           200:  * as a FIFO, with code modeled on point 4 above.  This scheme seemed
        !           201:  * the simplest for uniquely identifying the argument FIFO.
        !           202:  * Each element of the FIFO is a T_STR_STR, so ts_data for these is
        !           203:  * just a NUL terminated string.
        !           204:  */
        !           205: 
        !           206: /*
        !           207:  * Write an argument fifo into ffp from the argument vector argv[].
        !           208:  * Returns 0 if it runs out of space, 1 on success, 2 if it could not
        !           209:  * open the local gift box for some reason.
        !           210:  */
        !           211: int
        !           212: gift_argf(ffp, argv)
        !           213:        FIFO *ffp;
        !           214:        char *argv[];
        !           215: {
        !           216:        FIFO *argfp;    /* For the argument fifo we're going to build.  */
        !           217:        char *current_token;
        !           218:        int i;
        !           219: 
        !           220:        /* Open the local gift box.  */
        !           221:        if (F_NULL == (argfp = fifo_open(&argf, 1))) {
        !           222:                puts("gift_argf():  Can't open local argument fifo for writing.\r\n");
        !           223:                puts("gift_argf():  No command line information will be passed.\r\n");
        !           224:                return(2);
        !           225:        }
        !           226: 
        !           227:        current_token = argv[0];
        !           228:        /*
        !           229:         * Build the command fifo.
        !           230:         */
        !           231:        for (i = 0; NULL != current_token; current_token = argv[++i]) {
        !           232:                if (T_NULL == 
        !           233:                        fifo_write_untyped(argfp,
        !           234:                                   current_token,
        !           235:                                   (int32) (strlen(current_token) + 1),
        !           236:                                   T_STR_STR)
        !           237:                ) {
        !           238:                        puts("gift_argf():  WARNING:  Command line too long.\r\n");
        !           239:                        puts("Truncating.\r\n");
        !           240:                        break;
        !           241:                }
        !           242:        }
        !           243: 
        !           244: 
        !           245:        /*
        !           246:         * Truncate argf to the minimum size needed.
        !           247:         */
        !           248:        RESIZE(&argf, fifo_len(argfp));
        !           249: 
        !           250:        /*
        !           251:         * Now that we've filled the FIFO, let's mark
        !           252:         * it as an argument fifo.
        !           253:         */
        !           254:        RETYPE(&argf, T_STR_ARGF);
        !           255: 
        !           256:        close(argfp);
        !           257: 
        !           258:        /* Write it into ffp.  */
        !           259:        if (T_NULL == fifo_write(ffp, &argf)) {
        !           260:                puts("gift_argf() ran out of space.");
        !           261:                return(0);
        !           262:        }
        !           263: 
        !           264:        return(1);
        !           265: } /* gift_argf() */
        !           266: 
        !           267: /*
        !           268:  * Write a structure describing the boot partition into a fifo.
        !           269:  * Returns 1 on success, 0 if it runs out of space, or 2 if it
        !           270:  * can't read the boot block.
        !           271:  */
        !           272: int
        !           273: gift_rootdev(ffp)
        !           274:        FIFO *ffp;
        !           275: {
        !           276: #define        NOPARTITION     255     /* Convenient illegal partition number.  */
        !           277: #define PART_PER_DRIVE 4       /* Number of partitions per drive.  */
        !           278: 
        !           279:        BIOS_ROOTDEV myrootdev; /* Build the data to be passed here.  */
        !           280:        FDISK_S fp[NPARTN];     /* Room for a partition table from disk.  */
        !           281:        int8 i;
        !           282: 
        !           283:        extern uint8 drive;     /* Drive number from secondary boot.  */
        !           284:        extern uint32 first;    /* Block number of start of partition.  */
        !           285:        
        !           286:        /* Fetch the partition table from disk.  */
        !           287:        if (0 == fdisk(fp)) {
        !           288:                puts("gift_rootdev() WARNING: invalid boot block.\r\n");
        !           289:                return(2);
        !           290:        }
        !           291: 
        !           292:        /* Mark an invalid partition.  */
        !           293:        myrootdev.rd_partition = NOPARTITION;
        !           294: 
        !           295:        /* Look for the current partition in the table.  */
        !           296:        for (i=0; i < NPARTN; ++i) {
        !           297:                if (first == fp[i].p_base) {
        !           298:                        myrootdev.rd_partition = i;
        !           299:                        break;
        !           300:                }
        !           301:        }
        !           302: 
        !           303:        if (NOPARTITION == myrootdev.rd_partition) {
        !           304:                puts("gift_rootdev() WARNING: Can't find my partition.\r\n");
        !           305:                return(2);
        !           306:        }
        !           307: 
        !           308:        /* Adjust the partition for the drive number.  */
        !           309:        myrootdev.rd_partition += (PART_PER_DRIVE * drive);
        !           310: 
        !           311:        if (T_NULL == fifo_write_untyped(ffp,
        !           312:                                         &myrootdev,
        !           313:                                         (int32) sizeof(BIOS_ROOTDEV),
        !           314:                                         T_BIOS_ROOTDEV)
        !           315:        ) {
        !           316:                puts("Ran out of space in gift_rootdev().\r\n");
        !           317:                return(0);
        !           318:        } else {
        !           319:                return(1);
        !           320:        }
        !           321: } /* gift_rootdev() */
        !           322: 
        !           323: /* Dump the contents of boot_gift.  */
        !           324: void
        !           325: dump_gift()
        !           326: {
        !           327:        extern typed_space boot_gift;
        !           328: 
        !           329:        puts("Dumping boot_gift.\r\n");
        !           330:        dump_fifo(&boot_gift);
        !           331: }
        !           332: 
        !           333: /* Dump the contents of a fifo.  */
        !           334: void
        !           335: dump_fifo(fifo)
        !           336:        typed_space *fifo;
        !           337: {
        !           338:     FIFO *ffp;
        !           339:     typed_space *tp;
        !           340: 
        !           341:     puts("Dumping a fifo.\r\n");
        !           342: 
        !           343:     if (F_NULL == (ffp = fifo_open(fifo, 0))) {        /* Open gift for reading.  */
        !           344:        puts("Can't open fifo.\r\n");
        !           345:        return;
        !           346:     }
        !           347: 
        !           348:     while (T_NULL != (tp = fifo_read(ffp))) {  /* While not EOFIFO.  */
        !           349:        switch(tp->ts_type) {
        !           350:        case T_BIOS_DISK:
        !           351:                dump_bios_disk(tp->ts_data);
        !           352:                break;
        !           353:        case T_BIOS_ROOTDEV:
        !           354:                dump_rootdev(tp->ts_data);
        !           355:                break;
        !           356:        case T_FIFO_SIC:
        !           357:                dump_fifo(tp);
        !           358:                break;
        !           359:        case T_STR_STR:
        !           360:                puts("String: ");
        !           361:                puts(tp->ts_data);
        !           362:                break;
        !           363:        case T_STR_ARGF:
        !           364:                RETYPE(tp, T_FIFO_SIC);
        !           365:                dump_fifo(tp);
        !           366:                break;
        !           367:        default:
        !           368:                puts("Unknown type: 0x");
        !           369:                print16(tp->ts_type);
        !           370:                break;
        !           371:        }
        !           372:        puts("\r\n");
        !           373:     }
        !           374:     puts("Nothing more to dump in this fifo.\r\n");
        !           375: 
        !           376: } /* dump_gift() */
        !           377: 
        !           378: /* Dump a T_BIOS_DISK typed_space.  */
        !           379: void
        !           380: dump_bios_disk(a_disk)
        !           381:        BIOS_DISK *a_disk;
        !           382: {
        !           383:        char buffer[BLOCK];
        !           384: 
        !           385:        puts("Dumping a BIOS_DISK struct.\r\n");
        !           386: 
        !           387:        puts("Drive ");
        !           388:        itobase((uint16) a_disk->dp_drive, buffer, 10);
        !           389:        puts(buffer);
        !           390: 
        !           391:        puts(":  Cylinders=");
        !           392:        itobase((uint16) a_disk->dp_cylinders, buffer, 10);
        !           393:        puts(buffer);
        !           394: 
        !           395:        puts("  Heads=");
        !           396:        itobase((uint16) a_disk->dp_heads, buffer, 10);
        !           397:        puts(buffer);
        !           398: 
        !           399:        puts("  Sectors per track=");
        !           400:        itobase((uint16) a_disk->dp_sectors, buffer, 10);
        !           401:        puts(buffer);
        !           402: 
        !           403:        puts("\r\n");
        !           404: } /* dump_bios_disk() */
        !           405: 
        !           406: 
        !           407: /* Dump a T_BIOS_ROOTDEV typed_space.  */
        !           408: void
        !           409: dump_rootdev(a_rootdev)
        !           410:        BIOS_ROOTDEV *a_rootdev;
        !           411: {
        !           412:        puts("Dumping a BIOS_ROOTDEV struct.\r\n");
        !           413: 
        !           414:        puts("partition: 0x");
        !           415:        print8(a_rootdev->rd_partition);
        !           416:        puts("\r\n");
        !           417: } /* dump_rootdev() */

unix.superglobalmegacorp.com

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