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; +}