Delete GPT partitions if we overwrite with MBR to avoid confusion with disks

that have both MBR and a secondary left over GPT partition signature. From
Mike M. Volokhov
This commit is contained in:
christos 2009-06-01 19:57:33 +00:00
parent 477a0ba90e
commit cb3a6fdee7
3 changed files with 108 additions and 10 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.39 2009/04/06 12:19:16 lukem Exp $
# $NetBSD: Makefile,v 1.40 2009/06/01 19:57:33 christos Exp $
PROG= fdisk
SRCS= fdisk.c
@ -17,7 +17,7 @@ CPPFLAGS+= -D_PATH_DEFDISK='"/dev/rwd0c"'
.if (${HOSTPROG:U} == "")
SUBDIR= mbr
DPADD+= ${LIBUTIL}
LDADD+= -lutil
DPADD+= ${LIBUTIL} ${LIBZ}
LDADD+= -lutil -lz
.include <bsd.subdir.mk>
.endif

View File

@ -1,6 +1,6 @@
.\" $NetBSD: fdisk.8,v 1.59 2008/01/20 15:04:09 dsl Exp $
.\" $NetBSD: fdisk.8,v 1.60 2009/06/01 19:57:33 christos Exp $
.\"
.Dd January 20, 2008
.Dd June 1, 2009
.Dt FDISK 8
.Os
.Sh NAME
@ -125,6 +125,14 @@ This mode is designed not to change any data unless you explicitly tell it to;
.Nm
selects defaults for its questions to guarantee that behaviour.
.Pp
If partition data is going to be updated, and disk carries GUID Partition
Tables the
.Nm
will remove both primary and backup GPT headers from the disk.
See
.Xr gpt 8
for information on how to manipulate GUID Partition Tables.
.Pp
.Nm
will calculate the correct
.Em cylinder ,
@ -559,6 +567,7 @@ Default location of i386 bootselect for extended partitions
.Xr disktab 5 ,
.Xr boot 8 ,
.Xr disklabel 8 ,
.Xr gpt 8 ,
.Xr installboot 8 ,
.Xr mbr 8 ,
.Xr mbrlabel 8

View File

@ -1,4 +1,4 @@
/* $NetBSD: fdisk.c,v 1.120 2009/04/20 17:06:55 drochner Exp $ */
/* $NetBSD: fdisk.c,v 1.121 2009/06/01 19:57:33 christos Exp $ */
/*
* Mach Operating System
@ -39,7 +39,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fdisk.c,v 1.120 2009/04/20 17:06:55 drochner Exp $");
__RCSID("$NetBSD: fdisk.c,v 1.121 2009/06/01 19:57:33 christos Exp $");
#endif /* not lint */
#define MBRPTYPENAMES
@ -61,13 +61,16 @@ __RCSID("$NetBSD: fdisk.c,v 1.120 2009/04/20 17:06:55 drochner Exp $");
#if !HAVE_NBTOOL_CONFIG_H
#include <sys/disklabel.h>
#include <sys/disklabel_gpt.h>
#include <sys/bootblock.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <disktab.h>
#include <util.h>
#include <zlib.h>
#else
#include <nbinclude/sys/disklabel.h>
#include <nbinclude/sys/disklabel_gpt.h>
#include <nbinclude/sys/bootblock.h>
#include "../../include/disktab.h"
/* We enforce -F, so none of these possibly undefined items can be needed */
@ -106,6 +109,8 @@ __RCSID("$NetBSD: fdisk.c,v 1.120 2009/04/20 17:06:55 drochner Exp $");
#define SCAN_F1 0x3b
#define SCAN_1 0x2
#define GPT_TYPE(offs) ((offs) == GPT_HDR_BLKNO ? "primary" : "secondary")
#define MAX_BIOS_DISKS 16 /* Going beyond F12 is hard though! */
/* We same the dflt 'boot partition' as a disk block, with some magic values. */
@ -197,6 +202,8 @@ int F_flag = 0;
int F_flag = 1;
#endif
struct gpt_hdr gpt1, gpt2; /* GUID partition tables */
struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
int bootsize; /* actual size of bootcode */
int boot_installed; /* 1 if we've copied code into the mbr */
@ -235,6 +242,8 @@ int write_disk(daddr_t, void *);
int get_params(void);
int read_s0(daddr_t, struct mbr_sector *);
int write_mbr(void);
int read_gpt(daddr_t, struct gpt_hdr *);
int delete_gpt(struct gpt_hdr *);
int yesno(const char *, ...);
int decimal(const char *, int, int, int, int);
#define DEC_SEC 1 /* asking for a sector number */
@ -288,7 +297,8 @@ main(int argc, char *argv[])
int csysid; /* For the s_flag. */
unsigned int cstart, csize;
a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
i_flag = B_flag = 0;
v_flag = 0;
E_flag = 0;
csysid = cstart = csize = 0;
@ -434,6 +444,9 @@ main(int argc, char *argv[])
/* must have been a blank disk */
init_sector0(1);
read_gpt(GPT_HDR_BLKNO, &gpt1);
read_gpt(disksectors - 1, &gpt2);
#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H
get_geometry();
#else
@ -499,10 +512,23 @@ main(int argc, char *argv[])
"yet. This is your last chance.\n");
if (u_flag)
print_s0(-1);
if (yesno("Should we write new partition table?"))
if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0)
printf("\nWARNING: The disk is carrying "
"GUID Partition Tables.\n"
" If you continue, "
"GPT headers will be deleted.\n\n");
if (yesno("Should we write new partition table?")) {
delete_gpt(&gpt1);
delete_gpt(&gpt2);
write_mbr();
} else
}
} else {
if (delete_gpt(&gpt1) > 0)
warnx("Primary GPT header was deleted");
if (delete_gpt(&gpt2) > 0)
warnx("Secondary GPT header was deleted");
write_mbr();
}
}
exit(0);
@ -2773,3 +2799,66 @@ get_type(int type)
return ("unknown");
return (ptr->name);
}
int
read_gpt(daddr_t offset, struct gpt_hdr *gptp)
{
char buf[512];
struct gpt_hdr *hdr = (void *)buf;
const char *tabletype = GPT_TYPE(offset);
if (read_disk(offset, buf) == -1) {
warn("Can't read %s GPT header", tabletype);
return -1;
}
(void)memcpy(gptp, buf, GPT_HDR_SIZE);
/* GPT CRC should be calculated with CRC field preset to zero */
hdr->hdr_crc_self = 0;
if (memcmp(gptp->hdr_sig, GPT_HDR_SIG, sizeof(gptp->hdr_sig))
|| gptp->hdr_lba_self != (uint64_t)offset
|| crc32(0, (void *)hdr, gptp->hdr_size) != gptp->hdr_crc_self) {
/* not a GPT */
(void)memset(gptp, 0, GPT_HDR_SIZE);
}
if (v_flag && gptp->hdr_size != 0) {
printf("Found %s GPT header CRC %"PRIu32" "
"at sector %"PRIdaddr", backup at %"PRIdaddr"\n",
tabletype, gptp->hdr_crc_self, offset, gptp->hdr_lba_alt);
}
return gptp->hdr_size;
}
int
delete_gpt(struct gpt_hdr *gptp)
{
char buf[512];
struct gpt_hdr *hdr = (void *)buf;
if (gptp->hdr_size == 0)
return 0;
/* don't accidently overwrite something important */
if (gptp->hdr_lba_self != GPT_HDR_BLKNO &&
gptp->hdr_lba_self != (uint64_t)disksectors - 1) {
warnx("given GPT header location doesn't seem correct");
return -1;
}
(void)memcpy(buf, gptp, GPT_HDR_SIZE);
/*
* Don't really delete GPT, just "disable" it, so it can
* be recovered later in case of mistake or something
*/
(void)memset(hdr->hdr_sig, 0, sizeof(gptp->hdr_sig));
if (write_disk(gptp->hdr_lba_self, hdr) == -1) {
warn("can't delete %s GPT header",
GPT_TYPE(gptp->hdr_lba_self));
return -1;
}
(void)memset(gptp, 0, GPT_HDR_SIZE);
return 1;
}