Subject: BSDs co-existing (was Re: installing 1.1....)
To: None <port-i386@NetBSD.ORG>
From: James da Silva <jds@cs.UMD.EDU>
List: port-i386
Date: 02/25/1996 01:37:56
 Mike Long writes:
 > Note that FreeBSD and NetBSD partitions can't share the same disk.
 > Both of them use a partition ID of 0xA5 to mark their partitions in
 > the DOS partition table.

 Jordan Hubbard writes: 
 > One quick suggestion: Both FreeBSD and NetBSD, AFAIK, use partition type
 > 0xA5 as their reserved partition type.  The FreeBSD boot blocks, and I
 > daresay the NetBSD ones as well, are rather simplistic and simply stop
 > at the first 0xA5 partition they find (though I'm also somewhat pressed
 > to suggest a better course of action - not enough room in the boot
 > blocks to present a menu :-).  This, of course, causes problems if the
 > OS you'd like to boot from is on the *second* partition of type 0xA5.

A simple hack (like the one below) allows the co-existing of BSD partitions
on the same disk by modifying the 0xA5 codes and the active flag in the
partition table before rebooting.  Certainly not as convenient as a boot
menu, but quite workable for experimentation.  I've used this to keep
different NetBSD version setups on the same machine, but it should work for
anything that uses the 0xA5 partition type.  Just get it to compile on each
version of BSD that you are switching between, then to switch to a
partition, do, eg, "active-bsd wd0 1" and reboot.

Just food for thought; not a finished product, nor my candidate for The
Right Way To Do It.

Jaime
..............................................................................
:  James da Silva  :  UMCP Computer Science Dept  :  Stand on my shoulders,  :
:  jds@cs.umd.edu  :  http://www.cs.umd.edu/~jds  :  not on my toes.         :


------------------------------------------------------------------------------
/* active-bsd - another jdshack */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/disklabel.h>

#define DOSPTYP_SPAREBSD (DOSPTYP_386BSD+1)

#define BOOTSIGOFF	(DOSPARTOFF + sizeof(struct dos_partition)*4)
#define BOOTSIG		0xaa55

#define ACTIVE		0x80
#define NOT_ACTIVE	0x00

struct dos_partition *read_partition(int fd);
void show_partition(struct dos_partition *dp);

void main(int argc, char **argv)
{
    struct dos_partition *dp;
    int fd, part;
    char devname[256];

    if(argc != 3) {
	fprintf(stderr, "Usage: active-bsd <disk> <partition [0..3]>\n");
	exit(1);
    }
    part = atoi(argv[2]);
    if(part < 0 || part > 3) {
	fprintf(stderr, "partition must be between 0..3\n");
	exit(1);
    }

    sprintf(devname, "/dev/r%sd", argv[1]);
    if((fd = open(devname, O_RDWR)) == -1) {
	fprintf(stderr, "open %s: %s", devname, strerror(errno));
	exit(1);
    }
    
    dp = read_partition(fd);
    printf("before modification:\n");
    show_partition(dp);
    make_active(dp, part);
    printf("after modification:\n");
    show_partition(dp);
    write_partition(fd);
    close(fd);
    exit(0);
}

char bootblock[512];

struct dos_partition *read_partition(int fd)
{
    off_t bbofs = DOSBBSECTOR * 512;
    int rc;
    unsigned short sig;

    if(lseek(fd, bbofs, SEEK_SET) == -1) {
	perror("lseek boot block");
	exit(1);
    }

    rc = read(fd, bootblock, 512);
    if(rc != 512) {
	fprintf(stderr, "read bootblock: %s\n",
		rc == -1? strerror(errno) : "short read");
	exit(1);
    }

    sig = *(short *)(bootblock + BOOTSIGOFF);
    if(sig != BOOTSIG) {
	fprintf(stderr, "bad boot signature: %x\n", sig);
	exit(1);
    }

    return (struct dos_partition *) (bootblock + DOSPARTOFF);
}

write_partition(int fd)
{
    off_t bbofs = DOSBBSECTOR * 512;
    int rc;

    if(lseek(fd, bbofs, SEEK_SET) == -1) {
	perror("lseek boot block");
	exit(1);
    }

    rc = write(fd, bootblock, 512);
    if(rc != 512) {
	fprintf(stderr, "write bootblock: %s\n",
		rc == -1? strerror(errno) : "short write");
	exit(1);
    }
}

void show_partition(struct dos_partition *dp)
{
    int i;

    printf("#  flg typ sectstart sectsize c/h/s-start   c/h/s-end\n");
    for(i = 0; i < NDOSPART; i++, dp++) {
	printf("%d:", i);
	printf(" %3d %3d", dp->dp_flag, dp->dp_typ);
	printf(" %9d %8d", dp->dp_start, dp->dp_size);
	printf(" %4d/%2d/%3d", dp->dp_scyl, dp->dp_shd, dp->dp_ssect);
	printf(" %4d/%2d/%3d\n", dp->dp_ecyl, dp->dp_ehd, dp->dp_esect);
    }
}


make_active(struct dos_partition *dp, int part)
{
    int i;

    for(i = 0; i < NDOSPART; i++, dp++) {
	if(i == part) {
	    /* make active */
	    dp->dp_flag = ACTIVE;
	    if(dp->dp_typ == DOSPTYP_SPAREBSD)
		dp->dp_typ = DOSPTYP_386BSD;
	}
	else {
	    /* make inactive */
	    dp->dp_flag = NOT_ACTIVE;
	    if(dp->dp_typ == DOSPTYP_386BSD)
		dp->dp_typ = DOSPTYP_SPAREBSD;
	}
    }
}