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