diff options
author | Tobias Weingartner <weingart@cvs.openbsd.org> | 1997-09-29 22:58:21 +0000 |
---|---|---|
committer | Tobias Weingartner <weingart@cvs.openbsd.org> | 1997-09-29 22:58:21 +0000 |
commit | 0188a0021a58a9c827b1a5f063a66abf9d7c111d (patch) | |
tree | 3e17757c1c906df5ea5967da6837600b509ae63c | |
parent | c083dba820bfbe8aff04a3e80845d30cc42d1362 (diff) |
New fdisk code with interactive (command line type)
editing code. Rewrite from the ground up, save about
20 lines of code. Seems to create valid partition
tables on i386 and alphas.
-rw-r--r-- | sbin/fdisk/Makefile | 34 | ||||
-rw-r--r-- | sbin/fdisk/cmd.c | 341 | ||||
-rw-r--r-- | sbin/fdisk/cmd.h | 79 | ||||
-rw-r--r-- | sbin/fdisk/disk.c | 206 | ||||
-rw-r--r-- | sbin/fdisk/disk.h | 58 | ||||
-rw-r--r-- | sbin/fdisk/fdisk.8 | 300 | ||||
-rw-r--r-- | sbin/fdisk/fdisk.c | 949 | ||||
-rw-r--r-- | sbin/fdisk/mbr.c | 137 | ||||
-rw-r--r-- | sbin/fdisk/mbr.h | 72 | ||||
-rw-r--r-- | sbin/fdisk/misc.c | 166 | ||||
-rw-r--r-- | sbin/fdisk/misc.h | 54 | ||||
-rw-r--r-- | sbin/fdisk/part.c | 247 | ||||
-rw-r--r-- | sbin/fdisk/part.h | 60 | ||||
-rw-r--r-- | sbin/fdisk/user.c | 207 | ||||
-rw-r--r-- | sbin/fdisk/user.h | 46 |
15 files changed, 1993 insertions, 963 deletions
diff --git a/sbin/fdisk/Makefile b/sbin/fdisk/Makefile index 676326f8b5d..ac3b0d6a5b8 100644 --- a/sbin/fdisk/Makefile +++ b/sbin/fdisk/Makefile @@ -1,7 +1,37 @@ -# $OpenBSD: Makefile,v 1.3 1997/09/21 11:36:28 deraadt Exp $ +# +# $OpenBSD: Makefile,v 1.4 1997/09/29 22:58:13 weingart Exp $ +# +# Copyright (c) 1997 Tobias Weingartner +# All rights reserved. +# +# 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 Tobias Weingartner. +# 4. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. +# PROG= fdisk -SRCS= fdisk.c +SRCS= fdisk.c user.c misc.c disk.c mbr.c part.c cmd.c DPADD= ${LIBUTIL} LDADD= -lutil MAN= fdisk.8 diff --git a/sbin/fdisk/cmd.c b/sbin/fdisk/cmd.c new file mode 100644 index 00000000000..173d089cf3c --- /dev/null +++ b/sbin/fdisk/cmd.c @@ -0,0 +1,341 @@ + +/* $OpenBSD: cmd.c,v 1.1 1997/09/29 22:58:14 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <stdio.h> +#include <ctype.h> +#include <memory.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <sys/disklabel.h> +#include "disk.h" +#include "misc.h" +#include "user.h" +#include "part.h" +#include "cmd.h" + + +int +Xinit(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + char buf[DEV_BSIZE]; + + /* Copy MBR */ + MBR_make(tt, buf); + MBR_parse(buf, mbr); + + /* Tell em we did something */ + printf("In memory copy is initialized.\n"); + printf("Use 'write' to update disk.\n"); + + return(CMD_DIRTY); +} + +int +Xdisk(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + + /* Print out disk info */ + DISK_printmetrics(disk); + + /* Ask for new info */ + if(ask_yn("Change geometry?")){ + disk->bios->cylinders = ask_num("Cylinders", ASK_DEC, 1, 1, 1024); + disk->bios->heads = ask_num("Heads", ASK_DEC, 1, 1, 256); + disk->bios->sectors = ask_num("Sectors", ASK_DEC, 1, 1, 64); + + disk->bios->size = disk->bios->cylinders * disk->bios->heads + * disk->bios->sectors; + } + + return(CMD_CONT); +} + +int +Xedit(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + int num; + prt_t *pp; + + if(!isdigit(cmd->args[0])){ + printf("Invalid argument: %s <partition number>\n", cmd->cmd); + return(CMD_CONT); + } + num = atoi(cmd->args); + + if(num < 0 || num > 3){ + printf("Invalid partition number.\n"); + return(CMD_CONT); + } + + /* Print out current table entry */ + pp = &mbr->part[num]; + PRT_print(0, NULL); + PRT_print(num, pp); + + /* Ask for partition type */ + pp->id = ask_num("Partition id", ASK_HEX, pp->id, 0, 0xFF); + + /* Unused, so just zero out */ + if(pp->id == DOSPTYP_UNUSED){ + memset(pp, 0, sizeof(*pp)); + printf("Partiton %d cleared.\n", num); + return(CMD_DIRTY); + } + + /* Change table entry */ + if(ask_yn("Do you wish to edit in CHS mode?")){ + int maxcyl, maxhead, maxsect; + + /* Shorter */ + maxcyl = disk->bios->cylinders - 1; + maxhead = disk->bios->heads - 1; + maxsect = disk->bios->sectors; + + /* Get data */ + pp->scyl = ask_num("Starting cylinder", ASK_DEC, pp->scyl, 0, maxcyl); + pp->shead = ask_num("Starting head", ASK_DEC, pp->shead, 0, maxhead); + pp->ssect = ask_num("Starting sector", ASK_DEC, pp->ssect, 1, maxsect); + pp->ecyl = ask_num("Ending cylinder", ASK_DEC, pp->ecyl, 0, maxcyl); + pp->ehead = ask_num("Ending head", ASK_DEC, pp->ehead, 0, maxhead); + pp->esect = ask_num("Ending sector", ASK_DEC, pp->esect, 1, maxsect); + + /* Fix up off/size values */ + PRT_fix_BN(disk, pp); + }else{ + int start, size; + + + /* Get data */ + start = disk->bios->size; + pp->bs = ask_num("Partition offset", ASK_DEC, pp->bs, 0, start); + + size = disk->bios->size - pp->bs; + pp->ns = ask_num("Partition size", ASK_DEC, pp->ns, 1, size); + + /* Fix up CHS values */ + PRT_fix_CHS(disk, pp); + } + + return(CMD_DIRTY); +} + +int +Xselect(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + int off; + int num; + + if(!isdigit(cmd->args[0])){ + printf("Invalid argument: %s <partition number>\n", cmd->cmd); + return(CMD_CONT); + } + + num = atoi(cmd->args); + off = mbr->part[num].bs; + + /* Sanity checks */ + if(mbr->part[num].id != DOSPTYP_EXTEND){ + printf("Partition %d is not an extended partition.\n", num); + return(CMD_CONT); + } + if(!off){ + printf("Loop to offset 0! Not selected.\n"); + return(CMD_CONT); + }else{ + printf("Selected extended partition %d\n", num); + printf("New MBR at offset %d.\n", off); + } + + /* Recursion is beautifull! */ + USER_modify(disk, tt, off); + + return(CMD_CONT); +} + +int +Xprint(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + + MBR_print(mbr); + + return(CMD_CONT); +} + +int +Xwrite(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + char mbr_buf[DEV_BSIZE]; + int fd; + + if(ask_yn("Are you sure?")){ + printf("Writing MBR at offset %d.\n", offset); + + fd = DISK_open(disk->name, O_RDWR); + MBR_make(mbr, mbr_buf); + MBR_write(fd, offset, mbr_buf); + close(fd); + + return(CMD_CLEAN); + } + + return(CMD_CONT); +} + +int +Xexit(cmd, disk, r, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *r; + mbr_t *tt; + int offset; +{ + + /* Nothing to do here */ + return(CMD_EXIT); +} + +int +Xquit(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + + if(ask_yn("You really want to quit?")) + exit(0); + + return(CMD_CONT); +} + +int +Xhelp(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + cmd_table_t *cmd_table = cmd->table; + int i; + + /* Hmm, print out cmd_table here... */ + for(i = 0; cmd_table[i].cmd != NULL; i++){ + printf("\t%s\t\t%s\n", cmd_table[i].cmd, cmd_table[i].help); + } + + return(CMD_CONT); +} + +int +Xupdate(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + + /* Update code */ + memcpy(mbr->code, tt->code, MBR_CODE_SIZE); + + printf("Machine code updated.\n"); + + return(CMD_DIRTY); +} + +int +Xflag(cmd, disk, mbr, tt, offset) + cmd_t *cmd; + disk_t *disk; + mbr_t *mbr; + mbr_t *tt; + int offset; +{ + int i, num = -1; + + /* Parse partition table entry number */ + if(!isdigit(cmd->args[0])){ + printf("Invalid argument: %s <partition number>\n", cmd->cmd); + return(CMD_CONT); + } + num = atoi(cmd->args); + + if(num < 0 || num > 3){ + printf("Invalid partition number.\n"); + return(CMD_CONT); + } + + /* Set active flag */ + for(i = 0; i < 4; i++){ + if(i == num) mbr->part[i].flag = DOSACTIVE; + else mbr->part[i].flag = 0x00; + } + + printf("Partition %d marked active.\n", num); + + return(CMD_DIRTY); +} + diff --git a/sbin/fdisk/cmd.h b/sbin/fdisk/cmd.h new file mode 100644 index 00000000000..6faef9f5161 --- /dev/null +++ b/sbin/fdisk/cmd.h @@ -0,0 +1,79 @@ + +/* $OpenBSD: cmd.h,v 1.1 1997/09/29 22:58:14 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _CMD_H +#define _CMD_H + +/* Includes */ +#include "disk.h" +#include "mbr.h" + + +/* Constants (returned by cmd funs */ +#define CMD_EXIT 0x0000 +#define CMD_CONT 0x0001 +#define CMD_CLEAN 0x0002 +#define CMD_DIRTY 0x0003 + + +/* Data types */ +struct _cmd_table_t; +typedef struct _cmd_t { + struct _cmd_table_t *table; + char cmd[10]; + char args[100]; +} cmd_t; + +typedef struct _cmd_table_t { + char *cmd; + int (*fcn)(cmd_t *, disk_t *, mbr_t *, mbr_t *, int); + char *help; +} cmd_table_t; + + +/* Prototypes */ +int Xinit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xdisk __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xedit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xselect __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xprint __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xwrite __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xexit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xquit __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xhelp __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xflag __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); +int Xupdate __P((cmd_t *, disk_t *, mbr_t *, mbr_t *, int)); + +#endif _CMD_H + + diff --git a/sbin/fdisk/disk.c b/sbin/fdisk/disk.c new file mode 100644 index 00000000000..c3ec443ebb7 --- /dev/null +++ b/sbin/fdisk/disk.c @@ -0,0 +1,206 @@ + +/* $OpenBSD: disk.c,v 1.1 1997/09/29 22:58:15 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <err.h> +#include <util.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/disklabel.h> +#include <sys/param.h> +#include <sys/sysctl.h> +#include <machine/cpu.h> +#ifdef CPU_BIOSDEV +#include <machine/biosvar.h> +#endif +#include "disk.h" + + +int +DISK_open(disk, mode) + char *disk; + int mode; +{ + int fd; + struct stat st; + + fd = opendev(disk, mode, OPENDEV_PART, NULL); + if(fd < 0) err(1, "%s", disk); + if(fstat(fd, &st) < 0) err(1, "%s", disk); + + if(!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) + err(1, "%s is not a character device or a regular file", disk); + + return(fd); +} + +int +DISK_close(fd) + int fd; +{ + + return(close(fd)); +} + +/* Routine to go after the disklabel for geometry + * information. This should work everywhere, but + * in the land of PC, things are not always what + * they seem. + */ +DISK_metrics * +DISK_getrealmetrics(name) + char *name; +{ + DISK_metrics *lm = NULL; + struct disklabel dl; + int fd; + + /* Get real metrics */ + if((fd = DISK_open(name, O_RDONLY)) >= 0){ + lm = malloc(sizeof(DISK_metrics)); + + if(ioctl(fd, DIOCGDINFO, &dl) < 0){ + warn("DIOCGDINFO"); + free(lm); + lm = NULL; + }else{ + lm->cylinders = dl.d_ncylinders; + lm->heads = dl.d_ntracks; + lm->sectors = dl.d_nsectors; + lm->size = dl.d_secperunit; + } + DISK_close(fd); + } + + return(lm); +} + + +#ifdef CPU_BIOSDEV +/* Routine to go after sysctl info for BIOS + * geometry. This should only really work on PC + * type machines. There is still a problem with + * correlating the BIOS drive to the BSD drive. + * + * XXX - Somebody fix this! + */ +DISK_metrics * +DISK_getbiosmetrics(name) + char *name; +{ + DISK_metrics *bm = NULL; + int biosdev, biosgeo; + int mib[3], size; + + /* Get BIOS metrics */ + mib[0] = CTL_MACHDEP; + mib[1] = CPU_BIOSDEV; + size = sizeof(int); + + if(sysctl(mib, 2, &biosdev, &size, NULL, 0) < 0){ + warn("sysctl"); + return(NULL); + } + + mib[1] = CPU_BIOSGEOMETRY; + size = sizeof(int); + + if(sysctl(mib, 2, &biosgeo, &size, NULL, 0) < 0){ + warn("sysctl"); + return(NULL); + } + + bm = malloc(sizeof(DISK_metrics)); + bm->cylinders = BIOSNTRACKS(biosgeo); + bm->heads = BIOSNHEADS(biosgeo); + bm->sectors = BIOSNSECTS(biosgeo); + bm->size = BIOSNTRACKS(biosgeo) * BIOSNHEADS(biosgeo) + * BIOSNSECTS(biosgeo); + + return(bm); +} +#endif /* CPU_BIOSDEV */ + + +/* This is ugly, and convoluted. All the magic + * for disk geo/size happens here. Basically, + * the bios size is the one we will use in the + * rest of the program, the real size is what we + * got from the disklabel. If the disklabel fails, + * we assume we are working with a normal file, + * and should request the user to specify the + * geometry he/she wishes to use. + */ +int +DISK_getmetrics(disk) + disk_t *disk; +{ + + disk->real = DISK_getrealmetrics(disk->name); +#ifdef CPU_BIOSDEV + disk->bios = DISK_getbiosmetrics(disk->name); +#else + disk->bios = disk->real; /* We aint no stinkin PC */ +#endif + + /* Can not get geometry, punt */ + if(disk->bios == NULL || disk->real == NULL) + return(1); + + return(0); +} + +int +DISK_printmetrics(disk) + disk_t *disk; +{ + + if(disk->real) + printf("Disk GEO: %d/%d/%d [%d sectors]\n", disk->real->cylinders, + disk->real->heads, disk->real->sectors, disk->real->size); + else + printf("Disk GEO: <none>\n"); + + if(disk->bios) + printf("Bios GEO: %d/%d/%d [%d sectors]\n", disk->bios->cylinders, + disk->bios->heads, disk->bios->sectors, disk->bios->size); + else + printf("Bios GEO: <none>\n"); + + return(0); +} + diff --git a/sbin/fdisk/disk.h b/sbin/fdisk/disk.h new file mode 100644 index 00000000000..acfdda110b8 --- /dev/null +++ b/sbin/fdisk/disk.h @@ -0,0 +1,58 @@ + +/* $OpenBSD: disk.h,v 1.1 1997/09/29 22:58:15 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _DISK_H +#define _DISK_H + +/* Data types */ +typedef struct _DISK_metrics { + int cylinders; + int heads; + int sectors; + int size; +} DISK_metrics; + +typedef struct _disk_t { + char *name; + DISK_metrics *bios; + DISK_metrics *real; +} disk_t; + +/* Prototypes */ +int DISK_open __P((char *, int)); +int DISK_close __P((int)); +int DISK_getmetrics __P((disk_t *)); +int DISK_printmetrics __P((disk_t *)); + +#endif _DISK_H + diff --git a/sbin/fdisk/fdisk.8 b/sbin/fdisk/fdisk.8 index a13cb112bb0..44243ab4847 100644 --- a/sbin/fdisk/fdisk.8 +++ b/sbin/fdisk/fdisk.8 @@ -1,5 +1,32 @@ -.\" $OpenBSD: fdisk.8,v 1.5 1996/09/27 15:27:15 deraadt Exp $ -.\" $NetBSD: fdisk.8,v 1.8 1995/03/18 14:55:34 cgd Exp $ +.\" $OpenBSD: fdisk.8,v 1.6 1997/09/29 22:58:20 weingart Exp $ +.\" +.\" Copyright (c) 1997 Tobias Weingartner +.\" All rights reserved. +.\" +.\" 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 Tobias Weingartner. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. .\" .Dd April 4, 1993 .Dt FDISK 8 @@ -9,35 +36,36 @@ .Nd DOS partition maintenance program .Sh SYNOPSIS .Nm -.Op Fl aium -.Op f Ar mbrname -.Op Ar device -.Sh PROLOGUE +.Op Fl ie +.Op Fl f Ar mbrname +.Op Fl c Ar cyls +.Op Fl h Ar heads +.Op Fl s Ar sects +.Ar device +.Sh DESCRIPTION In order for the BIOS to boot the kernel, certain conventions must be -adhered to. -Sector 0 of the disk must contain boot code, a MBR partition table, -and a magic number. -These MBR partitions (also known as BIOS partitions) can be used to -break the disk up into several pieces. -The BIOS loads sector 0 into memory, verifies the magic number, and -begins executing the code at the first byte. +adhered to. Sector 0 of a bootable hard disk must contain boot code, +a MBR partition table, and a magic number. These MBR partitions (also +known as BIOS partitions) can be used to break the disk up into several +pieces. The BIOS loads sector 0 of the boot disk into memory, verifies +the magic number, and begins executing the code at the first byte. The normal DOS MBR boot code searches the MBR partition table for an -`active' partition (indicated by a flag value of 0x80); if one is found, -the boot block from that partition is loaded and replaces the original -boot block. +`active' partition (indicated by a `*' in the fist column), and if one +is found, the boot block from that partition is loaded and executed in +place of the original (MBR) boot block. .Pp The following options are available: -.Bl -tag -width indent -.It Fl a -To change the active partition. +.Bl -tag -width "-f mbrname" .It Fl i -Initialize the MBR sector from other information. -.It Fl u -Update, or change, the MBR sector information. -.It Fl m -Force creation of a new MBR sector. +Initialize the MBR sector. +.It Fl e +Edit existing MBR sectors. .It Fl f Ar mbrname -Specifies an alternate MBR file. +Specifies an alternate MBR template file. +.It Fl c,h,s +Specify an alternate BIOS geometry for +.Nm +to use. .El .Pp The DOS @@ -50,131 +78,140 @@ program serves a similar purpose to the DOS program. When called with no special flags, it prints the MBR partition table of the specified device, ie. .Bd -literal - # fdisk wd0 - Using device /dev/rwd0c: - Parameters extracted from in-core disklabel are: - cylinders=769 heads=15 sectors/track=33 - sectors/cylinder=495 total=380655 - Parameters to be used for BIOS calculations are: - cylinders=769 heads=15 sectors/track=33 - sectors/cylinder=495 - Warning: BIOS sector numbers start at 1 (not 0) - MBR Partition 0: sysid 166=0xa6 (OpenBSD) - start 495, size 380160 (185 MB), flag 0x80 - beg: cylinder 1, head 0, sector 1 - end: cylinder 768, head 14, sector 33 - MBR Partition 1: sysid 6=0x06 (Primary 'big' DOS (> 32MB)) - start 380655, size 2475 (1 MB), flag 0x00 - beg: cylinder 764, head 0, sector 1 - end: cylinder 768, head 14, sector 33 - MBR Partition 2: <UNUSED> - MBR Partition 3: sysid 165=0xa5 (386BSD/FreeBSD/NetBSD) - start 383130, size 224234 (109 MB), flag 0x00 - beg: cylinder 769, head 0, sector 2 - end: cylinder 197, head 14, sector 33 + # fdisk fd0 + Disk: fd0 + Disk GEO: 80/2/18 + Bios GEO: 80/2/18 + + Disk offset: 0 + NT Serial#: 0 + Signature: 0xAA55 + + Starting Ending + #: id cyl hd sec - cyl hd sec [ start - size] + ---------------------------------------------------------------------- + *0: A6 0 0 1 - 79 1 18 [ 0 - 2880] OpenBSD + 1: 00 0 0 0 - 0 0 0 [ 0 - 0] unused + 2: A7 0 0 2 - 79 1 18 [ 1 - 2879] NEXTSTEP + 3: 00 0 0 0 - 0 0 0 [ 0 - 0] unused .Ed .Pp This disk is divided into three partitions that happen to fill the disk. -The second partition overlaps the end of the first. -(Used for debugging purposes) -.Bl -tag -width "cyl, sector and head" -.It Em "sysid" -is used to label the partition. +Partition two overlaps partition one. (Used for debugging purposes) +.Bl -tag -width "start/size" +.It Em "#" +Number of partition table entry. A '*' denotes the bootable partition. +.It Em "id" +System identifier. .oS reserves the magic number 166 decimal (A6 in hex). If no 166 partition is found, it will use an older 386BSD partition -(with a magic number of 165). -.It Em "start and size" -fields provide the start address -and size of a partition in sectors. -.It Em "flag 0x80" -specifies that this is the active partition. -.It Em "cyl, sector and head" -fields are used to specify the beginning address -and end address for the partition. +(with a magic number of 165 or A5 in hex). +.It Em "cyl/hd/sec" +These fields provide the starting and ending address of the partition +in physical BIOS geometry +.It Em "start/size" +These fields provide the starting sector and size in sectors of the +partition in linear block addresses. .It Em "Note:" -these numbers are calculated using BIOS's understanding of the disk -geometry and saved in the bootblock. +Note that the sectors field is `1 based', and the start field is +`0 based'. The CHS values will need to be in the BIOS's geometry +for the system to be able to boot and use the drive correctly. .El .Pp -The flags +The .Fl i -or -.Fl u -are used to indicate that the partition data is to be updated. +flag is used to indicate that the partition data is to be initialized. In this mode, .Nm -will enter a conversational mode. -This mode is designed not to change any data unless you explicitly -tell it to; -.Nm -selects defaults for its questions to guarantee that behavior. +will completely overwrite the primary MBR, and start with a fresh one using +a default template, or one given by the +.Fl f +flag. It will set up partition number 3 to be an +.oS +partition, that will start at cylinder 0, head 1, sector 1, and extend +to the end of the disk. +This mode is designed to initialize an MBR the very first time, +or when it has been corrupted beyond repair. It is almost equivelant +to the DOS command `FDISK /MBR'. .Pp -It displays each partition and asks if you want to edit it. -If you reply affirmatively, -it will step through each field showing the old value -and asking for a new one. -When you are done with a partition, +The flag +.Fl e +is used to modify a partition table using a interactive edit mode of the .Nm -will display the information again and ask if it is correct. +program. This mode is designed to allow you to change any partition on the +drive you choose, including extended partitions. It is a very powerfull mode, +but is safe as long as you do not execute the +.Em write +command, or answer in the negative (the default) when .Nm -will then procede to the next entry. -.Pp -Getting the -.Em cyl, sector, -and -.Em head -fields correct is tricky. -So by default, -they will be calculated for you; -you can specify them if you choose. -.Pp -After all the partitions are processed, -you are given the option to change the -.Em active -partition. -To change only the -.Em active -partition, you can use the -.Fl a -flag instead. -.Pp -Finally, -when the all the data for the first sector has been accumulated, -.Nm -will ask if you really want to rewrite sector 0. -Only if you reply affirmatively to this question will +askes you about writing out changes. +.Sh COMMAND MODE +When you first enter this mode, you are presented with a prompt, that looks +like so: +.Em "fdisk: 0>" . +This prompt has two important pieces of information for you. It will tell +you if the in memory copy of the boot block has been modified or not. If it +has been modified, the prompt will change to look like: +.Em "fdisk:*0>" . +The second piece of information pertains to the number given in the prompt. +This number specifies the disk offset of the currently selected boot block +you are editing. This number could be something different that zero when +you are editing extended partitions. The list of commands and their +explanations are given below. +.Bl -tag -width "update" +.It Em help +This command gives you a list of commands that .Nm -write anything to the disk. +understands in the interactive edit mode. +.It Em init +This command initializes the currently selected, in memory copy, of the +boot block. +.It Em disk +This command will display the current drive geometry that fdisk has +probed. You are given a chance to edit them if you wish. +.It Em edit +This command is used to edit a given table entry in the memory copy of +the current boot block. You may edit either in physical geometry mode, +or in sector offsets and sizes. +.It Em flag +This command makes the given partition table entry bootable. Only one +entry can be marked bootable. If you wish to boot from an extended +partition, you will need to mark the partition table entry for the +extended partition as bootable. +.It Em update +This command will update the machine code in the memory copy of the +currently selected boot block. +.It Em select +This command will select and load into memory the boot block pointed +to by the extended partition table entry in the current boot block. +.It Em print +This command will print the currently selected in memory copy of the boot +block and its MBR table to the terminal. +.It Em write +This will write the in memory copy of the boot block to disk. You will +be asked to confirm this operation. +.It Em exit +This will exit the current level of fdisk, either returning to the +previously selected in memory copy of a boot block, or exit the +program if there is none. +.It Em quit +Quit program without saving current changes. +.El .Pp -The difference between the -.Fl u -flag and -.Fl i -flag is that -the -.Fl u -flag just edits the fields as they appear on the disk, while the -.Fl i -flag is used to `initialize' sector 0. -The -.Fl i -flag instructs -.Nm -to start by making the first 3 partitions empty, setting the last partition -to use the whole disk for -.oS , -and marking the last partition active. .Sh NOTES The automatic calculation of starting cylinder etc. uses a set of figures that represent what the BIOS thinks is the geometry of the drive. -These figures are by default taken from the incore disklabel, but +These figures are by default taken from the incore disklabel, or +values that +.Em /boot +has passed to the kernel, but .Nm -gives you an opportunity to change them. +gives you an opportunity to change them if there is a need to. This allows the user to create a bootblock that can work with drives -that use geometry translation under the BIOS. +that use geometry translation under a potentially different BIOS. .Pp If you hand craft your disk layout, please make sure that the @@ -186,12 +223,15 @@ Editing an existing partition is risky, and may cause you to lose all the data in that partition. .Pp You should run this program interactively once or twice to see how it works. -This is completely safe as long as you answer the last question in the negative. +This is completely safe as long as you answer the write questions in the +negative. .Sh FILES .Pa /usr/mdec/mbr -- the default MBR that can be written onto the disk +- the default MBR template .Sh SEE ALSO -.Xr disklabel 8 +.Xr disklabel 8 , +.Xr boot_i386 8 .Sh BUGS There are subtleties that the program detects that are not explained in -this manual page. +this manual page. Also, chances are that some of the subleties it should +detect are being steamrolled. Caveat Emperor. diff --git a/sbin/fdisk/fdisk.c b/sbin/fdisk/fdisk.c index f931111691b..93416d293e9 100644 --- a/sbin/fdisk/fdisk.c +++ b/sbin/fdisk/fdisk.c @@ -1,874 +1,161 @@ -/* $OpenBSD: fdisk.c,v 1.20 1997/09/29 22:50:06 weingart Exp $ */ -/* $NetBSD: fdisk.c,v 1.11 1995/10/04 23:11:19 ghudson Exp $ */ + +/* $OpenBSD: fdisk.c,v 1.21 1997/09/29 22:58:16 weingart Exp $ */ /* - * Mach Operating System - * Copyright (c) 1992 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ -#ifndef lint -static char rcsid[] = "$OpenBSD: fdisk.c,v 1.20 1997/09/29 22:50:06 weingart Exp $"; -#endif /* not lint */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/disklabel.h> -#include <sys/ioctl.h> -#include <sys/stat.h> - -#include <ctype.h> #include <err.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <unistd.h> -#include <util.h> - -#define _PATH_MBR "/usr/mdec/mbr" - -/* - * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University - * Copyright (c) 1989 Robert. V. Baron - * Created. - */ - -char *disk; -char *mbrname = _PATH_MBR; - -struct disklabel disklabel; /* disk parameters */ -int cylinders; -int sectors; -int heads; -int cylindersectors; -int disksectors; - -struct mboot { - u_int8_t padding[2]; /* force the int's to be int aligned */ - u_int8_t bootinst[DOSPARTOFF]; - struct dos_partition parts[4]; - u_int16_t signature; -} mboot; - -#define ACTIVE 0x80 -#define BOOT_MAGIC (u_int16_t)0xAA55 - -int dos_cylinders; -int dos_heads; -int dos_sectors; -int dos_cylindersectors; - -#define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0)) -#define DOSCYL(c) ((c) & 0xff) -int partition = -1; - -int a_flag; /* set active partition */ -int i_flag; /* replace partition data */ -int u_flag; /* update partition data */ -int m_flag; /* give me a brand new mbr */ - -struct part_type { - int type; - char *name; -} part_types[] = { - { 0x00, "unused"}, - { 0x01, "Primary DOS with 12 bit FAT"}, - { 0x02, "XENIX / filesystem"}, - { 0x03, "XENIX /usr filesystem"}, - { 0x04, "Primary DOS with 16 bit FAT"}, - { 0x05, "Extended DOS"}, - { 0x06, "Primary 'big' DOS (> 32MB)"}, - { 0x07, "OS/2 HPFS, QNX or Advanced UNIX"}, - { 0x08, "AIX filesystem"}, - { 0x09, "AIX boot partition or Coherent"}, - { 0x0A, "OS/2 Boot Manager or OPUS"}, - { 0x0B, "Primary Windows 95 with 32 bit FAT"}, - { 0x0E, "Primary DOS with 16-bit FAT, CHS-mapped"}, - { 0x10, "OPUS"}, - { 0x12, "Compaq Diagnostics"}, - { 0x40, "VENIX 286"}, - { 0x50, "DM"}, - { 0x51, "DM"}, - { 0x52, "CP/M or Microport SysV/AT"}, - { 0x54, "Ontrack"}, - { 0x56, "GB"}, - { 0x61, "Speed"}, - { 0x63, "ISC, System V/386, GNU HURD or Mach"}, - { 0x64, "Novell Netware 2.xx"}, - { 0x65, "Novell Netware 3.xx"}, - { 0x75, "PCIX"}, - { 0x80, "Minix 1.1 ... 1.4a"}, - { 0x81, "Minix 1.4b ... 1.5.10"}, - { 0x82, "Linux swap"}, - { 0x83, "Linux filesystem"}, - { 0x93, "Amoeba filesystem"}, - { 0x94, "Amoeba bad block table"}, - { 0xA5, "386BSD/FreeBSD/NetBSD"}, - { 0xA6, "OpenBSD"}, - { 0xA7, "NEXTSTEP"}, - { 0xB7, "BSDI BSD/386 filesystem"}, - { 0xB8, "BSDI BSD/386 swap"}, - { 0xDB, "Concurrent CPM or C.DOS or CTOS"}, - { 0xE1, "Speed"}, - { 0xE3, "Speed"}, - { 0xE4, "Speed"}, - { 0xF1, "Speed"}, - { 0xF2, "DOS 3.3+ Secondary"}, - { 0xF4, "Speed"}, - { 0xFF, "BBT (Bad Blocks Table)"}, -}; - -void usage __P((void)); -void print_s0 __P((int)); -void print_part __P((int)); -void init_sector0 __P((int)); -void intuit_translated_geometry __P((void)); -int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, - quad_t)); -int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t)); -void change_part __P((int)); -void print_params __P((void)); -void change_active __P((int)); -void get_params_to_use __P((void)); -void dos __P((int, unsigned char *, unsigned char *, unsigned char *)); -int open_disk __P((int)); -int read_disk __P((u_int32_t, void *)); -int write_disk __P((int, void *)); -int get_params __P((void)); -int read_s0 __P((void)); -int write_s0 __P((void)); -int yesno __P((char *)); -void decimal __P((char *, int *)); -int type_match __P((const void *, const void *)); -char *get_type __P((int)); -int get_mapping __P((int, int *, int *, int *, int *)); - -int -main(argc, argv) - int argc; - char *argv[]; -{ - int ch, part; - - while ((ch = getopt(argc, argv, "0123aiumf:")) != -1) - switch (ch) { - case '0': - partition = 0; - break; - case '1': - partition = 1; - break; - case '2': - partition = 2; - break; - case '3': - partition = 3; - break; - case 'a': - a_flag = 1; - break; - case 'i': - i_flag = 1; - case 'u': - u_flag = 1; - break; - case 'm': - m_flag = 1; - i_flag = 1; - u_flag = 1; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc == 0) - usage(); - - disk = argv[0]; - - if (open_disk(a_flag || i_flag || u_flag) < 0) - exit(1); - - printf("Using device %s:\n", disk); - if (m_flag || read_s0()) - init_sector0(0); - - intuit_translated_geometry(); - - if (u_flag) - get_params_to_use(); - else - print_params(); - - printf("WARNING: BIOS sector numbers start at 1 (not 0)\n"); - if (partition == -1) { - for (part = 0; part < NDOSPART; part++) - change_part(part); - } else - change_part(partition); - - if (u_flag || a_flag) - change_active(partition); +#include <paths.h> +#include <sys/types.h> +#include <sys/fcntl.h> +#include <sys/disklabel.h> +#include "disk.h" +#include "user.h" - if (u_flag || a_flag) { - printf("\nWe haven't changed the partition table yet. "); - printf("This is your last chance.\n"); - print_s0(-1); - if (yesno("Should we write new partition table?")) - write_s0(); - } +#define _PATH_MBR _PATH_BOOTDIR "mbr" - exit(0); -} void usage() { - fprintf(stderr, "usage: fdisk [-aium] [-0123] [-f mbrboot] disk\n"); - fprintf(stderr, "-a: change active, -i: initialize, -u: update\n"); - fprintf(stderr, "-m: replace MBR bootblock, -0123: select partition\n"); + fprintf(stderr, "usage: fdisk [-ie] [-f mbrboot] [-c cyl] [-h head] [-s sect] disk\n"); + fprintf(stderr, "\t-i: initialize disk with virgin MBR\n"); + fprintf(stderr, "\t-e: edit MBRs on disk interactively\n"); + fprintf(stderr, "\t-f: specify non-standard MBR template\n"); + fprintf(stderr, "\t-chs: specify disk geometry\n"); fprintf(stderr, "`disk' may be of the forms: sd0 or /dev/rsd0c.\n"); exit(1); } -void -print_s0(which) - int which; -{ - int part; - - print_params(); - printf("Information from DOS bootblock is:\n"); - if (which == -1) { - for (part = 0; part < NDOSPART; part++) - print_part(part); - } else - print_part(which); -} - -static struct dos_partition mtpart = { 0 }; - -static inline u_int16_t -getshort(p) - void *p; -{ - unsigned char *cp = p; - - return cp[0] | (cp[1] << 8); -} - -static inline void -putshort(p, l) - void *p; - u_int16_t l; -{ - unsigned char *cp = p; - - *cp++ = l; - *cp++ = l >> 8; -} - -static inline u_int32_t -getlong(p) - void *p; -{ - unsigned char *cp = p; - - return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); -} - -static inline void -putlong(p, l) - void *p; - u_int32_t l; -{ - unsigned char *cp = p; - - *cp++ = l; - *cp++ = l >> 8; - *cp++ = l >> 16; - *cp++ = l >> 24; -} - -void -leader(lead) - int lead; -{ - while (lead--) - printf(" "); -} - -void -print_partinfo(pp, lead, off) - struct dos_partition *pp; - int lead; - u_int32_t off; -{ - static int extcnt; - static int extoff; - - printf("sysid %d=0x%02x (%s)\n", pp->dp_typ, pp->dp_typ, - get_type(pp->dp_typ)); - if (DPCYL(pp->dp_scyl, pp->dp_esect) > 1023) { - leader(lead); - printf("Starts beyond 1023/0/1: BIOS cannot boot from here\n"); - } - leader(lead); - printf(" start %d, size %d (%d MB), flag 0x%02x\n", - getlong(&pp->dp_start) + - (pp->dp_typ != DOSPTYP_EXTEND ? off : extoff), - getlong(&pp->dp_size), - getlong(&pp->dp_size) * 512 / (1024 * 1024), pp->dp_flag); - leader(lead); - printf(" beg: cylinder %4d, head %3d, sector %2d\n", - DPCYL(pp->dp_scyl, pp->dp_ssect), - pp->dp_shd, DPSECT(pp->dp_ssect)); - leader(lead); - printf(" end: cylinder %4d, head %3d, sector %2d\n", - DPCYL(pp->dp_ecyl, pp->dp_esect), - pp->dp_ehd, DPSECT(pp->dp_esect)); - - if (pp->dp_typ == DOSPTYP_EXTEND) { - struct mboot data; - u_int32_t off2; - int i; - - off2 = extoff+getlong(&pp->dp_start); - - if (read_disk(off2, data.bootinst) == -1) { - leader(lead+4); - printf("uhm, disk read error...\n"); - return; - } - - if (!extoff) - extoff = off2; - - if (getshort(&data.signature) != BOOT_MAGIC) { - fprintf(stderr, - "warning: invalid fdisk partition table found!\n"); - return; - } - - for (i = 0; i < 4; i++) { - pp = &data.parts[i]; - if (memcmp(pp, &mtpart, sizeof(*pp))) { - leader(lead+2); - printf("Extended Partition %d: ", extcnt); - extcnt++; - print_partinfo(pp, lead+2, off2); - extcnt--; - } - } - } -} - -void -print_part(part) - int part; -{ - struct dos_partition *pp = &mboot.parts[part]; - - printf("MBR Partition %d: ", part); - if (!memcmp(pp, &mtpart, sizeof(*pp))) - printf("<UNUSED>\n"); - else - print_partinfo(pp, 0, 0); -} - - -void -init_sector0(start) - int start; -{ - struct dos_partition *partp; - FILE *f; - - f = fopen(mbrname, "r"); - if (!f) - err(1, "cannot open %s", mbrname); - - if (fread(mboot.bootinst, sizeof mboot.bootinst, 1, f) != 1) - err(1, "reading %s", mbrname); - fclose(f); - - putshort(&mboot.signature, BOOT_MAGIC); - - partp = &mboot.parts[3]; - partp->dp_typ = DOSPTYP_OPENBSD; - partp->dp_flag = ACTIVE; - putlong(&partp->dp_start, start); - putlong(&partp->dp_size,disksectors - start); - - dos(getlong(&partp->dp_start), - &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); - dos(getlong(&partp->dp_start) + getlong(&partp->dp_size) - 1, - &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); -} - -/* - * Prerequisite: the disklabel parameters and master boot record must - * have been read (i.e. dos_* and mboot are meaningful). - * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and - * dos_cylindersectors to be consistent with what the - * partition table is using, if we can find a geometry - * which is consistent with all partition table entries. - * We may get the number of cylinders slightly wrong (in - * the conservative direction). The idea is to be able - * to create a NetBSD partition on a disk we don't know - * the translated geometry of. - * This whole routine should be replaced with a kernel interface to get - * the BIOS geometry (which in turn requires modifications to the i386 - * boot loader to pass in the BIOS geometry for each disk). - */ -void -intuit_translated_geometry() -{ - int cylinders = -1, heads = -1, sectors = -1, i, j; - int c1, h1, s1, c2, h2, s2; - int a1, a2; - quad_t num, denom; - - /* Try to deduce the number of heads from two different mappings. */ - for (i = 0; i < NDOSPART * 2; i++) { - if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) - continue; - for (j = 0; j < 8; j++) { - if (get_mapping(j, &c2, &h2, &s2, &a2) < 0) - continue; - num = (quad_t)h1*(a2-s2) - h2*(a1-s1); - denom = (quad_t)c2*(a1-s1) - c1*(a2-s2); - if (denom != 0 && num % denom == 0) { - heads = num / denom; - break; - } - } - if (heads > 0) - break; - } - - if (heads <= 0) - return; - /* Now figure out the number of sectors from a single mapping. */ - for (i = 0; i < NDOSPART * 2; i++) { - if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) - continue; - num = a1 - s1; - denom = c1 * heads + h1; - if (denom != 0 && num % denom == 0) { - sectors = num / denom; - break; - } - } - - if (sectors == -1) - return; - - /* Estimate the number of cylinders. */ - cylinders = dos_cylinders * dos_cylindersectors / heads / sectors; - - /* Now verify consistency with each of the partition table entries. - * Be willing to shove cylinders up a little bit to make things work, - * but translation mismatches are fatal. */ - for (i = 0; i < NDOSPART * 2; i++) { - if (get_mapping(i, &c1, &h1, &s1, &a1) < 0) - continue; - if (sectors * (c1 * heads + h1) + s1 != a1) - return; - if (c1 >= cylinders) - cylinders = c1 + 1; - } - - /* Everything checks out. Reset the geometry to use for further - * calculations. */ - dos_cylinders = cylinders; - dos_heads = heads; - dos_sectors = sectors; - dos_cylindersectors = heads * sectors; -} - -/* - * For the purposes of intuit_translated_geometry(), treat the partition - * table as a list of eight mapping between (cylinder, head, sector) - * triplets and absolute sectors. Get the relevant geometry triplet and - * absolute sectors for a given entry, or return -1 if it isn't present. - * Note: for simplicity, the returned sector is 0-based. - */ int -get_mapping(i, cylinder, head, sector, absolute) - int i, *cylinder, *head, *sector; - int *absolute; -{ - struct dos_partition *part = &mboot.parts[i / 2]; - - if (part->dp_typ == 0) - return -1; - if (i % 2 == 0) { - *cylinder = DPCYL(part->dp_scyl, part->dp_ssect); - *head = part->dp_shd; - *sector = DPSECT(part->dp_ssect) - 1; - *absolute = getlong(&part->dp_start); - } else { - *cylinder = DPCYL(part->dp_ecyl, part->dp_esect); - *head = part->dp_ehd; - *sector = DPSECT(part->dp_esect) - 1; - *absolute = getlong(&part->dp_start) - + getlong(&part->dp_size) - 1; - } - return 0; -} - -void -change_part(part) - int part; -{ - struct dos_partition *partp = &mboot.parts[part]; - int sysid, start, size; +main(argc, argv) + int argc; + char **argv; +{ + int ch, fd; + int i_flag = 0, m_flag = 0; + int c_arg = 0, h_arg = 0, s_arg = 0; + disk_t disk; + char *mbrfile = _PATH_MBR; + mbr_t mbr; + char mbr_buf[DEV_BSIZE]; + + while((ch = getopt(argc, argv, "ief:c:h:s:")) != -1){ + switch(ch){ + case 'i': + i_flag = 1; + break; - print_part(part); - if (!u_flag || !yesno("Do you want to change it?")) - return; + case 'e': + m_flag = 1; + break; - if (i_flag) { - memset(partp, 0, sizeof(*partp)); - if (part == 3) { - init_sector0(0); - printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n"); - print_part(part); - } - } + case 'f': + mbrfile = optarg; + break; - do { - sysid = partp->dp_typ, - start = getlong(&partp->dp_start), - size = getlong(&partp->dp_size); - decimal("sysid", &sysid); - decimal("start", &start); - decimal("size", &size); - partp->dp_typ = sysid; - putlong(&partp->dp_start, start); - putlong(&partp->dp_size, size); + case 'c': + c_arg = atoi(optarg); + break; - if (yesno("Explicitly specify beg/end address?")) { - int tsector, tcylinder, thead; + case 'h': + h_arg = atoi(optarg); + break; - tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect); - thead = partp->dp_shd; - tsector = DPSECT(partp->dp_ssect); - decimal("beginning cylinder", &tcylinder); - decimal("beginning head", &thead); - decimal("beginning sector", &tsector); - partp->dp_scyl = DOSCYL(tcylinder); - partp->dp_shd = thead; - partp->dp_ssect = DOSSECT(tsector, tcylinder); + case 's': + s_arg = atoi(optarg); + break; - tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect); - thead = partp->dp_ehd; - tsector = DPSECT(partp->dp_esect); - decimal("ending cylinder", &tcylinder); - decimal("ending head", &thead); - decimal("ending sector", &tsector); - partp->dp_ecyl = DOSCYL(tcylinder); - partp->dp_ehd = thead; - partp->dp_esect = DOSSECT(tsector, tcylinder); - } else { - dos(getlong(&partp->dp_start), - &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect); - dos(getlong(&partp->dp_start) - + getlong(&partp->dp_size) - 1, - &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect); + default: + usage(); } - - print_part(part); - } while (!yesno("Is this entry okay?")); -} - -void -print_params() -{ - - printf("Parameters extracted from in-core disklabel are:\n"); - printf(" cylinders=%d heads=%d sectors/track=%d\n", - cylinders, heads, sectors); - printf(" sectors/cylinder=%d total=%d\n", - cylindersectors, disksectors); - if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255) - printf("Figures below won't work with BIOS for partitions not in cylinder 1\n"); - printf("Parameters to be used for BIOS calculations are:\n"); - printf(" cylinders=%d heads=%d sectors/track=%d\n", - dos_cylinders, dos_heads, dos_sectors); - printf(" sectors/cylinder=%d\n", - dos_cylindersectors); -} - -void -change_active(which) - int which; -{ - struct dos_partition *partp = &mboot.parts[0]; - int part, active = 3; - - if (a_flag && which != -1) - active = which; - else { - for (part = 0; part < NDOSPART; part++) - if (partp[part].dp_flag & ACTIVE) - active = part; } - if (yesno("Do you want to change the active partition?")) { - do { - decimal("active partition", &active); - } while (!yesno("Are you happy with this choice?")); - } - for (part = 0; part < NDOSPART; part++) - partp[part].dp_flag &= ~ACTIVE; - partp[active].dp_flag |= ACTIVE; -} - -void -get_params_to_use() -{ - print_params(); - if (yesno("Do you want to change our idea of what BIOS thinks?")) { - do { - decimal("BIOS's idea of #cylinders", &dos_cylinders); - decimal("BIOS's idea of #heads", &dos_heads); - decimal("BIOS's idea of #sectors", &dos_sectors); - dos_cylindersectors = dos_heads * dos_sectors; - print_params(); - } while (!yesno("Are you happy with this choice?")); - } -} - -/* - * Change real numbers into strange dos numbers - */ -void -dos(sector, cylinderp, headp, sectorp) - int sector; - unsigned char *cylinderp, *headp, *sectorp; -{ - int cylinder, head; - - if (dos_cylindersectors) - cylinder = sector / dos_cylindersectors; - else - cylinder = 0; - sector -= cylinder * dos_cylindersectors; + argc -= optind; + argv += optind; - if (dos_sectors) - head = sector / dos_sectors; + /* Argument checking */ + if(argc != 1) + usage(); else - head = 0; - sector -= head * dos_sectors; - - *cylinderp = DOSCYL(cylinder); - *headp = head; - *sectorp = DOSSECT(sector + 1, cylinder); -} - -int fd; - -int -open_disk(u_flag) - int u_flag; -{ - struct stat st; - - fd = opendev(disk, (u_flag ? O_RDWR : O_RDONLY), OPENDEV_PART, &disk); - if (fd == -1) { - warn("%s", disk); - return (-1); - } - if (fstat(fd, &st) == -1) { - close(fd); - warn("%s", disk); - return (-1); - } - if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) { - close(fd); - warnx("%s is not a character device or regular file", disk); - return (-1); - } - if (get_params() == -1) { - close(fd); - return (-1); - } - return (0); -} - -int -read_disk(sector, buf) - u_int32_t sector; - void *buf; -{ - if (lseek(fd, (off_t)(sector * 512), 0) == -1) - return (-1); - return (read(fd, buf, 512)); -} - -int -write_disk(sector, buf) - int sector; - void *buf; -{ - if (lseek(fd, (off_t)(sector * 512), 0) == -1) - return (-1); - return (write(fd, buf, 512)); -} - -int -get_params() -{ - if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) { - warn("DIOCGDINFO"); - return (-1); - } - - dos_cylinders = cylinders = disklabel.d_ncylinders; - dos_heads = heads = disklabel.d_ntracks; - dos_sectors = sectors = disklabel.d_nsectors; - dos_cylindersectors = cylindersectors = heads * sectors; - disksectors = cylinders * heads * sectors; - return (0); -} - -int -read_s0() -{ - - if (read_disk(0, mboot.bootinst) == -1) { - warn("can't read fdisk partition table"); - return (-1); - } - if (getshort(&mboot.signature) != BOOT_MAGIC) { - fprintf(stderr, - "warning: invalid fdisk partition table found!\n"); - /* So should we initialize things? */ - return (-1); + disk.name = argv[0]; + + /* Get the geometry */ + if(DISK_getmetrics(&disk) && !(c_arg | h_arg | s_arg)) + errx(1, "Can't get disk geometry, please use [-c|h|s] to specify."); + + /* Put in supplied geometry if there */ + if(c_arg | h_arg | s_arg){ + if(disk.bios != NULL){ + if(c_arg) disk.bios->cylinders = c_arg; + if(h_arg) disk.bios->heads = h_arg; + if(s_arg) disk.bios->sectors = s_arg; + }else{ + disk.bios = malloc(sizeof(DISK_metrics)); + if(!c_arg) warn("Unknown number of cylinders per disk."); + if(!h_arg) warn("Unknown number of heads per cylinder."); + if(!s_arg) warn("Unknown number of sectors per track."); + + disk.bios->cylinders = c_arg; + disk.bios->heads = h_arg; + disk.bios->sectors = s_arg; + } } - return (0); -} - -int -write_s0() -{ - int flag; - /* - * write enable label sector before write (if necessary), - * disable after writing. - * needed if the disklabel protected area also protects - * sector 0. (e.g. empty disk) - */ - flag = 1; - if (ioctl(fd, DIOCWLABEL, &flag) < 0) - warn("DIOCWLABEL"); - if (write_disk(0, mboot.bootinst) == -1) { - warn("can't write fdisk partition table"); - return -1; - } - flag = 0; - if (ioctl(fd, DIOCWLABEL, &flag) < 0) - warn("DIOCWLABEL"); - return 0; -} + /* Parse mbr template, to pass on later */ + if((fd = open(mbrfile, O_RDONLY)) < 0) + err(1, "open"); + MBR_read(fd, 0, mbr_buf); + close(fd); + MBR_parse(mbr_buf, &mbr); -int -yesno(str) - char *str; -{ - int ch, first; - printf("%s [n] ", str); + /* Print out current MBRs on disk */ + if((i_flag + m_flag) == 0) + exit(USER_print_disk(&disk)); - first = ch = getchar(); - while (ch != '\n' && ch != EOF) - ch = getchar(); - return (first == 'y' || first == 'Y'); -} - -void -decimal(str, num) - char *str; - int *num; -{ - char lbuf[100], *cp; - int acc = 0; + /* Punt if no i or m */ + if((i_flag + m_flag) != 1) + usage(); - while (1) { - printf("Supply a decimal value for \"%s\" [%d] ", str, *num); - if (fgets(lbuf, sizeof lbuf, stdin) == NULL) - errx(1, "eof"); - lbuf[strlen(lbuf)-1] = '\0'; + /* Now do what we are supposed to */ + if(i_flag) + USER_init(&disk, &mbr); - cp = lbuf; - cp += strspn(cp, " \t"); - if (*cp == '\0') - return; - if (!isdigit(*cp)) - goto bad; - acc = strtol(lbuf, &cp, 10); + if(m_flag) + USER_modify(&disk, &mbr, 0); - cp += strspn(cp, " \t"); - if (*cp != '\0') - goto bad; - *num = acc; - return; -bad: - printf("%s is not a valid decimal number.\n", lbuf); - } + return(0); } -int -type_match(key, item) - const void *key, *item; -{ - const int *typep = key; - const struct part_type *ptr = item; - - if (*typep < ptr->type) - return (-1); - if (*typep > ptr->type) - return (1); - return (0); -} - -char * -get_type(type) - int type; -{ - struct part_type *ptr; - - ptr = bsearch(&type, part_types, - sizeof(part_types) / sizeof(struct part_type), - sizeof(struct part_type), type_match); - if (ptr == 0) - return ("unknown"); - return (ptr->name); -} diff --git a/sbin/fdisk/mbr.c b/sbin/fdisk/mbr.c new file mode 100644 index 00000000000..2830fc3b741 --- /dev/null +++ b/sbin/fdisk/mbr.c @@ -0,0 +1,137 @@ + +/* $OpenBSD: mbr.c,v 1.1 1997/09/29 22:58:16 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <err.h> +#include <util.h> +#include <stdio.h> +#include <unistd.h> +#include <memory.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/disklabel.h> +#include <machine/param.h> +#include "disk.h" +#include "misc.h" +#include "mbr.h" +#include "part.h" + + +void +MBR_parse(mbr_buf, mbr) + char *mbr_buf; + mbr_t *mbr; +{ + int i; + + memcpy(mbr->code, mbr_buf, MBR_CODE_SIZE); + mbr->nt_serial = getlong(&mbr_buf[MBR_NTSER_OFF]); + mbr->spare = getshort(&mbr_buf[MBR_SPARE_OFF]); + mbr->signature = getshort(&mbr_buf[MBR_SIG_OFF]); + + for(i = 0; i < NDOSPART; i++) + PRT_parse(&mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i], &mbr->part[i]); +} + +void +MBR_make(mbr, mbr_buf) + mbr_t *mbr; + char *mbr_buf; +{ + int i; + + memcpy(mbr_buf, mbr->code, MBR_CODE_SIZE); + putlong(&mbr_buf[MBR_NTSER_OFF], mbr->nt_serial); + putshort(&mbr_buf[MBR_SPARE_OFF], mbr->spare); + putshort(&mbr_buf[MBR_SIG_OFF], mbr->signature); + + for(i = 0; i < NDOSPART; i++) + PRT_make(&mbr->part[i], &mbr_buf[MBR_PART_OFF + MBR_PART_SIZE * i]); +} + +void +MBR_print(mbr) + mbr_t *mbr; +{ + int i; + + printf("NT Serial #: %d\n", (int)mbr->nt_serial); + printf("Signature #: 0x%X\n\n", (int)mbr->signature); + + /* Header */ + PRT_print(0, NULL); + + /* Entries */ + for(i = 0; i < NDOSPART; i++){ + PRT_print(i, &mbr->part[i]); + } +} + +int +MBR_read(fd, where, buf) + int fd; + off_t where; + char *buf; +{ + off_t off; + int len; + + where *= DEV_BSIZE; + off = lseek(fd, where, SEEK_SET); + if(off != where) return(off); + + len = read(fd, buf, DEV_BSIZE); + if(len != DEV_BSIZE) return(len); + + return(0); +} + +int +MBR_write(fd, where, buf) + int fd; + off_t where; + char *buf; +{ + off_t off; + int len; + + where *= DEV_BSIZE; + off = lseek(fd, where, SEEK_SET); + if(off != where) return(off); + + len = write(fd, buf, DEV_BSIZE); + if(len != DEV_BSIZE) return(len); + + return(0); +} + diff --git a/sbin/fdisk/mbr.h b/sbin/fdisk/mbr.h new file mode 100644 index 00000000000..049b8f854c4 --- /dev/null +++ b/sbin/fdisk/mbr.h @@ -0,0 +1,72 @@ + +/* $OpenBSD: mbr.h,v 1.1 1997/09/29 22:58:17 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _MBR_H +#define _MBR_H + +#include "part.h" + +/* Various constants */ +#define MBR_CODE_SIZE 0x1B8 +#define MBR_PART_SIZE 0x10 +#define MBR_PART_OFF 0x1BE +#define MBR_NTSER_OFF 0x1B8 +#define MBR_SPARE_OFF 0x1BC /* Spare short, not used */ +#define MBR_SIG_OFF 0x1FE + + +/* MBR type */ +typedef struct _mbr_t { + unsigned char code[MBR_CODE_SIZE]; + unsigned long nt_serial; + unsigned short spare; + prt_t part[NDOSPART]; + unsigned short signature; +} mbr_t; + +/* Prototypes */ +void MBR_print_disk __P((char *)); +void MBR_print __P((mbr_t *)); +void MBR_parse __P((char *, mbr_t *)); +void MBR_make __P((mbr_t *, char *)); +int MBR_read __P((int, off_t, char *)); +int MBR_write __P((int, off_t, char *)); + +/* Sanity check */ +#include <machine/param.h> +#if (DEV_BSIZE != 512) +#error "DEV_BSIZE != 512, somebody better fix!" +#endif + +#endif _MBR_H + diff --git a/sbin/fdisk/misc.c b/sbin/fdisk/misc.c new file mode 100644 index 00000000000..756d0968c28 --- /dev/null +++ b/sbin/fdisk/misc.c @@ -0,0 +1,166 @@ + +/* $OpenBSD: misc.c,v 1.1 1997/09/29 22:58:17 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <err.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <sys/disklabel.h> +#include "misc.h" + + +int +ask_cmd(cmd) + cmd_t *cmd; +{ + char lbuf[100], *cp, *buf; + + /* Get input */ + if(fgets(lbuf, sizeof lbuf, stdin) == NULL) + errx(1, "eof"); + lbuf[strlen(lbuf)-1] = '\0'; + + /* Parse input */ + buf = lbuf; + buf = &buf[strspn(buf, " \t")]; + cp = &buf[strcspn(buf, " \t")]; + *cp++ = '\0'; + strncpy(cmd->cmd, buf, 10); + buf = &cp[strspn(cp, " \t")]; + strncpy(cmd->args, buf, 100); + + return(0); +} + +int +ask_num(str, flags, dflt, low, high) + const char *str; + int flags; + int dflt; + int low; + int high; +{ + char lbuf[100], *cp; + int num; + + do { + num = dflt; + if(flags == ASK_HEX) + printf("%s [%X - %X]: [%X] ", str, low, high, num); + else + printf("%s [%d - %d]: [%d] ", str, low, high, num); + + if (fgets(lbuf, sizeof lbuf, stdin) == NULL) + errx(1, "eof"); + lbuf[strlen(lbuf)-1] = '\0'; + + /* Convert */ + cp = lbuf; + num = strtol(lbuf, &cp, ((flags==ASK_HEX)?16:10)); + + /* Make sure only number present */ + if(cp == lbuf) + num = dflt; + if(*cp != '\0'){ + printf("'%s' is not a valid number.\n", lbuf); + num = low - 1; + }else if(num < low || num > high){ + printf("'%d' is out of range.\n", num); + } + } while(num < low || num > high); + + return(num); +} + +int +ask_yn(str) + const char *str; +{ + int ch, first; + + printf("%s [n] ", str); + fflush(stdout); + + first = ch = getchar(); + while (ch != '\n' && ch != EOF) + ch = getchar(); + + if(ch == EOF || first == EOF) + errx(1, "eof"); + + return(first == 'y' || first == 'Y'); +} + +u_int16_t +getshort(p) + void *p; +{ + unsigned char *cp = p; + + return cp[0] | (cp[1] << 8); +} + +void +putshort(p, l) + void *p; + u_int16_t l; +{ + unsigned char *cp = p; + + *cp++ = l; + *cp++ = l >> 8; +} + +u_int32_t +getlong(p) + void *p; +{ + unsigned char *cp = p; + + return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24); +} + +void +putlong(p, l) + void *p; + u_int32_t l; +{ + unsigned char *cp = p; + + *cp++ = l; + *cp++ = l >> 8; + *cp++ = l >> 16; + *cp++ = l >> 24; +} + diff --git a/sbin/fdisk/misc.h b/sbin/fdisk/misc.h new file mode 100644 index 00000000000..14c67436156 --- /dev/null +++ b/sbin/fdisk/misc.h @@ -0,0 +1,54 @@ + +/* $OpenBSD: misc.h,v 1.1 1997/09/29 22:58:18 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _MISC_H +#define _MISC_H + +#include <sys/types.h> +#include "cmd.h" + +/* Constants */ +#define ASK_HEX 0x01 +#define ASK_DEC 0x02 + +/* Prototypes */ +int ask_cmd __P((cmd_t *)); +int ask_num __P((const char *, int, int, int, int)); +int ask_yn __P((const char *)); +u_int16_t getshort __P((void *)); +u_int32_t getlong __P((void *)); +void putshort __P((void *, u_int16_t)); +void putlong __P((void *, u_int32_t)); + +#endif _MISC_H + diff --git a/sbin/fdisk/part.c b/sbin/fdisk/part.c new file mode 100644 index 00000000000..e9fdb0121df --- /dev/null +++ b/sbin/fdisk/part.c @@ -0,0 +1,247 @@ + +/* $OpenBSD: part.c,v 1.1 1997/09/29 22:58:18 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <err.h> +#include <util.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/disklabel.h> +#include <machine/param.h> +#include "disk.h" +#include "misc.h" +#include "mbr.h" + + +static struct part_type { + int type; + char *name; +} part_types[] = { + { 0x00, "unused"}, + { 0x01, "Primary DOS with 12 bit FAT"}, + { 0x02, "XENIX / filesystem"}, + { 0x03, "XENIX /usr filesystem"}, + { 0x04, "Primary DOS with 16 bit FAT"}, + { 0x05, "Extended DOS"}, + { 0x06, "Primary 'big' DOS (> 32MB)"}, + { 0x07, "OS/2 HPFS, QNX or Advanced UNIX"}, + { 0x08, "AIX filesystem"}, + { 0x09, "AIX boot partition or Coherent"}, + { 0x0A, "OS/2 Boot Manager or OPUS"}, + { 0x0B, "Primary Windows 95 with 32 bit FAT"}, + { 0x0E, "Primary DOS with 16-bit FAT, CHS-mapped"}, + { 0x10, "OPUS"}, + { 0x12, "Compaq Diagnostics"}, + { 0x40, "VENIX 286"}, + { 0x50, "DM"}, + { 0x51, "DM"}, + { 0x52, "CP/M or Microport SysV/AT"}, + { 0x54, "Ontrack"}, + { 0x56, "GB"}, + { 0x61, "Speed"}, + { 0x63, "ISC, System V/386, GNU HURD or Mach"}, + { 0x64, "Novell Netware 2.xx"}, + { 0x65, "Novell Netware 3.xx"}, + { 0x75, "PCIX"}, + { 0x80, "Minix 1.1 ... 1.4a"}, + { 0x81, "Minix 1.4b ... 1.5.10"}, + { 0x82, "Linux swap"}, + { 0x83, "Linux filesystem"}, + { 0x93, "Amoeba filesystem"}, + { 0x94, "Amoeba bad block table"}, + { 0xA5, "386BSD/FreeBSD/NetBSD"}, + { 0xA6, "OpenBSD"}, + { 0xA7, "NEXTSTEP"}, + { 0xB7, "BSDI BSD/386 filesystem"}, + { 0xB8, "BSDI BSD/386 swap"}, + { 0xDB, "Concurrent CPM or C.DOS or CTOS"}, + { 0xE1, "Speed"}, + { 0xE3, "Speed"}, + { 0xE4, "Speed"}, + { 0xF1, "Speed"}, + { 0xF2, "DOS 3.3+ Secondary"}, + { 0xF4, "Speed"}, + { 0xFF, "BBT (Bad Blocks Table)"}, +}; + + +char * +PRT_ascii_id(id) + int id; +{ + static char unknown[] = "<Unknown ID>"; + int i; + + for(i = 0; i < sizeof(part_types)/sizeof(struct part_type); i++){ + if(part_types[i].type == id) + return(part_types[i].name); + } + + return(unknown); +} + +void +PRT_parse(prt, partn) + void *prt; + prt_t *partn; +{ + unsigned char *p = prt; + + partn->flag = *p++; + partn->shead = *p++; + partn->ssect = (*p) & 0x3F; + partn->scyl = ((*p << 2) & 0xFF00) | (*(p+1)); + p += 2; + + partn->id = *p++; + partn->ehead = *p++; + partn->esect = (*p) & 0x3F; + partn->ecyl = ((*p << 2) & 0xFF00) | (*(p+1)); + p += 2; + + partn->bs = getlong(p); + partn->ns = getlong(p+4); +} + +void +PRT_make(partn, prt) + prt_t *partn; + void *prt; +{ + unsigned char *p = prt; + + *p++ = partn->flag & 0xFF; + *p++ = partn->shead & 0xFF; + *p++ = (partn->ssect & 0x3F) | ((partn->scyl & 0x300) >> 2); + *p++ = partn->scyl & 0xFF; + + *p++ = partn->id & 0xFF; + + *p++ = partn->ehead & 0xFF; + *p++ = (partn->esect & 0x3F) | ((partn->ecyl & 0x300) >> 2); + *p++ = partn->ecyl & 0xFF; + + putlong(p, partn->bs); + putlong(p+4, partn->ns); +} + +void +PRT_print(num, partn) + int num; + prt_t *partn; +{ + + if(partn == NULL){ + printf(" Starting Ending\n"); + printf(" #: id cyl hd sec - cyl hd sec [ start - size]\n"); + printf("-------------------------------------------------------------------\n"); + }else{ + printf("%c%1d: %.2X %4d %3d %3d - %4d %3d %3d [%10d - %10d] %s\n", + (partn->flag == 0x80)?'*':' ', + num, partn->id, + partn->scyl, partn->shead, partn->ssect, + partn->ecyl, partn->ehead, partn->esect, + partn->bs, partn->ns, + PRT_ascii_id(partn->id)); + } +} + +void +PRT_fix_BN(disk, part) + disk_t *disk; + prt_t *part; +{ + int spt, tpc, spc; + int start = 0; + int end = 0; + + /* Disk metrics */ + spt = disk->bios->sectors; + tpc = disk->bios->heads; + spc = spt * tpc; + + start += part->scyl * spc; + start += part->shead * spt; + start += part->ssect - 1; + + end += part->ecyl * spc; + end += part->ehead * spt; + end += part->esect - 1; + + /* XXX - Should handle this... */ + if(start > end) + warn("Start of partition after end!"); + + part->bs = start; + part->ns = (end - start) + 1; +} + +void +PRT_fix_CHS(disk, part) + disk_t *disk; + prt_t *part; +{ + int spt, tpc, spc; + int start, end, size; + int cyl, head, sect; + + /* Disk metrics */ + spt = disk->bios->sectors; + tpc = disk->bios->heads; + spc = spt * tpc; + + start = part->bs; + size = part->ns; + end = (start + size) - 1; + + /* Figure out starting CHS values */ + cyl = (start / spc); start -= (cyl * spc); + head = (start / spt); start -= (head * spt); + sect = (start + 1); + + part->scyl = cyl; + part->shead = head; + part->ssect = sect; + + /* Figure out ending CHS values */ + cyl = (end / spc); end -= (cyl * spc); + head = (end / spt); end -= (head * spt); + sect = (end + 1); + + part->ecyl = cyl; + part->ehead = head; + part->esect = sect; +} + diff --git a/sbin/fdisk/part.h b/sbin/fdisk/part.h new file mode 100644 index 00000000000..32001760bf1 --- /dev/null +++ b/sbin/fdisk/part.h @@ -0,0 +1,60 @@ + +/* $OpenBSD: part.h,v 1.1 1997/09/29 22:58:19 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _PART_H +#define _PART_H + +/* Partition type */ +typedef struct _prt_t { + int shead, scyl, ssect; + int ehead, ecyl, esect; + int bs; + int ns; + unsigned char flag; + unsigned char id; +} prt_t; + +/* Prototypes */ +char *PRT_ascii_id __P((int)); +void PRT_parse __P((void *, prt_t *)); +void PRT_make __P((prt_t *, void *)); +void PRT_print __P((int, prt_t *)); + +/* This does CHS -> bs/ns */ +void PRT_fix_BN __P((disk_t *, prt_t *)); + +/* This does bs/ns -> CHS */ +void PRT_fix_CHS __P((disk_t *, prt_t *)); + +#endif _PART_H + diff --git a/sbin/fdisk/user.c b/sbin/fdisk/user.c new file mode 100644 index 00000000000..b2d84e1b8f7 --- /dev/null +++ b/sbin/fdisk/user.c @@ -0,0 +1,207 @@ + +/* $OpenBSD: user.c,v 1.1 1997/09/29 22:58:19 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#include <err.h> +#include <util.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/disklabel.h> +#include <machine/param.h> +#include "user.h" +#include "disk.h" +#include "misc.h" +#include "mbr.h" +#include "cmd.h" + + +/* Our command table */ +static cmd_table_t cmd_table[] = { + {"help", Xhelp, "Command help list"}, + {"init", Xinit, "Initialize loaded MBR"}, + {"disk", Xdisk, "Edit current drive stats"}, + {"edit", Xedit, "Edit given table entry"}, + {"flag", Xflag, "Flag given table entry as bootable"}, + {"update", Xupdate, "Update machine code in loaded MBR"}, + {"select", Xselect, "Select extended partition table entry MBR"}, + {"print", Xprint, "Print loaded MBR partition table"}, + {"write", Xwrite, "Write loaded MBR to disk"}, + {"exit", Xexit, "Exit current level of fdisk edit"}, + {"quit", Xquit, "Quit program without saving current changes"}, + {NULL, NULL, NULL} +}; + + +int +USER_init(disk, tt) + disk_t *disk; + mbr_t *tt; +{ + int fd; + char mbr_buf[DEV_BSIZE]; + + /* Fix up given mbr for this disk */ + tt->part[0].flag = 0; + tt->part[1].flag = 0; + tt->part[2].flag = 0; + tt->part[3].flag = DOSACTIVE; + tt->signature = DOSMBR_SIGNATURE; + + /* Use whole disk, save for first head, on first cyl. */ + tt->part[3].id = DOSPTYP_OPENBSD; + tt->part[3].scyl = 0; + tt->part[3].shead = 1; + tt->part[3].ssect = 1; + + /* Go right to the end */ + tt->part[3].ecyl = disk->bios->cylinders; + tt->part[3].ehead = disk->bios->heads; + tt->part[3].esect = disk->bios->sectors; + + /* Fix up start/length fields */ + PRT_fix_BN(disk, &tt->part[3]); + + /* Write sector 0 */ + fd = DISK_open(disk->name, O_RDWR); + MBR_make(tt, mbr_buf); + MBR_write(fd, (off_t)0, mbr_buf); + DISK_close(fd); + + return(0); +} + +int +USER_modify(disk, tt, offset) + disk_t *disk; + mbr_t *tt; + int offset; +{ + char mbr_buf[DEV_BSIZE]; + mbr_t mbr; + cmd_t cmd; + int i, st, fd, modified = 0; + + + /* Set up command table pointer */ + cmd.table = cmd_table; + + /* Read MBR & partition */ + fd = DISK_open(disk->name, O_RDONLY); + MBR_read(fd, offset, mbr_buf); + DISK_close(fd); + + /* Parse the sucker */ + MBR_parse(mbr_buf, &mbr); + + + /* Edit cycle */ + do { + printf("fdisk:%c%d> ", (modified)?'*':' ', offset); + fflush(stdout); + ask_cmd(&cmd); + + for(i = 0; cmd_table[i].cmd != NULL; i++) + if(strstr(cmd_table[i].cmd, cmd.cmd) == cmd_table[i].cmd) + break; + + /* Quick hack to put in '?' == 'help' */ + if(!strcmp(cmd.cmd, "?")) + i = 0; + + /* Check for valid command */ + if(cmd_table[i].cmd == NULL){ + printf("Invalid command '%s'. Try 'help'.\n", cmd.cmd); + continue; + }else + strcpy(cmd.cmd, cmd_table[i].cmd); + + /* Call function */ + st = cmd_table[i].fcn(&cmd, disk, &mbr, tt, offset); + + /* Update status */ + if(st == CMD_EXIT) break; + if(st == CMD_CLEAN) modified = 0; + if(st == CMD_DIRTY) modified = 1; + } while(1); + + + /* XXX - Write out MBR */ + if(modified){ + printf("\n"); + printf("\t-----------------------------------------------------\n"); + printf("\t--- ATTENTION - PARTITION TABLE HAS BEEN MODIFIED ---\n"); + printf("\t-----------------------------------------------------\n"); + if(ask_yn("\nDo you wish to write before exit?")){ + fd = DISK_open(disk->name, O_RDWR); + MBR_make(&mbr, mbr_buf); + MBR_write(fd, offset, mbr_buf); + close(fd); + } + } + + return(0); +} + +int +USER_print_disk(disk) + disk_t *disk; +{ + int fd, offset, i; + char mbr_buf[DEV_BSIZE]; + mbr_t mbr; + + fd = DISK_open(disk->name, O_RDONLY); + offset = 0; + + printf("Disk: %s\n", disk->name); + DISK_printmetrics(disk); + + do { + MBR_read(fd, (off_t)offset, mbr_buf); + MBR_parse(mbr_buf, &mbr); + + printf("\nDisk offset: %d\n", (int)offset); + MBR_print(&mbr); + + /* Print out extended partitions too */ + for(offset = i = 0; i < 4; i++) + if(mbr.part[i].id == DOSPTYP_EXTEND) + offset = mbr.part[i].bs; + } while(offset); + + return(DISK_close(fd)); +} + diff --git a/sbin/fdisk/user.h b/sbin/fdisk/user.h new file mode 100644 index 00000000000..a1934ddea31 --- /dev/null +++ b/sbin/fdisk/user.h @@ -0,0 +1,46 @@ + +/* $OpenBSD: user.h,v 1.1 1997/09/29 22:58:20 weingart Exp $ */ + +/* + * Copyright (c) 1997 Tobias Weingartner + * All rights reserved. + * + * 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 Tobias Weingartner. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + */ + +#ifndef _USER_H +#define _USER_H + +#include "disk.h" +#include "mbr.h" + +/* Prototypes */ +int USER_init __P((disk_t *, mbr_t *)); +int USER_modify __P((disk_t *, mbr_t *, int)); +int USER_print_disk __P((disk_t *)); + +#endif _USER_H + |