Module Name: src
Committed By: christos
Date: Mon Jun 1 19:57:33 UTC 2009
Modified Files:
src/sbin/fdisk: Makefile fdisk.8 fdisk.c
Log Message:
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
To generate a diff of this commit:
cvs rdiff -u -r1.39 -r1.40 src/sbin/fdisk/Makefile
cvs rdiff -u -r1.59 -r1.60 src/sbin/fdisk/fdisk.8
cvs rdiff -u -r1.120 -r1.121 src/sbin/fdisk/fdisk.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sbin/fdisk/Makefile
diff -u src/sbin/fdisk/Makefile:1.39 src/sbin/fdisk/Makefile:1.40
--- src/sbin/fdisk/Makefile:1.39 Mon Apr 6 08:19:16 2009
+++ src/sbin/fdisk/Makefile Mon Jun 1 15:57:33 2009
@@ -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 @@
.if (${HOSTPROG:U} == "")
SUBDIR= mbr
-DPADD+= ${LIBUTIL}
-LDADD+= -lutil
+DPADD+= ${LIBUTIL} ${LIBZ}
+LDADD+= -lutil -lz
.include <bsd.subdir.mk>
.endif
Index: src/sbin/fdisk/fdisk.8
diff -u src/sbin/fdisk/fdisk.8:1.59 src/sbin/fdisk/fdisk.8:1.60
--- src/sbin/fdisk/fdisk.8:1.59 Sun Jan 20 10:04:09 2008
+++ src/sbin/fdisk/fdisk.8 Mon Jun 1 15:57:33 2009
@@ -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 @@
.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 @@
.Xr disktab 5 ,
.Xr boot 8 ,
.Xr disklabel 8 ,
+.Xr gpt 8 ,
.Xr installboot 8 ,
.Xr mbr 8 ,
.Xr mbrlabel 8
Index: src/sbin/fdisk/fdisk.c
diff -u src/sbin/fdisk/fdisk.c:1.120 src/sbin/fdisk/fdisk.c:1.121
--- src/sbin/fdisk/fdisk.c:1.120 Mon Apr 20 13:06:55 2009
+++ src/sbin/fdisk/fdisk.c Mon Jun 1 15:57:33 2009
@@ -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 @@
#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 @@
#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 = 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 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 @@
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 @@
/* 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 @@
"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 @@
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;
+}