home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 02 / 386bsd.feb next >
Text File  |  1990-12-26  |  26KB  |  766 lines

  1. _PORTING UNIX TO THE 386: THREE INITIAL PC UTILITIES_
  2. by William F. Jolitz and Lynne G. Jolitz
  3.  
  4. [LISTING ONE]
  5.  
  6. /* Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  7.  * Written by William Jolitz 7/89
  8.  * Redistribution and use in source and binary forms are freely permitted
  9.  * provided that the above copyright notice and attribution and date of work
  10.  * and this paragraph are duplicated in all such forms.
  11.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  12.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  13.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  14.  * This program allows the bootstrap load of GCC cross compiled
  15.  * 32 bit protected mode absolute programs onto the obtuse architecture
  16.  * of PC AT/386, destroying the running DOS in the process.
  17.  * Currently works with TURBO C 1.5 & MASM 5.0, relies on farmalloc().
  18.  */
  19.  
  20. #pragma inline
  21. #include <io.h>
  22. #include <fcntl.h>
  23. #include <alloc.h>
  24. #include <dos.h>
  25. #include <sys\stat.h>
  26. #include "exec.h"
  27.  
  28. #define PGSIZE  4096
  29. #define CLOFSET (PGSIZE - 1)      /* 386 page roundup */
  30.  
  31. /* Header record of BSD UNIX executable file */
  32. struct exec exec;
  33.  
  34. long far_read(), to_long();
  35. char far *to_far();
  36. char far *add_to_far(char far *p, long n);
  37.  
  38. /* Get a file we can open, attempt to load it */
  39. main(argc, argv)
  40. char *argv[];
  41. {    int fd, i;
  42.         long addr, totalsz;
  43.     char far *base;
  44.  
  45.     if (argc != 2) {
  46.         printf("usage: boot <filename>\n");
  47.         exit(1);
  48.     }
  49.     fd = open(argv[1], O_BINARY);
  50.     if (fd < 0) {
  51.             printf("boot: Cannot open file \"%s\" \n", argv[1]);
  52.            exit(1);
  53.     }
  54.  
  55.     /* Reasonable file to load? */
  56.     i = read(fd, (char *)&exec, sizeof exec);
  57.     if (i != sizeof exec ||
  58.         (exec.a_magic != OMAGIC && exec.a_magic != NMAGIC
  59.               && exec.a_magic != ZMAGIC)) {
  60.               printf("Not a recognized object file format\n");
  61.               exit(1);
  62.     }
  63.  
  64.         /* Allocate buffer for temporary copy of protected mode executable
  65.         Buffer space requirements: |<--a.out------------>| pageroundup heap */
  66.         totalsz = exec.a_text + exec.a_data + exec.a_bss + 4096L + 20*1024L;
  67.  
  68.         /* Pad with trailing portion to put protected mode entry code in */
  69.     base = farmalloc(totalsz + 64*1024L);
  70.     if (base == 0) {
  71.           printf("Cannot allocate enough memory\n");
  72.           exit(1);
  73.     }
  74.         /* Load Instruction (e.g. text) portion of file */
  75.     printf("Text %ld", exec.a_text);
  76.     if (far_read(fd, base, exec.a_text) != exec.a_text)
  77.             goto eof;
  78.         /* Load Data portion of file */
  79.     addr = exec.a_text;
  80.  
  81.         /* Adjust for page alignment for pure procedure format */
  82.     if (exec.a_magic == NMAGIC && (addr & (PGSIZE-1)))
  83.             while (addr & CLOFSET)
  84.               * add_to_far(base, addr++) = 0;
  85.     printf("\nData %ld", exec.a_data);
  86.     if (far_read(fd, add_to_far(base,addr), exec.a_data) != exec.a_data)
  87.           goto eof;
  88.         /*  Clear Uninitialized data (BSS) space */
  89.     addr += exec.a_data;
  90.     printf("\nBss %ld", exec.a_bss);
  91.     for ( ; addr < totalsz; )
  92.          * add_to_far(base,addr++) = 0;
  93.         if(exec.a_entry)
  94.             printf("\nStart 0x%lx", exec.a_entry);
  95. #ifdef  CKSUM
  96.  
  97.     /* Optionally calculate checksum to validate against cross host's copy. */
  98.         far_cksum(base, addr-1L);
  99. #endif  CKSUM
  100.  
  101.         printf("\n");
  102.  
  103.         /* Effect copydown to absolute 0 and entry into protected mode at 
  104.         location "a_entry". */
  105.         transfer(base, totalsz, exec.a_entry);
  106.         /* NOTREACHED */
  107. eof:
  108.         printf(" - File incomplete, load aborted\n");
  109.         exit(1);
  110. }
  111.  
  112. /* We use the routines below to always keep far pointers normalized
  113.  * to simplify comparision/subtraction. */
  114. char far *to_far(l) long l; {
  115.         unsigned seg, offs;
  116.         seg = l>>4;
  117.         offs = l & 0xf;
  118.         return(MK_FP(seg,offs));
  119. }
  120.  
  121. long to_long(f) char far *f; {
  122.         unsigned long l;
  123.         l = FP_SEG(f)*16L + (unsigned long)FP_OFF(f);
  124.         return(l);
  125. }
  126.  
  127. char far *add_to_far(f,l) char far *f; long l; {
  128.         return(to_far(to_long(f)+l));
  129. }
  130.  
  131. char far *normalize(f) char far *f; {
  132.         unsigned seg,offs ;
  133.  
  134.         /* add in offset */
  135.         seg =  FP_SEG(f); offs =  FP_OFF(f);
  136.         seg += (offs >> 4) ; offs &= 0xf ;
  137.         return(MK_FP (seg, offs));
  138. }
  139.  
  140. /* read() that works anywhere in DOS address space for any size data,
  141.  * works via bounce buffer. Not designed for speed or elegance.  */
  142. long far_read(io, base, len) int io; long len; char far *base; {
  143.         char far *fp;
  144.  
  145.         /* normalize far pointer to handle segment rollover case */
  146.         fp = base = normalize(base);
  147.         while (len) {
  148.                 static char dbuf[PGSIZE];
  149.                 long rlen,tlen;
  150.  
  151.                 /* bounce buffer between my data segment and ultimate dest */
  152.                 tlen = (len > PGSIZE)? PGSIZE : len;
  153.                 if ((rlen = read (io, dbuf, tlen)) < 0) return (rlen);
  154.  
  155.                 /* shoot into place */
  156.                 movedata (_DS, (unsigned)dbuf, FP_SEG(fp), FP_OFF(fp), rlen);
  157.  
  158.                 /* update transfer address and count */
  159.                 fp = add_to_far(fp, rlen);
  160.                 len -= rlen ;
  161.                 if (tlen != rlen) break ;
  162.         }
  163.         return (to_long(fp) - to_long(base));
  164. }
  165.  
  166. extern far protentry(); /* known to be less than 0x200 bytes long */
  167. extern far gatea20();
  168.  
  169. /* set up to transfer to 386 program; call protentry to do the dirty work.  */
  170. transfer(base, len, entry) char far *base; long len, entry; {
  171.         unsigned seg,offs ;
  172.         long rbase;
  173.         char far *fp;
  174.  
  175.          /* Copy code to top of the system and execute there. This keeps it 
  176.              from getting stepped on. */
  177.         /* make 32 bit address */
  178.         rbase = to_long(base);
  179.         fp = add_to_far(base,len);
  180.         seg =  FP_SEG(fp); offs =  FP_OFF(fp);
  181.  
  182.      /* protect possible conflict of top paragraph of bss */
  183.      if (offs) seg++ ;
  184.  
  185.      /* force to protentry's offset so offsets agree */
  186.      offs =  FP_OFF(&protentry);
  187.      movedata (FP_SEG(&protentry), offs, seg, offs, PGSIZE);
  188.  
  189.     /* degate A20 - from now on, full physical memory address bus */
  190.     gatea20();
  191.  
  192.     /* enter prot_entry program, relocated to top of loaded program, via 
  193.     intersegment return */
  194.     asm push word ptr rbase+2 ;
  195.     asm push word ptr rbase ;
  196.     asm push word ptr len+2 ;
  197.     asm push word ptr len ;
  198.     asm push word ptr entry+2 ;
  199.     asm push word ptr entry ;
  200.     asm push word ptr seg;
  201.     asm push word ptr offs;
  202.     asm db 0cbh;    /* lret - intersegment return */
  203.  
  204.     /* within protentry: go into 32 bit mode, copy entire system to 0 with 
  205.     single string instruction, intrasegment jump to entry point */
  206.     printf("protentry returned?!?\n");
  207.     exit(1);
  208.  
  209.    /* NOTREACHED */
  210. }
  211.  
  212. #ifdef  CKSUM
  213. /* 16 bit checksum of program. */
  214. far_cksum(base, len) long len; char far *base; {
  215.      char far *tmp;
  216.      unsigned seg,offs ;
  217.      long nbytes,sum, tlen;
  218.      tmp = base;
  219.      sum = 0;
  220.      nbytes = 0;
  221.      while (len) {
  222.                /* normalize far pointer to handle segment rollover case */
  223.            tmp = normalize(tmp);
  224.            
  225.                /* Do a page at a time */
  226.             tlen = (len > PGSIZE)? PGSIZE : len;
  227.            len -= tlen ;
  228.            while (tlen--) {
  229.             nbytes++;
  230.             if (sum&01)
  231.                 sum = (sum>>1) + 0x8000;
  232.             else
  233.                 sum >>= 1;
  234.             sum += *tmp++ ;
  235.             sum &= 0xFFFF;
  236.             }
  237.     }
  238.      printf("\nChecksum %05lu%6ld ", sum, (nbytes+CLSIZE)/PGSIZE);
  239. }
  240. #endif CKSUM
  241.  
  242.  
  243.  
  244. [LISTING TWO]
  245.  
  246. /* Excerpted with permission from 4.3BSD include file 
  247.  * "/usr/include/sys/exec.h"
  248.  * Redistribution and use in source and binary forms are freely permitted
  249.  * provided that the above copyright notice and attribution and date of work
  250.  * and this paragraph are duplicated in all such forms.
  251.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  252.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  253.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  254.  * Header prepended to each a.out file.
  255.  */
  256. struct exec {
  257.         long    a_magic;        /* magic number */
  258. unsigned long   a_text;         /* size of text segment */
  259. unsigned long   a_data;         /* size of initialized data */
  260. unsigned long   a_bss;          /* size of uninitialized data */
  261. unsigned long   a_syms;         /* size of symbol table */
  262. unsigned long   a_entry;        /* entry point */
  263. unsigned long   a_trsize;       /* size of text relocation */
  264. unsigned long   a_drsize;       /* size of data relocation */
  265. };
  266.  
  267. #define OMAGIC  0407            /* old impure format */
  268. #define NMAGIC  0410            /* read-only text */
  269. #define ZMAGIC  0413            /* demand load format */
  270.  
  271.  
  272. [LISTING THREE]
  273.  
  274.         title   _gatea20
  275. ;  Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  276. ;  Written by William Jolitz, July 1989
  277. ;  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  278. ;  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  279. ;  WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  280. ;       (void) gatea20();
  281. ;       Enable Address Bit 20 that was disabled by BIOS for MSDOS
  282. ;       We need it off to use entire memory space of the AT.
  283. ;       We do this just prior to entering protected mode, never to return.
  284. ;
  285.  
  286. _TEXT   segment byte public 'CODE'
  287.         assume  cs:_TEXT,ds:_TEXT
  288. _TEXT   ends
  289.  
  290. Status_Port     equ     64h             ; 8042 Status Port
  291. Cmd_rdy         equ     2               ;  Keyboard is ready?
  292. Write_outpt     equ     0d1h            ;  Write next data to output port
  293. Port_A          equ     60h             ; 8042 Keyboard Scan and Diagnostic
  294. EnableA20       equ     0dfh            ; Enable Address bit 20 for use
  295.  
  296. _TEXT   segment byte public 'CODE'
  297.  
  298. ;       Wait for Keyboard controller to be ready for command
  299. wait42  proc    near
  300. chkrdy:
  301.         in      al, Status_Port
  302.         and     al, Cmd_rdy
  303.         jnz     chkrdy
  304.         ret
  305. wait42  endp
  306.  
  307. ;       Turn on A20 again.
  308. _gatea20        proc far
  309.         call    wait42
  310.         mov     al, Write_outpt
  311.         out     Status_Port, al
  312.         call    wait42
  313.         mov     al, EnableA20
  314.         out     Port_A, al
  315.         call    wait42
  316.         ret
  317. _gatea20        endp
  318.  
  319.         public  _gatea20
  320. _TEXT   ends
  321.         end
  322.  
  323.  
  324.  
  325. [LISTING FOUR]
  326.  
  327.         title   protentry
  328. ; Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  329. ; Written by William Jolitz 7/89
  330. ; Redistribution and use in source and binary forms are freely permitted
  331. ; provided that the above copyright notice and attribution and date of work
  332. ; and this paragraph are duplicated in all such forms.
  333. ; THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  334. ; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  335. ; WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  336. ;       protentry(entry,len,addr,...) long entry,len,addr;
  337. ;       Entered via jump or "ret" (e.g. no return address on stack),
  338. ;       builds necessary data structures and transfers into 32-bit
  339. ;       mode, then copies the 32-bit mode program at address "addr"
  340. ;       and byte length "len" to location 0 and enters the program
  341. ;       at location "entry". Note that both "entry" and "addr" are
  342. ;       true 32-bit absolute pointers, NOT segment:offset pairs. It
  343. ;       is assumed that both the stack and this program will not be
  344. ;       overwritten in the subsequent copy to 0 of the program to be
  345. ;       entered, so caller is responsible to place this in a location
  346. ;       above the program.
  347. ;
  348. ;       Note that this program is position-independant (self relocating).
  349. ;
  350. ;       Any additional args past the necessary three will be passed on the
  351. ;       stack to the entered program [note: we obviously don't provide a
  352. ;       "return" address]
  353. ;
  354. _TEXT   segment byte public 'CODE'
  355.         assume  cs:_TEXT,ds:nothing
  356. _TEXT   ends
  357.  
  358. Data32  equ     66h ; prefix to toggle 16/32 data operand
  359. JMPFAR  equ     0eah ; opcode for JMP intersegment
  360.  
  361.         .186    ; allow use of shl ax,cnt insn
  362. _TEXT   segment byte public 'CODE'
  363.  
  364. _protentry      proc far
  365.         jmp short relstrt
  366.  
  367. ; Global Descriptor Table contains three descriptors:
  368. ;  0h: Null: not used
  369. ;  8h: Code: code segment starts at 0 and extents for 4 gbytes
  370. ; 10h: Data: data segment starts at 0 and extends for 4 gbytes(overlays code)
  371. GDT:
  372. NullDesc dw     0,0,0,0       ; null descriptor - not used
  373. CodeDesc dw     0FFFFh        ; limit at maximum: (bits 15:0)
  374.          db     0,0,0         ; base at 0: (bits 23:0)
  375.          db     10011111b     ; present/priv level 0/code/conforming/readable
  376.          db     11001111b     ; page granular/default 32-bit/limit(bits 19:16)
  377.          db     0             ; base at 0: (bits 31:24)
  378. DataDesc dw     0FFFFh        ; limit at maximum: (bits 15:0)
  379.          db     0,0,0         ; base at 0: (bits 23:0)
  380.          db     10010011b     ; present/priv level 0/data/expand-up/writeable
  381.          db     11001111b     ; page granular/default 32-bit/limit(bits 19:16)
  382.          db     0             ; base at 0: (bits 31:24)
  383.  
  384. ; Load Pointers for Tables
  385. ; contains 6-byte pointer information for: LIDT, LGDT
  386.  
  387. ; Interrupt Descriptor Table pointer
  388. IDTPtr   dw     7FFh    ; limit at maximum (allows all 256 interrupts)
  389.          dw     0       ; base at 0: (bits 15:0)
  390.          dw     0       ; base at 0: (bits 31:16)
  391.  
  392. ; Global Descriptor Table pointer
  393. GDTPtr   dw     17h     ; limit to three 8 byte selectors(null,code,data)
  394.          dw offset GDT  ; base address of GDT (bits 15:0)
  395.          dw     0h      ; base address of GDT (bits 31:16)
  396.  
  397. ; Constructed instruction for entry into 32 bit protected mode
  398. ;       ljmp    far Note
  399. dispat: db      Data32  ; 32-bit  override prefix
  400.         db      JMPFAR  ; opcode for JMP intersegment
  401. offl    dw      0       ; starting address of 32-bit code (low-word)
  402.         dw      0h      ; starting address (high word of linear address)
  403.         dw      8h      ; CodeDesc selector=8h
  404.  
  405. relstrt:
  406.         cli             ; disable interrupts
  407.         ; do address fixups
  408.         mov     ax,ss   ; first, make a new 32 bit stack pointer!
  409.         mov     cx,4
  410.         shl     ax,cl   ; ax now contains segment address low 16 bits
  411.         mov     bx,ss
  412.         mov     cx,12
  413.         shr     bx,cl   ; bx now contains segment address high 16 bits
  414.         add     ax,sp
  415.         adc     bx,0    ; ax contains esp 15:0, bx contains esp 31:16
  416.         mov     si,ax   ; pass new stack to 32bit mode via si & di
  417.         mov     di,bx
  418.  
  419.         mov     ax,cs
  420.         mov     cx,4
  421.         shl     ax,cl   ; ax now contains segment address low 16 bits
  422.         mov     bx,cs
  423.         mov     cx,12
  424.         shr     bx,cl   ; bx now contains segment address high 16 bits 
  425.  
  426.         mov     cx,cs:GDTPtr+2
  427.         mov     dx,bx
  428.         add     cx,ax
  429.         mov     cs:GDTPtr+2,cx  
  430.         adc     cs:GDTPtr+4,dx
  431.         mov     cx, OFFSET(cpydwn)
  432.         mov     dx,bx
  433.         add     cx,ax
  434.         mov     cs:offl,cx              ; overflow?
  435.         adc     cs:offl+2,dx
  436.  
  437.         ;  Load the descriptor tables
  438.         
  439. ;       lidt    cs:IDTPtr    ; load Interrupt Descriptor Table
  440. db 2eh,0Fh,01h,00011110b
  441. dw offset IDTPtr
  442. ;       lgdt    cs:GDTPtr    ; load Global Descriptor Table
  443. db 2Eh,0Fh,01h,00010110b
  444. dw offset GDTPtr
  445. ;       smsw    ax            ; put Machine Status Word in AX
  446. db 0fh, 01h, 11100000b
  447.         or al,1               ; activate Protection Enable bit
  448. ;       lmsw    ax            ; store Machine Status Word, begin protected mode
  449. db 0fh,01h,11110000b
  450.  
  451.         jmp short Next  ; flush prefetch queue
  452.  
  453.         ;  Load the segment registers with approriate descriptor selectors
  454.  
  455. Next:   mov     bx,10h  ; set segment registers to DataDesc
  456.         mov     ss,bx   ; load SS,DS,ES segment registers with DataDesc
  457.         mov     ds,bx
  458.         mov     es,bx
  459.  
  460.         ; Load CS via above's constructed ljmp, entering 32 bit protected mode
  461.         jmp short dispat
  462.  
  463.         ; Finally running in Protected 32-bit Mode
  464. cpydwn:
  465.         mov     ax,di   ; movl  %edi,%eax
  466.         shl     ax,16   ;db 0c1h,0e0h,10h       ; shll  $16,%eax
  467.         db Data32
  468.         mov     ax,si   ; movw  %si,%ax
  469.         mov     sp,ax   ; movl  %eax,%esp
  470.         pop     ax      ; pop   eax     ; entry addr
  471.         pop     cx      ; pop   ecx     ; byte size
  472.         pop     si      ; pop   esi     ; source address
  473.         xor     di,di   ; xor   edi,edi ; destination address
  474.         cld
  475.         rep     movsb   ; copy into place
  476.         mov     sp,si   ; movl esp,esi
  477.         jmp     ax      ; jmp   eax     ; go to entry
  478. _protentry      endp
  479.  
  480.         public  _protentry
  481. _TEXT   ends
  482.         end
  483.  
  484.  
  485. [LISTING FIVE]
  486.  
  487. /* Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  488.  * Written by William Jolitz 7/89
  489.  * Redistribution and use in source and binary forms are freely permitted
  490.  * provided that the above copyright notice and attribution and date of work
  491.  * and this paragraph are duplicated in all such forms.
  492.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  493.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  494.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  495.  * This program copies a BSD filesystem out of an MSDOS file and
  496.  * places it on an pre-reserved disk partition. Note that both the
  497.  * geometry of the particular disk, and the particulars of the
  498.  * BSD partition need to be adjusted to suit the drive on which this will
  499.  * be used. Normally, this would be a very rude requirement, but
  500.  * we tolerate this because this program is a throw-away used to get
  501.  * us started, and we have better schemes to deal with configuration
  502.  * a little further down the pike.
  503.  * Currently works with TURBO C 1.5 .
  504.  */
  505.  
  506. #include <bios.h>
  507. #include <io.h>
  508. #include <fcntl.h>
  509. #include <sys\stat.h>
  510. #include "diskl.h"
  511.  
  512. /* Disk geometry (here, a NEC DS5146). Adjust parameters to suit drive. */
  513. #define    NCYL    615
  514. #define    NTRACK    8
  515. #define    NSECT    17
  516.  
  517. #define    BSIZE    512    /* Disk block size */
  518.  
  519. /* Location & size of root partition. Adjust for drive partition layout. */
  520. #define    OFF_CYL    290    /* Cylinder offset of start of BSD root partition */
  521. #define    ROOTSZ    50    /* size of root partition, in units of cylinders */
  522.  
  523. char trkbuf[NSECT*BSIZE];
  524.  
  525. struct label_blk {
  526.     char bufr[LABELOFFSET];
  527.     struct disklabel dl;
  528. } lbl;
  529.  
  530. main (argc, argv) char *argv[]; {
  531.     int fi, rem, cyl, head, sector, tfrcnt;
  532.     if (argc != 2) {
  533.         printf ("usage: cpfs <rootfs>\n");
  534.         exit (1);
  535.     }
  536.     fi = open (argv[1],O_BINARY);
  537.     if (fi < 0) {
  538.         printf ("Cannot open \"%s\" file to read filesystem\n",
  539.             argv[1]);
  540.         exit (1);
  541.     }
  542.     cyl = OFF_CYL;
  543.     tfrcnt = head = 0;
  544.  
  545. #ifndef FIRST
  546.     /* check for presence of disklabel */
  547.     biosdisk (2, 0x80, 0, OFF_CYL, LABELSECTOR, 1, &lbl);
  548.     if (lbl.dl.dk_magic != DISKMAGIC) {
  549.         printf ("BSD Disk partition does not have a label!\n");
  550.         exit (1);
  551.     }
  552.  
  553.     /* Treat first track of data special; use disk label in first block of
  554.          * file to validate that the file to be loaded and disk drive 
  555.          * partition are appropriate for each other. */
  556.     read (fi, trkbuf, BSIZE);
  557.     if (strncmp (trkbuf, &lbl, BSIZE) != 0) {
  558.         printf ("BSD root partition and filesystem mismatch!\n");
  559.         exit (1);
  560.     }
  561.  
  562.     /* reset filesystem file to beginning */
  563.     lseek (fi, 0, SEEK_SET);
  564. #endif
  565.  
  566.     printf ("WARNING! About to overwrite disk (will loose previous\n");
  567.     printf ("contents). Are you certain of your use of this program?");
  568.     if (getche () != 'y') exit (1);
  569.     printf("\n");
  570.  
  571.     /* Transfer file to absolute disk section, a track at a time, 
  572.          because we're impatient. */
  573.     while ((rem = read (fi, trkbuf, NSECT*BSIZE)) == NSECT*BSIZE) {
  574.         biosdisk (3, 0x80, head, cyl, 1, NSECT, trkbuf);
  575.         if (++head == NTRACK) {
  576.             head = 0;
  577.             if (++cyl > NCYL || cyl > OFF_CYL+ROOTSZ ) {
  578.                 printf ("Overran root partition!\n");
  579.                 exit (1);
  580.             }
  581.         }
  582.         tfrcnt += NSECT;
  583.         printf ("Amount transferred %5dK bytes\r",
  584.             tfrcnt*BSIZE/1024);
  585.     }
  586.  
  587.     /* Transfer any remainder leftover in track buffer. */
  588.     if (rem > BSIZE-1) {
  589.         biosdisk (3, 0x80, head, cyl, 1, rem/BSIZE, trkbuf);
  590.         tfrcnt += rem/BSIZE;
  591.         printf ("Amount transferred %5dK bytes\n",
  592.             tfrcnt*BSIZE/1024);
  593.     }
  594.  
  595.     exit (0);
  596. }
  597.  
  598. [LISTING SIX]
  599.  
  600.  
  601. /* Copyright (c) 1985,1986,1989,1990 Micheal J. Karels. All rights reserved.
  602.  * Based on a concept by Sam Leffler. Written by Michael J. Karels 4/85 
  603.  * Revised by William Jolitz 86-90.
  604.  * Redistribution and use in source and binary forms are freely permitted
  605.  * provided that the above copyright notice and attribution and date of work
  606.  * and this paragraph are duplicated in all such forms.
  607.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  608.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  609.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  610.  * Each disk has a label which includes information about the hardware
  611.  * disk geometry, filesystem partitions, and drive specific information.
  612.  * The label is in block 1, offset from the beginning to leave room
  613.  * for a bootstrap, etc.
  614.  */
  615.  
  616. #define LABELSECTOR    1        /* sector containing label */
  617. #define LABELOFFSET    (BSIZE-120)    /* offset of label in sector */
  618. #define DISKMAGIC    0xabc        /* The disk magic number */
  619. #define    DTYPE_ST506    1        /* ST506 Winchester */
  620. #define    DTYPE_FLOPPY    2        /* 5-1/4" minifloppy */
  621. #define    DTYPE_SCSI    3        /* SCSI Direct Access Device */
  622.  
  623. struct disklabel {
  624.     short    dk_magic;        /* the magic number */
  625.     short    dk_type;        /* drive type */
  626.     struct dcon {
  627.         short    dc_secsize;    /* # of bytes per sector */
  628.         short    dc_nsectors;    /* # of sectors per track */
  629.         short    dc_ntracks;    /* # of tracks per cylinder */
  630.         short    dc_ncylinders;    /* # of cylinders per unit */
  631.         long    dc_secpercyl;    /* # of sectors per cylinder */
  632.         long    dc_secperunit;    /* # of sectors per unit */
  633.         long    dc_drivedata[4]; /* drive-type specific information */
  634.     } dc;
  635.     struct dpart {            /* the partition table */
  636.         long    nblocks;    /* number of sectors in partition */
  637.         long    cyloff;        /* starting cylinder for partition */
  638.     } dk_partition[8];
  639.     char    dk_name[16];        /* pack identifier */
  640. };
  641.  
  642. #define dk_secsize        dc.dc_secsize
  643. #define dk_nsectors        dc.dc_nsectors
  644. #define dk_ntracks        dc.dc_ntracks
  645. #define dk_ncylinders        dc.dc_ncylinders
  646. #define dk_secpercyl        dc.dc_secpercyl
  647. #define dk_secperunit        dc.dc_secperunit
  648.  
  649. /* Drive data for ST506. */
  650. #define dk_precompcyl    dc.dc_drivedata[0]
  651. #define dk_ecc        dc.dc_drivedata[1]    /* used only when formatting */
  652. #define dk_gap3        dc.dc_drivedata[2]    /* used only when formatting */
  653.  
  654. /* Drive data for SCSI */
  655. #define dk_blind    dc.dc_drivedata[0]     /* can we work in "blind" i/o */
  656.  
  657.  
  658. [LISTING SEVEN]
  659.  
  660.  
  661. /* Copyright (c) 1989, 1990 William Jolitz. All rights reserved.
  662.  * Written by William Jolitz 7/89
  663.  * Redistribution and use in source and binary forms are freely permitted
  664.  * provided that the above copyright notice and attribution and date of work
  665.  * and this paragraph are duplicated in all such forms.
  666.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  667.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  668.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  669.  * This program copies a MSDOS file to BSD's idea of a swap partition,
  670.  * known to be the second one in the disklabel. Typical use is to place
  671.  * a TAR formatted file, obtained from a cross-host, onto swap. Then
  672.  * BSD is booted with the boot program and the BSD tar utility is
  673.  * used to extract the files being transferred within the TAR image,
  674.  * hopefully before we need to page on the swap space. Again, this
  675.  * program is rude in requiring one to adjust the manifest constant
  676.  * denoting the cylinder on which the BSD root filesystem appears,
  677.  * but this is another throw-away program to get the real work started.
  678.  * Currently works with TURBO C 1.5 .
  679.  */
  680.  
  681. #include <bios.h>
  682. #include <alloc.h>
  683. #include <fcntl.h>
  684. #include <sys\stat.h>
  685. #include "diskl.h"
  686.  
  687. /* Location of root partition. Adjust to suit given drive partition layout. */
  688. #define    OFF_CYL    290    /* Cylinder offset of start of BSD root partition */
  689.  
  690. char *trkbuf;
  691.  
  692. #define BSIZE    512
  693. struct label_blk {
  694.     char bufr[LABELOFFSET];
  695.     struct disklabel dl;
  696. } lbl;
  697.  
  698. main(argc, argv) char *argv[]; {
  699.     int fi, rem, cyl, head, tfrcnt;
  700.     int bsize, ncyl, ntrack, nsect, off_cyl, maxcyl;
  701.  
  702.     if (argc != 2) {
  703.         printf("usage: cpsw <file>\n");
  704.         exit(1);
  705.     }
  706.  
  707.     fi = open(argv[1], O_BINARY);
  708.     if (fi < 0) {
  709.         printf("Cannot open \"%s\" file to BSD swap\n",
  710.             argv[1]);
  711.         exit(1);
  712.     }
  713.  
  714.     /* check for presence of disklabel */
  715.     biosdisk(2, 0x80, 0, OFF_CYL, LABELSECTOR, 1, &lbl);
  716.     if (lbl.dl.dk_magic != 0xabc) {
  717.         printf("BSD root disk partition does not have a label!\n");
  718.         exit(1);
  719.     }
  720.  
  721.        /* Extract disk geometry and swap partition location from disk label. */
  722.     bsize = lbl.dl.dk_secsize;
  723.     nsect = lbl.dl.dk_nsectors;
  724.     ntrack = lbl.dl.dk_ntracks;
  725.     off_cyl = lbl.dl.dk_partition[1].cyloff;
  726.     maxcyl = lbl.dl.dk_partition[1].cyloff +
  727.         lbl.dl.dk_partition[1].nblocks / lbl.dl.dk_secpercyl;
  728.  
  729.     /* Allocate track buffer */
  730.     trkbuf = malloc (nsect*bsize);
  731.  
  732.     printf("WARNING! About to overwrite disk (will loose previous\n");
  733.     printf("contents). Are you certain of your use of this program?");
  734.     if (getche() != 'y') exit(1);
  735.     printf("\n");
  736.  
  737.     tfrcnt = head = 0;
  738.     cyl = off_cyl;
  739.  
  740.     /* Transfer file to absolute disk section, a track at a time, 
  741.          because we're impatient. */
  742.     while ((rem = read(fi, trkbuf, nsect*bsize)) == nsect*bsize) {
  743.         biosdisk(3, 0x80, head, cyl, 1, nsect, trkbuf);
  744.         if (++head == ntrack) {
  745.             head = 0;
  746.             if (++cyl > maxcyl) {
  747.                 printf("Overran swap partition!\n");
  748.                 exit(1);
  749.             }
  750.         }
  751.         tfrcnt += nsect;
  752.         printf("Amount transferred %5dK bytes\r",
  753.             tfrcnt*BSIZE/1024);
  754.     }
  755.  
  756.     /* Transfer any remainder leftover */
  757.     if (rem > BSIZE-1) {
  758.         biosdisk(3, 0x80, head, cyl, 1, rem/bsize, trkbuf);
  759.         tfrcnt += rem/bsize;
  760.         printf("Amount transferred %5dK bytes\n",
  761.             tfrcnt*bsize/1024);
  762.     }
  763.     exit(0);
  764. }
  765.  
  766.