aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stand/i386/zfsboot/zfsboot.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/stand/i386/zfsboot/zfsboot.c b/stand/i386/zfsboot/zfsboot.c
index fe3c5d1e6b07..076f96da05f8 100644
--- a/stand/i386/zfsboot/zfsboot.c
+++ b/stand/i386/zfsboot/zfsboot.c
@@ -460,6 +460,33 @@ copy_dsk(struct zfsdsk *zdsk)
}
/*
+ * Get disk size from GPT.
+ */
+static uint64_t
+drvsize_gpt(struct dsk *dskp)
+{
+#ifdef GPT
+ struct gpt_hdr hdr;
+ char *sec;
+
+ sec = dmadat->secbuf;
+ if (drvread(dskp, sec, 1, 1))
+ return (0);
+
+ memcpy(&hdr, sec, sizeof(hdr));
+ if (memcmp(hdr.hdr_sig, GPT_HDR_SIG, sizeof(hdr.hdr_sig)) != 0 ||
+ hdr.hdr_lba_self != 1 || hdr.hdr_revision < 0x00010000 ||
+ hdr.hdr_entsz < sizeof(struct gpt_ent) ||
+ DEV_BSIZE % hdr.hdr_entsz != 0) {
+ return (0);
+ }
+ return (hdr.hdr_lba_alt + 1);
+#else
+ return (0);
+#endif
+}
+
+/*
* Get disk size from eax=0x800 and 0x4800. We need to probe both
* because 0x4800 may not be available and we would like to get more
* or less correct disk size - if it is possible at all.
@@ -475,6 +502,11 @@ drvsize_ext(struct zfsdsk *zdsk)
dskp = &zdsk->dsk;
+ /* Try to read disk size from GPT */
+ size = drvsize_gpt(dskp);
+ if (size != 0)
+ return (size);
+
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
v86.eax = 0x800;