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