tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
fdisk behavior on a gpt partitioned disks
Hello,
as EFI goes forward it becomes a more and more common case when a
reused disk partitioned in MBR style can contain GPT as well (usually
just because its deletion wasn't carried before). It's not a problem on
usual PCs, but EFI compliant systems are have to use GUID partition
tables, and therefore they are just ignoring MBR layout. This is the
problem.
The simple solution here is just remove GUID tables from the disk by
issuing "gpt destroy" command (see gpt(8) for details). However, I
heard a lot from other people that fdisk(8) should take care about this
problem too. Well, if you're one from those guys, please examine
attached patch :-)
The patch implements the following logic:
- always warn if disk have GPT
- in interactive mode: explicitly warn that any change to MBR will
result in GPT removal, ask for confirmation, and remove GPT
- in non-interactive mode: remove GPT and explicitly note this fact
--
Cheers,
Mishka.
Index: Makefile
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/Makefile,v
retrieving revision 1.38
diff -u -r1.38 Makefile
--- Makefile 29 Nov 2007 23:19:25 -0000 1.38
+++ Makefile 29 May 2009 11:33:10 -0000
@@ -18,7 +18,7 @@
.if (${HOSTPROG:U} == "")
SUBDIR= mbr
-DPADD+= ${LIBUTIL}
-LDADD+= -lutil
+DPADD+= ${LIBUTIL} ${LIBZ}
+LDADD+= -lutil -lz
.include <bsd.subdir.mk>
.endif
Index: fdisk.c
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.116.6.1
diff -u -r1.116.6.1 fdisk.c
--- fdisk.c 20 Apr 2009 23:16:45 -0000 1.116.6.1
+++ fdisk.c 29 May 2009 11:33:12 -0000
@@ -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 */
@@ -245,6 +248,9 @@
int get_params(void);
int read_s0(daddr_t, struct mbr_sector *);
int write_mbr(void);
+int get_gpt(void);
+int read_gpt(daddr_t, struct gpt_hdr *);
+int delete_gpt(int);
int yesno(const char *, ...);
int decimal(const char *, int, int, int, int);
#define DEC_SEC 1 /* asking for a sector number */
@@ -291,6 +297,7 @@
size_t len;
char *cp;
int n;
+ int gptm = 0;
#ifdef BOOTSEL
daddr_t default_ptn; /* start sector of default ptn */
char *cbootmenu = 0;
@@ -298,7 +305,8 @@
int csysid; /* For the b_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;
@@ -444,6 +452,10 @@
/* must have been a blank disk */
init_sector0(1);
+ gptm = get_gpt();
+ if (gptm)
+ warnx("The disk is carrying GUID Partition Tables");
+
#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H
get_geometry();
#else
@@ -509,10 +521,20 @@
"yet. This is your last chance.\n");
if (u_flag)
print_s0(-1);
- if (yesno("Should we write new partition table?"))
+ if (gptm)
+ 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(gptm);
write_mbr();
- } else
+ }
+ } else {
+ if (delete_gpt(gptm) > 0)
+ warnx("GPT headers were deleted");
write_mbr();
+ }
}
exit(0);
@@ -2777,3 +2799,79 @@
return ("unknown");
return (ptr->name);
}
+
+int
+get_gpt(void)
+{
+ int gptm = 0;
+ struct gpt_hdr *gptp;
+
+ if ((gptp = malloc(512)) == NULL)
+ err(1, "Malloc failed");
+
+ if (read_gpt(GPT_HDR_BLKNO, gptp) == 1)
+ gptm |= 1;
+ if (read_gpt(disksectors - 1, gptp) == 1)
+ gptm |= 2;
+
+ free(gptp);
+ return (gptm);
+}
+
+int
+read_gpt(daddr_t offset, struct gpt_hdr *gptp)
+{
+ int rc = 1;
+ struct gpt_hdr *buf;
+ const char *tabletype =
+ offset == GPT_HDR_BLKNO ? "primary" : "secondary";
+
+ memset(gptp, 0, sizeof(struct gpt_hdr));
+ if (read_disk(offset, gptp) == -1) {
+ warn("Can't read %s GPT header", tabletype);
+ return -1;
+ }
+
+ if ((buf = malloc(512)) == NULL)
+ err(1, "Malloc failed");
+ memcpy(buf, gptp, 512);
+ buf->hdr_crc_self = 0;
+
+ if (memcmp(gptp->hdr_sig, GPT_HDR_SIG, sizeof(gptp->hdr_sig))
+ || gptp->hdr_lba_self != offset
+ || crc32(0, (void *)buf, gptp->hdr_size)
+ != gptp->hdr_crc_self)
+ /* not a GPT */
+ rc = 0;
+
+ if (rc && v_flag)
+ printf("Found %s GPT header CRC %"PRIu32" "
+ "at sector %"PRIdaddr", backup at %"PRIdaddr".\n",
+ tabletype, gptp->hdr_crc_self,
+ offset, gptp->hdr_lba_alt);
+ free(buf);
+ return (rc);
+}
+
+int
+delete_gpt(int gptm)
+{
+ int rc = 0;
+ void *buf;
+
+ if ((buf = calloc(1, 512)) == NULL)
+ err(1, "Malloc failed");
+
+ if (gptm&1 && (rc = write_disk(1, buf)) == -1) {
+ warn("can't delete primary GPT header");
+ goto delete_gpt_exit;
+ }
+ if (gptm&2 && (rc = write_disk(disksectors - 1, buf)) == -1) {
+ warn("can't delete secondary GPT header");
+ goto delete_gpt_exit;
+ }
+
+ delete_gpt_exit:
+ free(buf);
+ return (rc);
+}
Home |
Main Index |
Thread Index |
Old Index