Return to BSD News archive
Newsgroups: comp.unix.bsd Path: sserve!manuel!munnari.oz.au!mips!decwrl!csus.edu!netcomsv!mork!jagane From: jagane@netcom.com (Jagane D Sundar) Subject: Hack for DOS co-existence(386bsd) Message-ID: <cgnl=fk.jagane@netcom.com> Date: Sun, 21 Jun 92 04:14:00 GMT Organization: Netcom - Online Communication Services (408 241-9760 guest) Keywords: 386bsd DOS co-existence Here's a hack for DOS co-existence. It works by allowing DOS to build a filesystem on one a 386bsd partition and fakes fdisk entries to make DOS utilities happy. ADVANTAGES OF THIS APPROACH: 1) It takes the appropriate condescending attitude towards DOS, ie. DOS is allowed to build its filesystem on a 386bsd partition, but 386bsd is THE OS THAT RULES THE DISK. 2) Allows tools like mtools to access the DOS partition and read the DOS filesystem without any modifications to the device driver code. 3) Changes in only one source file( boot.c) that becomes part of the secondary boot block( bootas, bootwd). 4) It solved my problem very quickly. IMPORTANT NOTES: 1) It assumes that 386bsd is the first OS to be installed on the hard disk. ie. All previous contents are wiped out. 2) It allows just one DOS partition. 3) I have tested it with the Pace SCSI Driver but it should work fine with the wd driver too. INSTRUCTIONS TO USE IT: 1) Follow normal installation procedure to install 386bsd on the hard disk but MAKE SURE TO INCLUDE A PARTITION (say d) when you make the entry in disklabel. This is the partition that will become the DOS partition. 2) Copy boot.c included in this message to /sys/i386/stand and make the secondary boot block for the type of your disk(bootas or bootwd). 3) Copy bootxx to /usr/mdec and write disklabel on the disk using disklabel. 4) Compile fdisk.c included to make fdisk utility. Use fdisk to initialize the partition that you had set aside for DOS. For example if you had set aside the partition d on disk as0 for DOS, you would say "fdisk -i as0 d". 5) Use fdisk henceforth to switch to DOS partition. eg. "fdisk -d as0". 6) Boot DOS from floppy and do a fdisk( the DOS utility). You should see two partitions, a DOS partition and a dummy partition. DO NOT ATTEMPT TO EVER CAHNGE THINGS IN THE PARTITION TABLE if you value the sanity of 386bsd partitions. INCLUDED: boot.c fdisk.c ACKNOWLEDGEMENTS: To BILL JOLITZ for bringing a state of art OS in source form to wannabe kernel hackers like me.: To Pace Willisson for the SCSI Driver, so I could get my SCSI system up. Have fun, Jagane D Sundar ____________________Cut here for boot.c_______________________________________ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef lint char copyright[] = "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ All rights reserved.\n"; #endif /* not lint */ #ifdef lint static char sccsid[] = "from:@(#)boot.c 7.3 (Berkeley) 5/4/91"; #endif /* not lint */ #include "param.h" #include "reboot.h" #include <a.out.h> #include "saio.h" #include "disklabel.h" #include "dinode.h" /* * Boot program, loaded by boot block from remaing 7.5K of boot area. * Sifts through disklabel and attempts to load an program image of * a standalone program off the disk. If keyboard is hit during load, * or if an error is encounter, try alternate files. */ char *files[] = { "386bsd", "386bsd.alt", "386bsd.old", "boot" , "vmunix", 0}; int retry = 0; extern struct disklabel disklabel; extern int bootdev, cyloffset; #define SCSI #pragma pack(1) struct fdisktab { unsigned char active; unsigned char beghead; unsigned char begsect; unsigned char begcyl; unsigned char id; unsigned char endhead; unsigned char endsect; unsigned char endcyl; long startsect; long numsects; }; /* * Boot program... loads /boot out of filesystem indicated by arguements. * We assume an autoboot unless we detect a misconfiguration. */ main(dev, unit, off) { register struct disklabel *lp; register int io; register char **bootfile = files; int howto = 0; struct fdisktab *fdtab; fdtab = (struct fdisktab *) 0x7dbe; if(fdtab->active == 0x80) Heigh_ho_back_to_dos_we_go(dev, fdtab); printf("dev %x unit %x off %d\n", dev, unit, off); { int i = 10000; while(--i) inb(0x84); } unit = off = 0; dev = 4; /* are we a disk, if so look at disklabel and do things */ lp = &disklabel; if (lp->d_magic == DISKMAGIC) { /* * Synthesize bootdev from dev, unit, type and partition * information from the block 0 bootstrap. * It's dirty work, but someone's got to do it. * This will be used by the filesystem primatives, and * drivers. Ultimately, opendev will be created corresponding * to which drive to pass to top level bootstrap. */ for (io = 0; io < lp->d_npartitions; io++) { #ifdef SCSI if (lp->d_type == DTYPE_SCSI) { if (lp->d_partitions[io].p_offset == off) break; } else #endif if (lp->d_partitions[io].p_size == 0) continue; if (lp->d_partitions[io].p_offset == off*lp->d_secpercyl) break; } if (io == 8) goto screwed; cyloffset = off; } else { screwed: /* probably a bad or non-existant disklabel */ printf("DIDNT GET DISKLABEL\n"); io = 0 ; howto |= RB_SINGLE|RB_ASKNAME ; } /* construct bootdev */ /* currently, PC has no way of booting off alternate controllers */ bootdev = MAKEBOOTDEV(/*i_dev*/ dev, /*i_adapt*/0, /*i_ctlr*/0, unit, /*i_part*/io); for (;;) { /*printf("namei %s", *bootfile);*/ io = namei(*bootfile); if (io > 2) { copyunix(io, howto); } else printf("File not found"); printf(" - didn't load %s, ",*bootfile); if(*++bootfile == 0) bootfile = files; printf("will try %s\n", *bootfile); wait(1<<((retry++) + 10)); } } /*ARGSUSED*/ copyunix(io, howto) register io; { struct exec x; int i; char *addr,c; struct dinode fil; int off; fetchi(io, &fil); /*printf("mode %o ", fil.di_mode);*/ i = iread(&fil, 0, (char *)&x, sizeof x); off = sizeof x; if (i != sizeof x || x.a_magic != 0413) { printf("Not an executable format"); return; } off = 4096; if (iread(&fil, off, (char *)0, x.a_text) != x.a_text) goto shread; off += x.a_text; addr = (char *)x.a_text; while ((int)addr & CLOFSET) *addr++ = 0; if (iread(&fil, off, addr, x.a_data) != x.a_data) goto shread; addr += x.a_data; bzero(addr, x.a_bss); /* mask high order bits corresponding to relocated system base */ x.a_entry &= ~0xfff00000; /*if (scankbd()) { printf("Operator abort"); kbdreset(); return; }*/ /* howto, bootdev, cyl */ i = (*((int (*)()) x.a_entry))(3, bootdev, 0); if (i) printf("Program exits with %d", i) ; return; shread: printf("Read of file is incomplete"); return; } const char gdtnew[] = { 0, 0, 0, 0, 0, 0, 0, 0, /* (0x0) */ 0xff, 0xff, 0, 0, 0, 0x9f, 0xcf, 0, /* code segment (0x8) */ 0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* data segment (0x10) */ 0xff, 0xff, 0, 0, 0, 0x9f, 0x00, 0, /* dummy code segment (0x18) */ 0xff, 0xff, 0, 0, 0, 0x93, 0x00, 0, /* dummy data segment (0x20) */ }; const struct { short filler; short size; const char *gdt; } loadgdt = { 0, sizeof gdtnew - 1, gdtnew }; Heigh_ho_back_to_dos_we_go(dev, fdtab) struct fdisktab *fdtab; { char *boot0block; char *stub, *stub1, *stub2; boot0block = (char *)0x7c00; stub = (char *)0x7b00; stub1 = (char *)0x7b80; stub2 = (char *)0x7ba0; bzero(stub, 0x100); *stub++ = 0x0f; *stub++ = 0x20; *stub++ = 0xc0; *stub++ = 0x25; *stub++ = 0xfe; *stub++ = 0xff; *stub++ = 0x0f; *stub++ = 0x22; *stub++ = 0xc0; *stub++ = 0xea; *stub++ = 0x80; *stub++ = 0x7b; *stub++ = 0x00; *stub++ = 0x00; *stub1++ = 0x31; *stub1++ = 0xc0; *stub1++ = 0x8e; *stub1++ = 0xd8; *stub1++ = 0x8e; *stub1++ = 0xc0; *stub1++ = 0x8e; *stub1++ = 0xd0; *stub1++ = 0x8e; *stub1++ = 0xe0; *stub1++ = 0x8e; *stub1++ = 0xe8; *stub1++ = 0x2e; *stub1++ = 0x0f; *stub1++ = 0x01; *stub1++ = 0x1e; *stub1++ = 0xa0; *stub1++ = 0x7b; *stub1++ = 0xea; *stub1++ = 0x00; *stub1++ = 0x7c; *stub1++ = 0x00; *stub1++ = 0x00; *stub2++ = 0x00; *stub2++ = 0x04; *stub2++ = 0x00; *stub2++ = 0x00; printf("Heigh_ho_back_to_dos_we_go\n"); bread(dev, fdtab->startsect, boot0block, 512); asm(" cli /* load gdt */ .byte 0x2e,0x0f,0x01,0x15 /* lgdt %cs:$imm */ .long _loadgdt + 2 movl $0x7a00, %esp movl $0x20, %eax movl %ax, %ds movl %ax, %es movl %ax, %fs movl %ax, %gs movl %ax, %ss .byte 0xea .long 0x7b00 .word 0x18 "); } ____________________End boot.c________________________________________________ ____________________Cut here for fdisk.c_______________________________________ #include <stdio.h> #include <sys/types.h> #include <sys/fcntl.h> #include <sys/disklabel.h> extern int errno; struct fdisktab { unsigned char active; unsigned char beghead; unsigned char begsect; unsigned char begcyl; unsigned char id; unsigned char endhead; unsigned char endsect; unsigned char endcyl; long startsect; long numsects; }; main(argc, argv) char **argv; { int force = 0; int activate_unix = 1; if(argc == 4) { if(!strcmp(argv[1], "-I")) force = 1; else if(!strcmp(argv[1], "-i")) force = 0; else usage(); argc--; argv[1] = argv[2]; argv[2] = argv[3]; initialize(argc, argv, force); } else if(argc == 3) { if(!strcmp(argv[1], "-u")) activate_unix = 1; else if(!strcmp(argv[1], "-d")) activate_unix = 0; else usage(); activate(argv[2], activate_unix); } else if(argc == 2) if(*argv[1] != '-') display(argv[1]); else usage(); else usage(); } initialize(argc, argv, force) char **argv; { char devname[256]; int fd; unsigned char buf[2048]; struct disklabel *lbl; struct fdisktab *fdisk; int index, i; sprintf(devname, "/dev/r%sc", argv[1]); if( (fd = open(devname, O_RDWR)) < 0) { printf("Could not open %s. Errno %d.\n", devname, errno); exit(-1); } if(read(fd, buf, 1024) < 1024) { printf("Error %d reading disklabel from %s\n", errno, devname); exit(-1); } fdisk = (struct fdisktab *) &buf[446]; /* talk about hardwire... */ if( !((buf[510] == 0x55) && (buf[511] == 0xaa)) ) { printf("Invalid boot 0 block on device %s\n", devname); exit(-1); } printf("Found valid boot 0 block on %s\n", devname); lbl = (struct disklabel *) &buf[512]; if(lbl->d_magic != DISKMAGIC) { printf("Invalid disklabel on device %s\n", devname); exit(-1); } printf("Found valid disklabel on %s\n", devname); if((*argv[2] >= 'A') && (*argv[2] <= 'Z')) *argv[2] -= ('A' - 'a'); #ifdef DEBUG printf("part %c\n", *argv[2]); #endif index = *argv[2] - 'a'; if(index >= MAXPARTITIONS) { printf("Partition %c is out of range in device %s\n", *argv[2], devname); exit(-1); } #ifdef DEBUG for(i = 0; i < MAXPARTITIONS; i++) printf("%d p_fstype %d\n", i, lbl->d_partitions[i].p_fstype); #endif if(force || (lbl->d_partitions[index].p_fstype == FS_UNUSED) ) { /* create dos partition. */ fdisk->startsect = lbl->d_partitions[index].p_offset; fdisk->numsects = lbl->d_partitions[index].p_size; fdisk->id = (unsigned char)4; /* create dummy partition so that DOS can activate it */ fdisk++; fdisk->active = 0x80; fdisk->startsect = lbl->d_partitions[index].p_offset + lbl->d_partitions[index].p_size; fdisk->numsects = 0; fdisk->id = (unsigned char)98; } else { printf("Partition %c of device %s is not an unused partition.\n" ,*argv[2], devname); printf("\tUse the -I flag if you want to force write.\n"); exit(-1); } if(lseek(fd, 0, 0) != 0L) { printf("Error seeking back to 0 %s\n", devname); exit(-1); } if(write(fd, buf, 1024) != 1024) printf("Error %d writing disklabel on %s.\n", errno, devname); } activate(dev, activate_unix) char *dev; int activate_unix; { char devname[256]; int fd; unsigned char buf[2048]; struct disklabel *lbl; struct fdisktab *fdisk1, *fdisk2; int index, i; sprintf(devname, "/dev/r%sc", dev); if( (fd = open(devname, O_RDWR)) < 0) { printf("Could not open %s. Errno %d.\n", devname, errno); exit(-1); } if(read(fd, buf, 512) < 512) { printf("Error %d reading disklabel from %s\n", errno, devname); exit(-1); } fdisk1 = (struct fdisktab *) &buf[446]; /* talk about hardwire... */ fdisk2 = fdisk1 + 1; if( !((buf[510] == 0x55) && (buf[511] == 0xaa)) ) { printf("Invalid boot 0 block on device %s\n", devname); exit(-1); } printf("Found valid boot 0 block on %s\n", devname); if(activate_unix) { fdisk1->active = 0x00; fdisk2->active = 0x80; } else { fdisk1->active = 0x80; fdisk2->active = 0x00; } if(lseek(fd, 0, 0) != 0L) { printf("Error seeking back to 0 %s\n", devname); exit(-1); } if(write(fd, buf, 512) != 512) printf("Error %d writing fdisk entry on %s.\n", errno, devname); } display(dev) char *dev; { char devname[256]; int fd; unsigned char buf[2048]; struct disklabel *lbl; struct fdisktab *fdisk1, *fdisk2; int index, i; sprintf(devname, "/dev/r%sc", dev); if( (fd = open(devname, O_RDWR)) < 0) { printf("Could not open %s. Errno %d.\n", devname, errno); exit(-1); } if(read(fd, buf, 1024) < 1024) { printf("Error %d reading disklabel from %s\n", errno, devname); exit(-1); } fdisk1 = (struct fdisktab *) &buf[446]; /* talk about hardwire... */ fdisk2 = fdisk1 + 1; if( !((buf[510] == 0x55) && (buf[511] == 0xaa)) ) { printf("Invalid boot 0 block on device %s\n", devname); exit(-1); } printf("Found valid boot 0 block on %s\n", devname); lbl = (struct disklabel *) &buf[512]; if(lbl->d_magic != DISKMAGIC) { printf("Invalid disklabel on device %s\n", devname); exit(-1); } printf("Found valid disklabel on %s\n", devname); printf("disklabel:\n"); for(i = 0; i < MAXPARTITIONS; i++) printf("%c:\tsize %ld,\toffset %ld,\tfstype %d\n", 'a'+i, lbl->d_partitions[i].p_size, lbl->d_partitions[i].p_offset, lbl->d_partitions[i].p_fstype); printf("\n"); printf("fdisk table:\n"); printf("Entry 1:\toffset %ld,\tsize %ld,\tfstype %d\t %s\n", fdisk1->startsect, fdisk1->numsects, fdisk1->id, (fdisk1->active == 0x80 ? "ACTIVE" : "NOT ACTIVE") ); printf("Entry 2:\toffset %ld,\tsize %ld,\tfstype %d\t %s\n", fdisk2->startsect, fdisk2->numsects, fdisk2->id, (fdisk2->active == 0x80 ? "ACTIVE" : "NOT ACTIVE") ); } usage() { printf("Usage : fdisk [-i|-I] <device_name> <partition>\n"); printf("\t\t-i : initialize <partition> as dos partition.\n"); printf("\t\t-I : force initialize (disregard current partition state)\n"); printf("\n"); printf("Usage : fdisk [-d|-u] <device_name>\n"); printf("\t\t-d : Activate dos partition.\n"); printf("\t\t-u : Activate 386bsd.\n"); printf("\n"); printf("Usage : fdisk <device_name>\n"); printf("\t\t : Display state of partitions on <device_name>.\n"); printf("\n"); printf("device_name = [as|wd], partition = [a-h]\n"); printf("Run fdisk after disklabel.\n"); exit(-1); } ____________________End fdisk.c________________________________________________