From 85c2cf303dbd843c7927692db7f414ae1199168a Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Wed, 12 Jul 2000 16:45:11 +0000 Subject: [PATCH] - Always respect cylinder boundaries when creating slices unless the user explicitly sets the geometry. - Allow for MBR boot loaders that are longer than one sector. Only accept boot loaders if their size is a multiple of the sector size, however. --- sbin/fdisk/fdisk.c | 87 +++++++++++++++++++++++++++++++++-------- sbin/i386/fdisk/fdisk.c | 87 +++++++++++++++++++++++++++++++++-------- 2 files changed, 140 insertions(+), 34 deletions(-) diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c index d8801117cd3a..dc0b5de9f162 100644 --- a/sbin/fdisk/fdisk.c +++ b/sbin/fdisk/fdisk.c @@ -45,6 +45,8 @@ int iotest; #define LBUF 100 static char lbuf[LBUF]; +#define MBRSIGOFF 510 + /* * * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 @@ -77,13 +79,11 @@ int cyls, sectors, heads, cylsecs, disksecs; struct mboot { unsigned char padding[2]; /* force the longs to be long aligned */ - unsigned char bootinst[DOSPARTOFF]; + unsigned char *bootinst; /* boot code */ + off_t bootinst_size; struct dos_partition parts[4]; - unsigned short int signature; - /* room to read in MBRs that are bigger then DEV_BSIZE */ - unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; }; -struct mboot mboot; +struct mboot mboot = {{0}, NULL, 0}; #define ACTIVE 0x80 #define BOOT_MAGIC 0xAA55 @@ -297,6 +297,13 @@ main(int argc, char *argv[]) if(rv < 0) err(1, "cannot open any disk"); } + + /* (abu)use mboot.bootinst to probe for the sector size */ + if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) + err(1, "cannot allocate buffer to determine disk sector size"); + read_disk(0, mboot.bootinst); + free(mboot.bootinst); + if (s_flag) { int i; @@ -331,7 +338,8 @@ main(int argc, char *argv[]) partp->dp_typ = DOSPTYP_386BSD; partp->dp_flag = ACTIVE; partp->dp_start = dos_sectors; - partp->dp_size = disksecs - dos_sectors; + partp->dp_size = ((disksecs - dos_sectors) / dos_cylsecs) * + dos_cylsecs; dos(partp->dp_start, partp->dp_size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); @@ -477,14 +485,22 @@ static void init_boot(void) { const char *fname; - int fd; + int fd, n; + struct stat sb; fname = b_flag ? b_flag : "/boot/mbr"; if ((fd = open(fname, O_RDONLY)) == -1 || - read(fd, mboot.bootinst, DOSPARTOFF) == -1 || + fstat(fd, &sb) == -1) + err(1, "%s", fname); + if ((mboot.bootinst_size = sb.st_size) % secsize != 0) + errx(1, "%s: length must be a multiple of sector size", fname); + if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) + errx(1, "%s: unable to allocate read buffer", fname); + if ((n = read(fd, mboot.bootinst, mboot.bootinst_size)) == -1 || close(fd)) err(1, "%s", fname); - mboot.signature = BOOT_MAGIC; + if (n != mboot.bootinst_size) + errx(1, "%s: short read", fname); } @@ -492,12 +508,17 @@ static void init_sector0(unsigned long start) { struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); -unsigned long size = disksecs - start; +unsigned long size; init_boot(); partp->dp_typ = DOSPTYP_386BSD; partp->dp_flag = ACTIVE; + /* ensure cylinder boundaries */ + start = (start / dos_sectors) * dos_sectors; + if(start == 0) + start = dos_sectors; + size = ((disksecs - start) / dos_cylsecs) * dos_cylsecs; partp->dp_start = start; partp->dp_size = size; @@ -555,6 +576,20 @@ struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1; partp->dp_esect = DOSSECT(tsec,tcyl); partp->dp_ehd = thd; } else { + if(partp->dp_start % dos_sectors != 0) { + printf("Adjusting partition to start at a " + "cylinder boundary\n"); + partp->dp_start = + (partp->dp_start / dos_sectors) * + dos_sectors; + } + if(partp->dp_size % dos_cylsecs != 0) { + printf("Adjusting partition to end at a " + "cylinder boundary\n"); + partp->dp_size = + (partp->dp_size / dos_cylsecs) * + dos_cylsecs; + } dos(partp->dp_start, partp->dp_size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, @@ -611,7 +646,6 @@ change_code() { if (ok("Do you want to change the boot code?")) init_boot(); - } void @@ -745,15 +779,25 @@ get_params() static int read_s0() { - if (read_disk(0, (char *) mboot.bootinst) == -1) { + if (mboot.bootinst != NULL) { + free(mboot.bootinst); + mboot.bootinst_size = secsize; + if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { + warnx("unable to allocate buffer to read fdisk " + "partition table"); + return -1; + } + } + if (read_disk(0, mboot.bootinst) == -1) { warnx("can't read fdisk partition table"); return -1; } - if (mboot.signature != BOOT_MAGIC) { + if (*(int *)&mboot.bootinst[MBRSIGOFF] != BOOT_MAGIC) { warnx("invalid fdisk partition table found"); /* So should we initialize things */ return -1; } + memcpy(mboot.parts, &mboot.bootinst[DOSPARTOFF], sizeof(mboot.parts)); return 0; } @@ -763,10 +807,13 @@ write_s0() #ifdef NOT_NOW int flag; #endif + int sector; + if (iotest) { print_s0(-1); return 0; } + memcpy(&mboot.bootinst[DOSPARTOFF], mboot.parts, sizeof(mboot.parts)); /* * write enable label sector before write (if necessary), * disable after writing. @@ -778,14 +825,20 @@ write_s0() if (ioctl(fd, DIOCWLABEL, &flag) < 0) warn("ioctl DIOCWLABEL"); #endif - if (write_disk(0, (char *) mboot.bootinst) == -1) { - warn("can't write fdisk partition table"); - return -1; + for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) + if (write_disk(sector, + &mboot.bootinst[sector * secsize]) == -1) { + warn("can't write fdisk partition table"); + return -1; +#ifdef NOT_NOW + flag = 0; + (void) ioctl(fd, DIOCWLABEL, &flag); +#endif + } #ifdef NOT_NOW flag = 0; (void) ioctl(fd, DIOCWLABEL, &flag); #endif - } return(0); } diff --git a/sbin/i386/fdisk/fdisk.c b/sbin/i386/fdisk/fdisk.c index d8801117cd3a..dc0b5de9f162 100644 --- a/sbin/i386/fdisk/fdisk.c +++ b/sbin/i386/fdisk/fdisk.c @@ -45,6 +45,8 @@ int iotest; #define LBUF 100 static char lbuf[LBUF]; +#define MBRSIGOFF 510 + /* * * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992 @@ -77,13 +79,11 @@ int cyls, sectors, heads, cylsecs, disksecs; struct mboot { unsigned char padding[2]; /* force the longs to be long aligned */ - unsigned char bootinst[DOSPARTOFF]; + unsigned char *bootinst; /* boot code */ + off_t bootinst_size; struct dos_partition parts[4]; - unsigned short int signature; - /* room to read in MBRs that are bigger then DEV_BSIZE */ - unsigned char large_sector_overflow[MAX_SEC_SIZE-MIN_SEC_SIZE]; }; -struct mboot mboot; +struct mboot mboot = {{0}, NULL, 0}; #define ACTIVE 0x80 #define BOOT_MAGIC 0xAA55 @@ -297,6 +297,13 @@ main(int argc, char *argv[]) if(rv < 0) err(1, "cannot open any disk"); } + + /* (abu)use mboot.bootinst to probe for the sector size */ + if ((mboot.bootinst = malloc(MAX_SEC_SIZE)) == NULL) + err(1, "cannot allocate buffer to determine disk sector size"); + read_disk(0, mboot.bootinst); + free(mboot.bootinst); + if (s_flag) { int i; @@ -331,7 +338,8 @@ main(int argc, char *argv[]) partp->dp_typ = DOSPTYP_386BSD; partp->dp_flag = ACTIVE; partp->dp_start = dos_sectors; - partp->dp_size = disksecs - dos_sectors; + partp->dp_size = ((disksecs - dos_sectors) / dos_cylsecs) * + dos_cylsecs; dos(partp->dp_start, partp->dp_size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); @@ -477,14 +485,22 @@ static void init_boot(void) { const char *fname; - int fd; + int fd, n; + struct stat sb; fname = b_flag ? b_flag : "/boot/mbr"; if ((fd = open(fname, O_RDONLY)) == -1 || - read(fd, mboot.bootinst, DOSPARTOFF) == -1 || + fstat(fd, &sb) == -1) + err(1, "%s", fname); + if ((mboot.bootinst_size = sb.st_size) % secsize != 0) + errx(1, "%s: length must be a multiple of sector size", fname); + if ((mboot.bootinst = malloc(mboot.bootinst_size = sb.st_size)) == NULL) + errx(1, "%s: unable to allocate read buffer", fname); + if ((n = read(fd, mboot.bootinst, mboot.bootinst_size)) == -1 || close(fd)) err(1, "%s", fname); - mboot.signature = BOOT_MAGIC; + if (n != mboot.bootinst_size) + errx(1, "%s: short read", fname); } @@ -492,12 +508,17 @@ static void init_sector0(unsigned long start) { struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]); -unsigned long size = disksecs - start; +unsigned long size; init_boot(); partp->dp_typ = DOSPTYP_386BSD; partp->dp_flag = ACTIVE; + /* ensure cylinder boundaries */ + start = (start / dos_sectors) * dos_sectors; + if(start == 0) + start = dos_sectors; + size = ((disksecs - start) / dos_cylsecs) * dos_cylsecs; partp->dp_start = start; partp->dp_size = size; @@ -555,6 +576,20 @@ struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i - 1; partp->dp_esect = DOSSECT(tsec,tcyl); partp->dp_ehd = thd; } else { + if(partp->dp_start % dos_sectors != 0) { + printf("Adjusting partition to start at a " + "cylinder boundary\n"); + partp->dp_start = + (partp->dp_start / dos_sectors) * + dos_sectors; + } + if(partp->dp_size % dos_cylsecs != 0) { + printf("Adjusting partition to end at a " + "cylinder boundary\n"); + partp->dp_size = + (partp->dp_size / dos_cylsecs) * + dos_cylsecs; + } dos(partp->dp_start, partp->dp_size, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd); dos(partp->dp_start + partp->dp_size - 1, partp->dp_size, @@ -611,7 +646,6 @@ change_code() { if (ok("Do you want to change the boot code?")) init_boot(); - } void @@ -745,15 +779,25 @@ get_params() static int read_s0() { - if (read_disk(0, (char *) mboot.bootinst) == -1) { + if (mboot.bootinst != NULL) { + free(mboot.bootinst); + mboot.bootinst_size = secsize; + if ((mboot.bootinst = malloc(mboot.bootinst_size)) == NULL) { + warnx("unable to allocate buffer to read fdisk " + "partition table"); + return -1; + } + } + if (read_disk(0, mboot.bootinst) == -1) { warnx("can't read fdisk partition table"); return -1; } - if (mboot.signature != BOOT_MAGIC) { + if (*(int *)&mboot.bootinst[MBRSIGOFF] != BOOT_MAGIC) { warnx("invalid fdisk partition table found"); /* So should we initialize things */ return -1; } + memcpy(mboot.parts, &mboot.bootinst[DOSPARTOFF], sizeof(mboot.parts)); return 0; } @@ -763,10 +807,13 @@ write_s0() #ifdef NOT_NOW int flag; #endif + int sector; + if (iotest) { print_s0(-1); return 0; } + memcpy(&mboot.bootinst[DOSPARTOFF], mboot.parts, sizeof(mboot.parts)); /* * write enable label sector before write (if necessary), * disable after writing. @@ -778,14 +825,20 @@ write_s0() if (ioctl(fd, DIOCWLABEL, &flag) < 0) warn("ioctl DIOCWLABEL"); #endif - if (write_disk(0, (char *) mboot.bootinst) == -1) { - warn("can't write fdisk partition table"); - return -1; + for(sector = 0; sector < mboot.bootinst_size / secsize; sector++) + if (write_disk(sector, + &mboot.bootinst[sector * secsize]) == -1) { + warn("can't write fdisk partition table"); + return -1; +#ifdef NOT_NOW + flag = 0; + (void) ioctl(fd, DIOCWLABEL, &flag); +#endif + } #ifdef NOT_NOW flag = 0; (void) ioctl(fd, DIOCWLABEL, &flag); #endif - } return(0); }