|
|
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.