|
|
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() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.