|
|
1.1 root 1: / Startup.s -- initilization code for any tertiary boot program.
2: /
3: / La Monte H. Yarroll <[email protected]>, September 1991
4: /
5: / RBOOTS is set exactly 128K below the top of 640K.
6: / One day, RBOOTS should be dynamicly determined based on the size of
7: / available memory.
8: RBOOTS = 0x8000 / New segement for boot program.
9: JMPF = 0xEA / jump far, direct
10: SEGSIZ = 0xffff / Size of a whole segment.
11: NSTK = 0x2000 / # of bytes of stack.
12: BLOCK = 0x200 / # of bytes in a disk block
13: DIRSIZE = 14 / Size of a file name.
14: SIZEOFSDAT = 23 / sizeof(seconddat)
15: SECONDDAT = 0x01E7 / Offset of useful data in secondary boot.
16: CR = 0x0d / Carriage return
17: LF = 0x0a / Line Feed
18: NUL = 0x00 / NUL (for terminating strings)
19: / Interrupts.
20: MON = 0x00 / Invoke BIOS monitor.
21: KEYBD = 0x16 / Keyboard software interrupt.
22: REBOOT = 0x19 / Reboot through BIOS.
23:
24:
25: NTRK = 40 / Number of tracks on a floppy.
26: NSPT = 9 / Number of sectors per track on a floppy.
27: NHD = 1 / Number of heads per drive on a floppy.
28: .bssd
29: stack: .blkb NSTK / Local Stack
30: .shri
31: .blkb 0x100 / Symbol "begin" must be at offset 0x100 from
32: begin: / the beginning of the code segment--secondary
33: / boot jumps here.
34: / Upon entry ds points at the secondary boot data segment,
35: / si points at the data we want,
36: / and es points at our data segment.
37: mov di, $seconddat
38: mov cx, $SIZEOFSDAT
39: cld
40: rep
41: movsb / Copy disk configuration information to our own segment.
42: / Create a nice, safe stack.
43: mov bp, $stack+NSTK
44: mov ax, es
45: mov ss, ax
46: mov sp, bp
47:
48: push es / Save location of data segment from secondary boot.
49: / Move the tertiary boot to high memory.
50: call moveme
51:
52: add sp, $2 / Throw away old data segment.
53: / Set up the new stack.
54: mov bp, $stack+NSTK
55: mov ax, es
56: mov ss, ax
57: mov sp, bp
58: .byte JMPF / Jump to the relocated code.
59: .word entry
60: .word RBOOTS
61: entry: call main_
62: / Aargh! main() returned! Wait for a keystroke and then reboot.
63: push $keymsg
64: call puts_
65: 0: movb ah, $1 / while (!iskey()) {};
66: int KEYBD / /* Read the key. */
67: movb ah, $1 / } while (iskey())
68: int KEYBD / /* Scan the keyboard for another key. */
69: jne 1b /
70: int REBOOT / Reboot through the BIOS.
71: .shrd
72: keymsg:
73: .byte CR
74: .byte LF
75: .ascii "Press any key to reboot."
76: .byte CR
77: .byte LF
78: .byte NUL
79: ////////
80: /
81: / Move tertiary boot to high memory.
82: / Take one parameter--a word on the stack pointing to the current
83: / data segment.
84: /
85: / As a side effect, this sets ds to the new data segment in high memory.
86: /
87: ////////
88: .shri
89: moveme:
90: mov bp, sp / For parameter lookups.
91: / Move the code segment.
92: push cs
93: pop ds
94: xor si, si / Point ds:si at loaded code segment.
95: mov ax, $RBOOTS
96: mov es, ax
97: xor di, di / Point es:di at where we want to be.
98: mov cx, $SEGSIZ / Move a maximal segment.
99: cld
100: rep
101: movsb
102: / Calculate location of new data segment.
103: mov ax, 2(bp)
104: push cs / Fetch the code segment.
105: pop bx
106: sub ax, bx / Calculate offset to data segment.
107: add ax, $RBOOTS / Calculate the new data segment.
108:
109: / Move the data segment.
110: mov ds, 2(bp)
111: xor si, si / Point ds:si at loaded data segment
112: mov es, ax
113: xor di, di / Point es:di at where we want to be.
114: mov cx, $SEGSIZ / Move a maximal segment.
115: cld
116: rep
117: movsb
118: / Set the new data segment appropriately.
119: push es
120: pop ds
121: mov myds_, ds
122: ret / routine moveme
123: / Shared data segment (initialized)
124: .shrd
125: .globl myds_
126: myds_: .word 0 / Place to communicate ds to C programs.
127: / Variables nbuf, traks, sects, and heads MUST appear in this order.
128: .globl seconddat
129: seconddat: / Data extracted from secondary boot data segment.
130: .globl nbuf_
131: nbuf_:
132: nbuf: .blkb DIRSIZE
133: / Defaults for all the following parameters match a floppy disk.
134: .globl traks
135: .globl traks_
136: traks_:
137: traks: .word NTRK / Number of cylinders on drive we're booting off of.
138: .globl sects
139: .globl sects_
140: sects_:
141: sects: .byte NSPT / Number of sectors per track for our drive.
142: .globl heads
143: .globl heads_
144: heads_:
145: heads: .byte NHD / Number of heads on drive we're booting off of.
146: .globl drive
147: .globl drive_
148: drive_:
149: drive: .byte 0 / Drive our partition resides upon.
150: .globl first
151: .globl first_
152: first_:
153: first: .word 0 / First block of our partition (?)
154: .word 0
155: /*
156: * Determine whether or not a given argument exists on the command line
157: * passed into the kernel.
158: *
159: * Takes a pointer to a NUL terminated string that is the name of
160: * the desired argument.
161: */
162: extern typed_space boot_gift;
163: int
164: arg_exist(arg)
165: {
166: } /* arg_exist() */
167: /*
168: * Looks for the string "astring" in the fifo "afifo".
169: * Returns TRUE if it find the string.
170: */
171: int
172: fifo_find_str(afifo, astring)
173: typed_space *afifo;
174: char *astring;
175: {
176: } /* fifo_find_str() */
177: /*
178: * bio.c -- buffer handling code.
179: *
180: * This code REALLY assumes single-threaded execution. All locks are
181: * advisory only and may be revoked without notice.
182: *
183: * See also bread() in diskio.c.
184: */
185: static BUF bufl[NBUF]; /* Buffer structures. */
186: static char blockp[NBUF * BLOCK]; /* The blocks themselves. */
187: static int buf_inited = (1==2); /* Has bufinit been called? */
188: /*
189: * Initialise buffer headers.
190: */
191: void
192: bufinit()
193: {
194: } /* bufinit() */
195: /*
196: * Claim a buffer for a block.
197: * Finds the buffer if it has already been accessed, otherwise,
198: * picks another buffer.
199: */
200: BUF *
201: bclaim(block)
202: daddr_t block;
203: {
204: } /* bclaim() */
205: /*
206: * Pick the next buffer for allocation.
207: * Uses a round-robin scheme of buffer allocation, skipping over
208: * locked buffers. If all buffers are locked, they are forcibly
209: * unlocked and the first one is picked.
210: */
211: BUF *
212: bpick()
213: {
214: } /* bpick() */
215: /*
216: * Release a buffer for a block.
217: */
218: void
219: brelease(bp)
220: BUF *bp;
221: {
222: } /* brelease() */
223: /*
224: * Attempt to lock the gate 'g'.
225: * Return TRUE on success, FALSE if it was already locked.
226: */
227: int
228: gate_lock(g)
229: GATE g;
230: {
231: } /* gate_lock() */
232: /*
233: * Check to see if the gate 'g' is locked.
234: */
235: int
236: gate_locked(g)
237: GATE g;
238: {
239: } /* gate_locked() */
240: /*
241: * Unlock the gate 'g'.
242: */
243: void
244: gate_unlock(g)
245: GATE g;
246: {
247: } /* gate_unlock() */
248: /*
249: * Sanity checker.
250: * Prints contents of "message" if something is amiss and dumps you
251: * into the monitor.
252: *
253: * Add tests and messages as needed.
254: */
255: void
256: sanity_check(message)
257: char *message;
258: {
259: } /* sanity_check() */
260: ////////
261: /
262: / I/O library for use with boot programs. Uses the BIOS.
263: /
264: / La Monte H. Yarroll <[email protected]>, September 1991
265: /
266: ////////
267: ////////
268: /
269: / Magic constants.
270: /
271: ////////
272: RETF = 0xCB / Far return
273: VIDEO = 0x10 / video swi
274: DISK = 0x13 / disk io swi
275: KEYBD = 0x16 / keyboard swi
276: MON = 0x00 / Monitor swi
277: READ1 = 0x0201 / read 1 sector
278:
279: BUFSIZE = 0x200 / Size of a physical disk block.
280:
281: NTRK = 40 / Number of tracks on a floppy.
282: NSPT = 9 / Number of sectors per track on a floppy.
283: NHD = 1 / Number of heads per drive on a floppy.
284: FIRST = 8 / Relative start of partition.
285: .shri / Shared code segment, initialized.
286: ////////
287: /
288: / Read a block from disk, relative to the start of the boot partition,
289: / using the code in the IBM firmware.
290: /
291: / It takes two parameters:
292: / daddr_t blockno; /* 32 bit block number. */
293: / char *buff; /* Must point to a 512 byte buffer. */
294: /
295: / The buffer must not cross a 4K boundry. Disk input should generally
296: / be done through the C routine bread(), which calls _bread() with an
297: / aligned buffer.
298: /
299: ////////
300: .globl _bread_
301: _bread_:
302: push es / Save registers
303: push si
304: push di
305: push bp
306: push dx
307: push ds
308: pop es / Set es:bp to address of the buffer.
309: mov bp, sp
310: mov ax, 12(bp) / Get low word of block number.
311: mov dx, 14(bp) / Get high word of block number.
312: mov bx, 16(bp) / Get a buffer to put it in.
313: mov bp, bx
314: mov di, bp / Blast the buffer contents.
315: mov cx, $BUFSIZE / For block 0, this fills the buffer
316: rep / with zeros.
317: stosb
318: / Block #0 is the sparse block--it means a block of all zeros.
319: test ax, ax / if block 0, return zeroed buffer
320: jnz 3f
321: test dx, dx
322: jnz 3f
323: movb al, $1 / Say that we read 1 block.
324: jmp 2f
325: / Translate block number into cylinder, head, and sector.
326: 3: add ax, first / add first block
327: adc dx, first+2 / add rest
328: mov bx, ax / save block number
329: movb al, heads / get number of heads
330: movb cl, sects / get number of sectors
331: mulb cl / calculate sectors per cylinder
332: xchg bx,ax / swap block/sectors
333: div bx / calculate track
334: xchg dx, ax / put track in DX
335: divb cl / calculate head/sector
336: movb cl, ah / set sector
337: inc cx / sectors start at 1 [incb cl]
338:
339: cmp dx, traks / check for second side
340: jb 0f
341: sub dx, traks / fold track
342: inc ax / next head [incb al]
343: 0: rorb dh, $1 / rotate track(low) into
344: rorb dh, $1 / msbits of DX
345: orb cl, dh / set track(high)
346: movb ch, dl / set track(low)
347: movb dh, al / set head
348: movb dl, drive / set drive
349: mov bx, bp / set offset [bbuf]
350: mov ax, $READ1 / Read, 1 sector.
351: int DISK / Disk I/O.
352: jnc 2f / Jump if no error.
353: mov ax, $READ1 / try again
354: int DISK
355: jc berror
356: 2:
357: / al contains the number of blocks read (should be 1).
358: pop dx / restore registers.
359: pop bp
360: pop di
361: pop si
362: pop es
363: ret / return.
364: berror: / error handling for _bread.
365: xorb al, al / ah contains an error code.
366: jmp 2b
367: ////////
368: /
369: / Write the character in "al" out to
370: / the display, using routines in the ROM.
371: / Like most calls to the ROM, this routine spends
372: / most of its time saving and restoring the
373: / registers.
374: /
375: ////////
376: .globl putchar_
377: putchar_: push si / Save registers.
378: push di
379: push bp
380: mov bp, sp
381: mov ax, 8(bp) / Fetch the single argument.
382: mov bx, $0x0007 / Page 0, white on black
383: movb ah, $0x0E / Write TTY.
384: int VIDEO / Call video I/O in ROM.
385: pop bp / Restore registers.
386: pop di
387: pop si
388: ret
389: ////////
390: /
391: / Fetch character from keyboard, using
392: / routines in the ROM.
393: /
394: ////////
395: .globl getchar_
396: getchar_:
397: push si / Save registers.
398: push di
399: push bp
400: movb ah, $0x00 / Read keystroke.
401: int KEYBD
402: movb ah, $0x00
403: pop bp / Restore registers.
404: pop di
405: pop si
406: ret
407: ////////
408: /
409: / Check for a pending keystroke using
410: / routines in the ROM.
411: /
412: ////////
413: .globl iskey_
414: iskey_:
415: push si / Save registers.
416: push di
417: push bp
418: movb ah, $0x01 / Check for keystroke.
419: int KEYBD
420: jne 0f
421: xor ax, ax / Set false.
422: jmp 1f
423: 0: xor ax, ax
424: inc ax / Set true.
425: 1: pop bp / Restore registers.
426: pop di
427: pop si
428: ret
429: ////////
430: /
431: / Goto a far address
432: / Takes two integer arguments: an offset, and a segment, in that order.
433: /
434: ////////
435: .globl gotofar_
436: gotofar_:
437: add sp, $2
438: .byte RETF
439: ////////
440: /
441: / Goto a kernel.
442: / Takes three integer arguments: an offset, a segment, and a new data segment
443: / in that order.
444: /
445: ////////
446: .globl gotoker_
447: gotoker_:
448: mov bp, sp
449: mov es, 6(bp) / Point es at the new data segment.
450: mov si, $seconddat / Point ds:si at useful data.
451: add sp, $2
452: .byte RETF
453: ////////
454: /
455: / Initilize hard disk parameters
456: /
457: ////////
458: .globl hdinit_
459: hdinit_:
460: push si / Save registers.
461: push di
462: push bp
463: mov si, bp / set si to partition table
464: movb dl, (si) / get drive number
465: movb ah, $8 / get drive parameters
466: int DISK
467: jc 1f / abort on error (just return)
468: movb al, ch / fetch cyl(lo)
469: movb ah, cl / move cyl(hi), sects
470: rolb ah, $1 / shift cylinder high to
471: rolb ah, $1 / the least sig bits
472: andb ah, $3 / mask out cylinder bits
473: mov di, $traks / point to drive
474: stosw / set number of tracks
475: movb al, $0x3F / sector mask
476: andb al, cl / mask sector
477: stosb / set sector
478: movb al, dh / get max head
479: inc ax / change to # of heads (incb al)
480: stosb / set number of heads
481: movsb / set drive
482: add si, $FIRST-1 / point to first block
483: movsw / fetch first block
484: movsw
485: 1: pop bp / Restore registers.
486: pop di
487: pop si
488: ret
489: ////////
490: /
491: / Invoke the native monitor.
492: / Useful for debugging.
493: /
494: ////////
495: .globl intmon_
496: intmon_:
497: int MON
498: ret
499: ////////
500: /
501: / void _ffcopy(from_fp, to_fp, count)
502: / faddr_t from_fp, to_fp;
503: / int count;
504: /
505: / Copy count bytes from from_fp to to_fp.
506: /
507: / Here is the stack after initial "push bp":
508: /
509: / 12(bp) count
510: / 10(bp) FP_SEL(to_fp)
511: / 8(bp) FP_OFF(to_fp)
512: / 6(bp) FP_SEL(from_fp)
513: / 4(bp) FP_OFF(from_fp)
514: / 2(bp) return IP
515: / 0(bp) old bp
516: /
517: ////////
518: .globl _ffcopy_
519: _ffcopy_:
520: push bp
521: mov bp, sp
522: push es
523: push di
524: push ds
525: push si
526: lds si, 4(bp) / from_fp to DS:SI
527: les di, 8(bp) / to_fp to ES:DI
528: mov cx, 12(bp) / rep count to CX
529: rep
530: movsb
531: pop si
532: pop ds
533: pop di
534: pop es
535: pop bp
536: ret / return from _ffcopy()
537: ////////
538: /
539: / Read a block from disk, relative to start of disk,
540: / using the code in the IBM firmware.
541: /
542: / It takes two parameters:
543: / daddr_t blockno; /* 32 bit block number. */
544: / char *buff; /* Must point to a 512 byte buffer. */
545: /
546: / The buffer must not cross a 4K boundry. Disk input should generally
547: / be done through the C routine xbread(), which calls _xbread() with an
548: / aligned buffer.
549: /
550: ////////
551: .globl _xbread_
552: _xbread_:
553: push es / Save registers
554: push si
555: push di
556: push bp
557: push dx
558: push ds
559: pop es / Set es:bp to address of the buffer.
560: mov bp, sp
561: mov ax, 12(bp) / Get low word of block number.
562: mov dx, 14(bp) / Get high word of block number.
563: mov bx, 16(bp) / Get a buffer to put it in.
564: mov bp, bx
565: / Translate block number into cylinder, head, and sector.
566: 3:
567: mov bx, ax / save block number
568: movb al, heads / get number of heads
569: movb cl, sects / get number of sectors
570: mulb cl / calculate sectors per cylinder
571: xchg bx,ax / swap block/sectors
572: div bx / calculate track
573: xchg dx, ax / put track in DX
574: divb cl / calculate head/sector
575: movb cl, ah / set sector
576: inc cx / sectors start at 1 [incb cl]
577:
578: cmp dx, traks / check for second side
579: jb 0f
580: sub dx, traks / fold track
581: inc ax / next head [incb al]
582: 0: rorb dh, $1 / rotate track(low) into
583: rorb dh, $1 / msbits of DX
584: orb cl, dh / set track(high)
585: movb ch, dl / set track(low)
586: movb dh, al / set head
587: movb dl, drive / set drive
588: mov bx, bp / set offset [bbuf]
589: mov ax, $READ1 / Read, 1 sector.
590: int DISK / Disk I/O.
591: jnc 2f / Jump if no error.
592: mov ax, $READ1 / try again
593: int DISK
594: jc berror
595: 2:
596: / al contains the number of blocks read (should be 1).
597: pop dx / restore registers.
598: pop bp
599: pop di
600: pop si
601: pop es
602: ret / return.
603: /* builtin.c -- builtin routines for tboot.
604: *
605: * Add new ones by adding a check for them in interpret().
606: *
607: * La Monte H. Yarroll <[email protected]>, September 1991
608: */
609: extern int slow_flag; /* Slow down pacifier. */
610: extern int feet_flag; /* Enable pacifier footprints. */
611: /* If possible, execute "command".
612: * Return "true" if the command exists, "false" otherwise.
613: */
614: int
615: interpret(command)
616: char *command;
617: {
618: } /* interpret() */
619: /* Display the BIOS parameters loaded up by the startup code. */
620: void
621: dpb()
622: {
623: } /* dpb() */
624: /* Ask the BIOS how many drives are attached. */
625: int get_num_of_drives()
626: {
627: } /* get_num_of_drives() */
628: /* Create a listing of file names in /. */
629: void
630: dir()
631: {
632: } /* dir() */
633: /* cbootlib.c -- C routines for use by boot programs.
634: *
635: * La Monte H. Yarroll <[email protected]>, September 1991
636: */
637: /* puts() -- put a NUL terminated string.
638: * Takes one argument--a pointer to a NUL terminated character string.
639: * Does no error checking. Calls the assembly language routine putc().
640: */
641: void
642: puts(s)
643: register char *s;
644: {
645: } /* puts() */
646: /* gets() -- Read string from keyboard.
647: * Takes one argument--a pointer to a buffer big enough for the
648: * expected response.
649: * It stops reading as soon as it detects a carriage return. The CR
650: * is replaced with a NUL.
651: */
652: char *
653: gets(s)
654: char *s;
655: {
656: } /* gets() */
657: /* Reverse string s in place.
658: * Straight from K&R.
659: */
660: void
661: reverse(s)
662: char s[];
663: {
664: } /* reverse() */
665: /* Convert n to decimal characters in s.
666: * Straight from K&R (with minor sylistic changes.)
667: */
668: void
669: itoa(n, s)
670: char s[];
671: int n;
672: {
673: } /* itoa() */
674: /* Convert n to digits in s, base base.
675: * Works for any base from 2 to 36.
676: * Modified itoa() from K&R.
677: */
678: void
679: itobase(n, s, base)
680: uint16 n;
681: char s[];
682: int base;
683: {
684: } /* itobase() */
685: /* basetoi(char *s, int base)
686: * Convert a string base "base" to an integer.
687: * Good through base 36.
688: * Loosely based on K&R's atoi().
689: */
690: uint16
691: basetoi(s, base)
692: char *s;
693: int base;
694: {
695: } /* basetoi() */
696: /* seginc(uint16 *offset,
697: * uint16 *segment,
698: * uint16 increment)
699: * Add an offset to a segment. We may adjust the segment base
700: * to make everything fit.
701: */
702: * segments are PP aligned.
703: */
704:
705: void
706: seginc(offset, segment, increment)
707: uint16 *offset;
708: uint16 *segment;
709: uint16 increment;
710: {
711: } /* seginc() */
712: /* Pad a string s on the left with character c, to length n.
713: * The old contents of s are replaced by the padded version.
714: */
715: char *
716: lpad(s, c, n)
717: char *s;
718: char c;
719: int n;
720: {
721: } /* lpad() */
722: /*
723: * Print a 32 bit integer in hexadecimal.
724: */
725: void
726: print32(my_int)
727: uint32 my_int;
728: {
729: }
730: /*
731: * Print a 16 bit integer in hexadecimal.
732: */
733: void
734: print16(my_int)
735: uint16 my_int;
736: {
737: }
738: /*
739: * Print an 8 bit integer in hexadecimal.
740: */
741: void
742: print8(my_int)
743: uint8 my_int;
744: {
745: }
746: /*
747: * Wrapper for far-far copy. Changes the segment so that the requested
748: * length does not wrap past the end of the segment.
749: *
750: * For Intel 8086 Real Mode.
751: */
752: void
753: ffcopy(to_offset, to_seg, from_offset, from_seg, length)
754: uint16 to_offset;
755: uint16 to_seg;
756: uint16 from_offset;
757: uint16 from_seg;
758: uint16 length;
759: {
760: } /* ffcopy() */
761: /*
762: * Align a far address so that its offset is within a paragraph of
763: * the start of the segment.
764: *
765: * Note that we ignore overflow in the segment, since this is exactly
766: * what happens when you offset past the end of the highest segment.
767: *
768: * WARNING: This routine is destructive to its arguments.
769: *
770: * For Intel 8086 Real Mode.
771: */
772: void
773: seg_align(offset, segment)
774: uint16 *offset;
775: uint16 *segment;
776: {
777: } /* seg_align() */
778: /*
779: * wait_for_keystroke() -- wait for a specific keystroke.
780: */
781: /* Location of BIOS-run timer. */
782: /*
783: * Waits delay ticks for the requested keystroke. Returns TRUE if
784: * keystroke came, FALSE if delay runs out.
785: * If key == -1, accept ANY keystroke.
786: */
787: int
788: wait_for_keystroke(delay, key)
789: int delay;
790: int key;
791: {
792: } /* wait_for_keystrok() */
793: /* coff.c -- rutines for manipulating coff executable files. */
794: /* Convert COFF to load table.
795: * Used to generate loading instructions for use by tboot main().
796: * Returns true on successful translation.
797: */
798: int
799: coff2load(ip, table, data_seg)
800: struct inode *ip; /* input: File to read. */
801: struct load_segment table[]; /* output: How to read it. */
802: uint16 *data_seg; /* output: Where to point es. */
803: {
804: }
805: /*
806: * Symbol name.
807: */
808: static char *
809: symName(sym, str_tab, work)
810: SYMENT *sym;
811: char *str_tab, *work;
812: {
813: }
814: /*
815: * Look up the value of a single data symbol in a coff file,
816: * relative to the start of the data segment.
817: *
818: * We use the symbol "sdata" to find the start of the data segment--
819: * this works for 386 COHERENT kernels but will not work in general.
820: * It should really fetch the address of the start of the data segment
821: * from the data section header.
822: */
823: uint32
824: wrap_coffnlist(fn, symbol)
825: char *fn; /* file name */
826: char *symbol; /* symbol to look up */
827: {
828: } /* wrap_coffnlist() */
829: int
830: coffnlist(fn, nlp, names, count)
831: char *fn; /* file name */
832: SYMENT *nlp; /* names to look up */
833: char *names; /* long names */
834: int count; /* size of passed table */
835: {
836: }
837: main()
838: {
839: }
840: /* diskio.c -- C routines for disk i/o in tertiary boot programs.
841: *
842: * La Monte H. Yarroll <[email protected]>, September 1991
843: */
844: /* Aligning bread.
845: * Reads 1 block into an arbitrary buffer. The assembly language
846: * routine bread() needs a buffer aligned on a 4K boundary.
847: */
848: char bufspace[FOURK+BLOCK];
849: char *lbuf = NULL; /* Buffer for bread. */
850: BUF *
851: bread(blockno)
852: daddr_t blockno; /* Block number. */
853: {
854: } /* bread() */
855: /*
856: * Inode OPEN: Load the inode for a file into memory.
857: * iopen(struct inode *ip,
858: * ino_t inode_number)
859: *
860: */
861: int
862: iopen(meminode, inode_number)
863: struct inode *meminode;
864: ino_t inode_number;
865: {
866: } /* iopen() */
867: /* Convert a filename to an inode number. Returns inode number 0 on
868: * failure.
869: */
870: ino_t
871: namei(filename)
872: char *filename;
873: {
874: } /* namei() */
875: /*
876: * Inode READ: Load a local buffer from a file.
877: * iread(struct inode *ip,
878: * char *buffer,
879: * fsize_t offset,
880: * uint16 lenarg);
881: */
882: void
883: iread(ip, buffer, offset, lenarg)
884: struct inode *ip; /* Read from this file, */
885: char *buffer; /* into this buffer, */
886: fsize_t offset; /* from here in the file, */
887: uint16 lenarg; /* for this many bytes. */
888: {
889: } /* iread() */
890: /*
891: * Inode to Far READ: Load an arbitrary length from a file into a far address.
892: * ifread(struct inode *ip,
893: * uint16 toseg,
894: * uint16 tooffset,
895: * fsize_t offset,
896: * fsize_t length);
897: */
898: void
899: ifread(ip, toseg, tooffset, offset, lenarg)
900: struct inode *ip; /* Read from this file, */
901: uint16 toseg; /* into this far buffer, */
902: uint16 tooffset;
903: fsize_t offset; /* from here in the file, */
904: fsize_t lenarg; /* for this many bytes. */
905: {
906: } /* ifread() */
907: /* Aligning xbread.
908: * Disk addresses are relative to the start of the disk, rather than
909: * the start of the partition.
910: * Reads 1 block into an arbitrary buffer. The assembly language
911: * routine xbread() needs a buffer aligned on a 4K boundary.
912: */
913: BUF *
914: xbread(blockno)
915: daddr_t blockno; /* Block number. */
916: {
917: } /* xbread() */
918: /*
919: *
920: * fdisk( fp ) -- Fixed Disk Configuration
921: * dev_t dev;
922: * struct fdisk_s *fp;
923: *
924: * Input: fp = pointer to memory-resident partition info (to update)
925: *
926: * Action: Read first block from the device.
927: * If valid signature present on block,
928: * copy partition information to memory
929: *
930: * Return: 1 = partition information successfully updated
931: * 0 = failure (could not read block, or bad signature)
932: */
933: int
934: fdisk( fp )
935: register FDISK_S *fp;
936: {
937: }
938: /*
939: * fifo_b.c -- Extra routines for handling typed fifos.
940: * Both fifo_b.c (boot fifo) and fifo_k.c (kernel fifo) are needed by the
941: * boot code.
942: */
943: /* How long is an open fifo? */
944: long
945: fifo_len(ffp)
946: FIFO *ffp;
947: {
948: } /* fifo_len() */
949: /* Write a typed space into a FIFO. */
950: typed_space *
951: fifo_write(ffp, space)
952: FIFO *ffp;
953: typed_space *space;
954: {
955: } /* fifo_write() */
956: /* Write a chunk of data into an open fifo as a typed space.
957: * Takes a FIFO to be written to, ffp; a pointer to the data, datum; a
958: * size for the datum, size; and a type for the new space, type.
959: *
960: * Returns a pointer to the newly written space. Returns NULL if the
961: * new space could not be written.
962: *
963: * Note that while sizes throughout this package refer to TOTAL sizes
964: * including headers, the size argument here is ONLY for the datum.
965: *
966: * Only FIFOs of type T_FIFO_SIC are implimented.
967: */
968: typed_space *
969: fifo_write_untyped(ffp, datum, size, type)
970: FIFO *ffp;
971: char *datum;
972: long size;
973: space_type type;
974: {
975: } /* fifo_write_untyped() */
976: /*
977: * fifo_k.c -- Routines for reading interally typed fifos.
978: * These are all that need to be included in the kernel.
979: */
980: /* The input channel from tboot to the kernel. */
981: TYPED_SPACE(boot_gift, 512, T_FIFO_SIC);
982: /* Read a typed space from a fifo.
983: * Return a pointer to the next typed space in the fifo ffp. Returns
984: * NULL on end of fifo.
985: *
986: * This read assumes that ffp->f_space has type T_FIFO_SIC.
987: */
988: typed_space *
989: fifo_read(ffp)
990: register FIFO *ffp;
991: {
992: } /* fifo_read() */
993: /* Go back to the start of the fifo.
994: * Takes a FIFO. For reading, go back to the first space; for writing
995: * truncate the FIFO to empty.
996: * Returns 1 on success, 0 otherwise.
997: */
998: int
999: fifo_rewind(ffp)
1000: FIFO *ffp;
1001: {
1002: } /* fifo_rewind() */
1003: /* Finish with using a typed space as a fifo.
1004: * Free up FIFO structure associated with a typed space.
1005: * Returns 0 if ffp was not open, 1 otherwise.
1006: */
1007: int
1008: fifo_close(ffp)
1009: FIFO *ffp;
1010: {
1011: } /* fifo_close() */
1012: /* Open a typed space as a fifo.
1013: *
1014: * Takes a typed_space that is already allocated, and a mode. The type of
1015: * the typed space must be a FIFO. Only T_FIFO_SIC has been implimented
1016: * (static, in-core fifo).
1017: *
1018: * The mode indicates whether to open for reading or writing.
1019: * mode == 0 means read only.
1020: * mode == 1 means write only.
1021: * Other values are illegal.
1022: *
1023: * Returns a pointer to an initialized FIFO structure. FIFO structures are
1024: * allocated from a pre-allocated array. Returns F_NULL if it can't open
1025: * the fifo.
1026: */
1027: FIFO *
1028: fifo_open(fifo_space, mode)
1029: typed_space *fifo_space;
1030: int mode;
1031: {
1032: } /* fifo_open() */
1033: /* This is the typed space we will use for our FIFO operations. */
1034: TYPED_SPACE(global_space, 128, T_FIFO_SIC); /* Static In-Core Fifo. */
1035: int
1036: main()
1037: {
1038: } /* main() */
1039: /* gift.c -- Prepare a gift of information for the program currently loaded.
1040: *
1041: * To pass a new data structure into the kernel:
1042: *
1043: * 1. Define your new data structure in typed.h. You will probably want
1044: * to define some supporting routines for your data structure. These
1045: * should go in a file by themselves. Be sure to add the file to the
1046: * tboot Makefile.
1047: *
1048: * 2. Write a routine that takes at least an ffp, which will generate your
1049: * data structure and write it into the ffp. The routine should return 0
1050: * if it ran out of space in the FIFO. Other return values are permissible,
1051: * but ignored. Add arguments to prepare_gift() as needed. It is called
1052: * only from the end of main() in tboot.c
1053: *
1054: * 3. Add a call to your routine to prepare_gift() in the section marked
1055: * FILL THE BOX. This is an if statement with || seperated calls. The
1056: * most important data structures should be called first, because later
1057: * calls will be skipped if the FIFO fills.
1058: *
1059: * 4. In the kernel (probably in a driver) you will want to add a loop to
1060: * look through the gift for your data structure:
1061: *
1062: * FIFO *ffp;
1063: * typed_space *tp;
1064: *
1065: * ffp = fifo_open(&boot_gift, 0); -- Open gift for reading.
1066: *
1067: * if (F_NULL == ffp) {
1068: * indicate_error("Could not open boot_gift.");
1069: * } else {
1070: * while (T_NULL != (tp = fifo_read(ffp))) { -- While not EOFIFO.
1071: * if (T_MYTYPE == tp->ts_type) { -- Is this my type?
1072: * my_handler(tp->ts_data); -- Process the data.
1073: * }
1074: * }
1075: * }
1076: *
1077: * Be sure to include fifo.c and typed.h into your kernel.
1078: *
1079: */
1080: /* We have to build the gift in the local segment and then copy it in
1081: * place. In a better world, the gift could be built in place.
1082: */
1083: TYPED_SPACE(local_gift, GIFTBOX, T_FIFO_SIC); /* Static In-Core Fifo. */
1084: /* Prepare a gift of information for the program currently loaded.
1085: *
1086: * The gift is a Static In-Core FIFO whose objects are typed spaces.
1087: *
1088: * cmd_line is the command line needby by gift_argf().
1089: *
1090: * It should be placed in memory at data_seg:offset.
1091: */
1092: void
1093: prepare_gift(data_seg, offset, cmd_line)
1094: uint16 data_seg;
1095: uint16 offset;
1096: char *cmd_line;
1097: {
1098: } /* prepare_gift() */
1099: /* Load the BIOS parameters loaded up by the startup code. */
1100: int
1101: gift_drive_params(ffp)
1102: FIFO *ffp;
1103: {
1104: } /* gift_drive_params() */
1105: /* We'd really rather have a dynamic in-core fifo, but they are not
1106: * yet implimented. We'll have to settle for a fixed length argument list.
1107: */
1108: TYPED_SPACE(argf, BLOCK, T_FIFO_SIC);
1109: /*
1110: * To read this item from bootgift, use the procedure outlined above in
1111: * point 4 to find the entry marked T_STR_ARGF. You must then explicitly
1112: * recast it with RETYPE(tp->ts_data, T_FIFO_SIC). Then you can open it
1113: * as a FIFO, with code modeled on point 4 above. This scheme seemed
1114: * the simplest for uniquely identifying the argument FIFO.
1115: * Each element of the FIFO is a T_STR_STR, so ts_data for these is
1116: * just a NUL terminated string. You can a
1117: */
1118: /* Write an argument fifo into ffp from the command line cmd_line.
1119: * Returns 0 if it runs out of space, 1 on success, and 2 if something else
1120: * goes wrong.
1121: */
1122: int
1123: gift_argf(ffp, cmd_line)
1124: FIFO *ffp;
1125: char *cmd_line;
1126: {
1127: } /* gift_argf() */
1128: /* Write a structure describing the boot partition into a fifo.
1129: * Returns 1 on success, 0 if it runs out of space, or 2 if it
1130: * can't read the boot block.
1131: */
1132: int
1133: gift_rootdev(ffp)
1134: FIFO *ffp;
1135: {
1136: } /* gift_rootdev() */
1137: /* Dump the contents of boot_gift. */
1138: void
1139: dump_gift()
1140: {
1141: }
1142: /* Dump the contents of a fifo. */
1143: void
1144: dump_fifo(fifo)
1145: typed_space *fifo;
1146: {
1147: } /* dump_gift() */
1148: /* Dump a T_BIOS_DISK typed_space. */
1149: void
1150: dump_bios_disk(a_disk)
1151: BIOS_DISK *a_disk;
1152: {
1153: } /* dump_bios_disk() */
1154: /* Dump a T_BIOS_ROOTDEV typed_space. */
1155: void
1156: dump_rootdev(a_rootdev)
1157: BIOS_ROOTDEV *a_rootdev;
1158: {
1159: } /* dump_rootdev() */
1160: /*
1161: * Handle the indirections in Unix-style file system.
1162: *
1163: * Uses a recursive scheme to follow up indirections.
1164: *
1165: * Needs optimization. A good place to start would be caching of
1166: * lookup tables.
1167: *
1168: * La Monte H. Yarroll <[email protected]>, September 1991
1169: */
1170: extern BUF *bread();
1171: daddr_t vmap();
1172: daddr_t indirect();
1173: daddr_t ind_lookup();
1174: uint16 ind_index();
1175: /* Convert the given virtual block to a physical block for the given inode.
1176: * ip points to the in-core inode for a file.
1177: * vblockno is a block number relative to the start of that file.
1178: */
1179: daddr_t
1180: vmap(ip, vblockno)
1181: struct inode *ip;
1182: daddr_t vblockno;
1183: {
1184: } /* vmap() */
1185: /* indirect(uint16 ind_level, daddr_t ind_table_ptr, daddr_t vblockno)
1186: * Recursively follow an indirection for a given virtual block number
1187: * vblockno.
1188: * ind_level must be the level of indirection still un-resolved.
1189: * ind_table is the physical block number of the next indirection.
1190: */
1191: daddr_t
1192: indirect(ind_level, ind_table_ptr, vblockno)
1193: uint16 ind_level;
1194: daddr_t ind_table_ptr;
1195: daddr_t vblockno;
1196: {
1197: } /* indirect() */
1198: /* ind_lookup(uint16 ind_level, daddr_t *ind_table, daddr_t vblockno)
1199: * Look up the next level of block in table ind_table, for virtual
1200: * block number vblockno.
1201: * Note that this table is in DISK CANNONICAL format. If the local
1202: * notion of daddr_t is a different size from DISK CANONICAL daddr_t
1203: */
1204: daddr_t
1205: ind_lookup(ind_level, ind_table, vblockno)
1206: uint16 ind_level;
1207: daddr_t *ind_table;
1208: daddr_t vblockno;
1209: {
1210: }
1211: /* uint16 ind_index(uint16 ind_level, daddr_t vblockno);
1212: * Calculate the index needed for virtual block vblockno into
1213: * a table of the given indirection level.
1214: */
1215: * NBN = 128 entries = 7 bit address.
1216: */
1217: uint16
1218: ind_index(ind_level, vblockno)
1219: uint16 ind_level;
1220: daddr_t vblockno;
1221: {}
1222: //////////
1223: / From MSDOS MWC86 system call interface.
1224: / Interrupt simulation.
1225: / Modified for use with tertiary boot code for COHERENT.
1226: /
1227: / Modified September 1991 by La Monte H. Yarroll <[email protected]>
1228: /
1229: / DANGER!! THIS IS SELF MODIFYING CODE. IT WILL ONLY WORK IN A STRICTLY
1230: / SINGLE THREADED ENVIRONMENT.
1231: //////////
1232: //////////
1233: / void
1234: / intcall(src, dest, intnum)
1235: / struct reg *src; /* All regs are loaded except flags */
1236: / struct reg *dest; /* All regs are stored here */
1237: / int intnum; /* Int number */
1238: //////////
1239: src = 6+RASIZE
1240: dest = src+PTRSIZE
1241: intnum = dest+PTRSIZE
1242: .globl intcall_
1243: intcall_:
1244: push si / Save register variables.
1245: push di
1246: push bp
1247: mov bp, sp
1248: movb al, intnum(bp) / Get intnum in AL
1249: movb cs:myint+1, al / Modify the code
1250: Lds si, src(bp) / Load DS:SI with src pointer.
1251: mov ax, (si) / Set AX
1252: mov bx, 2(si) / and BX
1253: mov cx, 4(si) / and CX
1254: mov dx, 6(si) / and DX
1255: mov di, 10(si) / and DI,
1256: push 12(si) / save src DS,
1257: mov es, 14(si) / set ES
1258: mov si, 8(si) / and SI
1259: pop ds / and DS.
1260: / Actually do the interrupt.
1261: myint: int 0 / This instruction gets modified.
1262: / The interrupt handler preserves SS:SP.
1263: / The iret to the handler pops the handler address and flags pushed above,
1264: / the iret from the handler pops the retint address and flags.
1265: retint:
1266: mov bp, sp / Restore BP.
1267: pushf / Save result flags
1268: push es / and ES
1269: push ds / and DS
1270: push si / and SI.
1271: mov si, ss
1272: mov ds, si / Restore DS
1273: mov es, si / and ES.
1274: Lds si, dest(bp) / Get dest in DS:SI.
1275: mov (si), ax / Load dest with returned AX
1276: mov 2(si), bx / and BX
1277: mov 4(si), cx / and CX
1278: mov 6(si), dx / and DX
1279: pop 8(si) / and SI
1280: mov 10(si), di / and DI
1281: pop 12(si) / and DS
1282: pop 14(si) / and ES
1283: pop 16(si) / and flags.
1284: pop bp
1285: pop di
1286: pop si
1287: Gret
1288: / end of intcall.m
1289: /* l.out.c -- routines for manipulating l.out executable files. */
1290: /* Convert l.out to load table.
1291: * Used to generate loading instructions for use by tboot main().
1292: * Returns true on successful translation.
1293: */
1294: int
1295: lout2load(ip, table, data_seg)
1296: struct inode *ip; /* input: File to read. */
1297: struct load_segment table[]; /* output: How to read it. */
1298: uint16 *data_seg; /* output: Where to point es. */
1299: {
1300: }
1301: /*
1302: * Get entries from l.out name list.
1303: */
1304: void
1305: l_out_nlist(fn, nlp)
1306: char *fn;
1307: struct nlist *nlp;
1308: {
1309: }
1310: /* Mini-monitor for testing boot code.
1311: *
1312: * La Monte H. Yarroll <[email protected]>, September 1991
1313: */
1314: void
1315: monitor()
1316: {
1317: }
1318: /* objects.c -- routines for handling different object formats.
1319: * Currently, only COFF and COHERENT l.out are supported.
1320: */
1321: /* Extract information from an object file that describes how to
1322: * load an executable.
1323: * The magic number of the file is in "magic".
1324: * The object file's inode is in "ip".
1325: *
1326: * The information needed is extracted into "table".
1327: * The value for the data segment is put in "data_seg".
1328: *
1329: * Returns TRUE if the needed information could be extracted, FALSE ow.
1330: */
1331: int
1332: object2load(magic, ip, table, data_seg)
1333: uint16 magic;
1334: struct inode *ip;
1335: struct load_segment table[];
1336: uint16 *data_seg;
1337: {
1338: } /* object2load() */
1339: /* Look up symbol(s) in an object file.
1340: * searches the name list (symbol table) of the load module
1341: * "filename" for each symbol in the array pointed to by "nlp".
1342: *
1343: * nlp points to an array of nlist structures, terminated by a
1344: * structure with a null string as its n_name member.
1345: *
1346: * If "filename" is not a load module or has had its symbol table
1347: * stripped, all returned n_type and n_value entries will be zero.
1348: *
1349: */
1350: uint16
1351: object_nlist(magic, filename, symbol)
1352: uint16 magic;
1353: char *filename;
1354: char *symbol;
1355: {
1356: } /* object_nlist() */
1357: /* Determine the value for sys_base based on the type of the load file. */
1358: uint16
1359: object_sys_base(magic)
1360: int magic;
1361: {
1362: } /* object_sys_base() */
1363: main()
1364: {
1365: } /* main () */
1366: /*
1367: * pacifier.c - state machine for putting something interesting on the screen.
1368: */
1369: int slow_flag = FALSE; /* Slow down pacifier. */
1370: int feet_flag = FALSE; /* Print footprints? */
1371: void pac_init(); /* Initialise the state machine. */
1372: void pac_cleanup(); /* Clean up after the state machine. */
1373: void pacifier(); /* Run the next step of the state machine. */
1374: void subliminal(); /* Print a subliminal message. */
1375: static int pac_inited = FALSE; /* Has pac_init() been called? */
1376: static int pac_dirty = FALSE; /* Has pacifier() been called? */
1377: static int state;
1378: static int substate;
1379: static int count;
1380: void
1381: pacifier()
1382: {
1383: } /* pacifier() */
1384: /*
1385: * Print a subliminal message on the console.
1386: * It does this by printing the message, backspacing over it,
1387: * spacing over it, and the backspacing again.
1388: */
1389: void
1390: subliminal(msg)
1391: char *msg;
1392: {
1393: } /* subliminal() */
1394: /*
1395: * Initialize the pacifier state machine.
1396: */
1397: void
1398: pac_init()
1399: {
1400: } /* pac_init() */
1401: /*
1402: * Clean up the screen after the pacifier.
1403: */
1404: void
1405: pac_cleanup()
1406: {
1407: } /* pac_cleanup() */
1408: /* sys.c -- Simulate kernel calls for file i/o.
1409: */
1410: int errno;
1411: /* Table of file descriptors. */
1412: static FD u_filep[NUFILE];
1413: static struct inode ip_table[NUFILE];
1414: static inited = (1==2);
1415: /* Open a file.
1416: * Takes a file name, file; and a way of opening it, type as follows:
1417: * 0 Read only
1418: * 1 Write
1419: * 2 Read and write
1420: * Only read is implimented.
1421: *
1422: * Returns a file descriptor, or -1 if the open failed.
1423: */
1424: int
1425: open(file, type)
1426: char *file;
1427: int type;
1428: {
1429: } /* open() */
1430: /* Read from a file.
1431: * Takes a file descriptor, a buffer, and a length to read.
1432: *
1433: * Returns the number of characters read, or -1 if an error occurs.
1434: */
1435: int
1436: read(fd, buffer, n)
1437: int fd;
1438: char *buffer;
1439: int n;
1440: {
1441: } /* read() */
1442: /* Close a file.
1443: * Takes a file descriptor.
1444: */
1445: int
1446: close(fd)
1447: int fd;
1448: {
1449: } /* close() */
1450: /* Set a read/write position.
1451: * Changes the seek position for file descriptor fd.
1452: * where and how describe the new seek position. where gives the
1453: * number of bytes that you wish to move the seek position; it is
1454: * measured from the beginning of the file if how is zero, from the
1455: * current seek position if how is one, or from the end of the file
1456: * if how is two. A successful call to lseek returns the new seek
1457: * position; a failure returns (int32) -1.
1458: */
1459: long
1460: lseek(fd, where, how)
1461: int fd;
1462: long where;
1463: int how;
1464: {
1465: } /* lseek() */
1466: /* tboot.c -- tertiary boot
1467: * This is invoked by the secondary boot to do all the things we can't
1468: * do in just 512 bytes.
1469: *
1470: * Includes an interpreter for builtin commands. Just type "info" or "dir"
1471: * to get disk information, or a directory listing of "/".
1472: *
1473: * Can load an image up to 1 gigabyte in length. Segments can be as
1474: * big as the whole file.
1475: *
1476: * La Monte H. Yarroll <[email protected]>, September 1991
1477: */
1478: /* Potentially communicated information from an earlier tboot. */
1479: TYPED_SPACE(boot_gift, 8192, T_FIFO_SIC); /* Static In-Core FIFO. */
1480: main()
1481: {
1482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.