diff options
author | Kenneth R Westerback <krw@cvs.openbsd.org> | 2015-05-09 17:11:27 +0000 |
---|---|---|
committer | Kenneth R Westerback <krw@cvs.openbsd.org> | 2015-05-09 17:11:27 +0000 |
commit | 4d77cba94d3c55d7eeb6d7b959d46927a86cac34 (patch) | |
tree | 2df500fb7cc659c6451fb5855bb75601878507e7 | |
parent | 857855b69507af62a597ffdab66845ef8d9b2b15 (diff) |
Cleanup/rejig GPT code to be more readable, support different endian
archs and different sized disk sectors. Make MBR have higher priority
than GPT. Add many paranoia checks and associated DPRINTF's to make
further development easier. Keep everything hidden behind #ifdef
GPT.
Tested and ok doug@ mpi@. Nothing bad seen by millert@.
-rw-r--r-- | sys/arch/amd64/amd64/disksubr.c | 15 | ||||
-rw-r--r-- | sys/arch/i386/i386/disksubr.c | 15 | ||||
-rw-r--r-- | sys/kern/subr_disk.c | 445 | ||||
-rw-r--r-- | sys/sys/disklabel.h | 14 |
4 files changed, 266 insertions, 223 deletions
diff --git a/sys/arch/amd64/amd64/disksubr.c b/sys/arch/amd64/amd64/disksubr.c index 0a50edf5522..927aefe95dc 100644 --- a/sys/arch/amd64/amd64/disksubr.c +++ b/sys/arch/amd64/amd64/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.70 2015/04/15 14:06:03 naddy Exp $ */ +/* $OpenBSD: disksubr.c,v 1.71 2015/05/09 17:11:26 krw Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* @@ -94,12 +94,6 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; -#if defined(GPT) - error = readgptlabel(bp, strat, lp, NULL, spoofonly); - if (error == 0) - goto done; -#endif - error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; @@ -140,11 +134,8 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; -#if defined(GPT) - if (readgptlabel(bp, strat, lp, &partoff, 1) != 0) -#endif - if (readdoslabel(bp, strat, lp, &partoff, 1) != 0) - goto done; + if (readdoslabel(bp, strat, lp, &partoff, 1) != 0) + goto done; /* Read it in, slap the new label in, and write it back out */ bp->b_blkno = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR) * diff --git a/sys/arch/i386/i386/disksubr.c b/sys/arch/i386/i386/disksubr.c index 52ccb57917f..3b7c9dcd60e 100644 --- a/sys/arch/i386/i386/disksubr.c +++ b/sys/arch/i386/i386/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.108 2014/08/30 10:41:10 miod Exp $ */ +/* $OpenBSD: disksubr.c,v 1.109 2015/05/09 17:11:26 krw Exp $ */ /* $NetBSD: disksubr.c,v 1.21 1996/05/03 19:42:03 christos Exp $ */ /* @@ -93,12 +93,6 @@ readdisklabel(dev_t dev, void (*strat)(struct buf *), bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; -#if defined(GPT) - error = readgptlabel(bp, strat, lp, NULL, spoofonly); - if (error == 0) - goto done; -#endif - error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; @@ -139,11 +133,8 @@ writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp) bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; -#if defined(GPT) - if (readgptlabel(bp, strat, lp, &partoff, 1) != 0) -#endif - if (readdoslabel(bp, strat, lp, &partoff, 1) != 0) - goto done; + if (readdoslabel(bp, strat, lp, &partoff, 1) != 0) + goto done; /* Read it in, slap the new label in, and write it back out */ bp->b_blkno = DL_BLKTOSEC(lp, partoff + DOS_LABELSECTOR) * diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c index 058b04dc3dc..71adfbc7bf3 100644 --- a/sys/kern/subr_disk.c +++ b/sys/kern/subr_disk.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_disk.c,v 1.182 2015/03/15 15:13:31 krw Exp $ */ +/* $OpenBSD: subr_disk.c,v 1.183 2015/05/09 17:11:26 krw Exp $ */ /* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */ /* @@ -514,6 +514,14 @@ notmbr: } notfat: +#ifdef GPT + if (n == 0 && part_blkno == DOSBBSECTOR && ourpart == -1) { + error = readgptlabel(bp, strat, lp, partoffp, spoofonly); + if (error == 0) + return (0); + } +#endif + /* record the OpenBSD partition's placement for the caller */ if (partoffp) *partoffp = DL_SECTOBLK(lp, dospartoff); @@ -548,45 +556,22 @@ notfat: #ifdef GPT -int gpt_chk_hdr(struct gpt_header *); -int gpt_chk_parts(struct gpt_header *, struct gpt_partition *); -int get_fstype(struct uuid *); - -int -gpt_chk_hdr(struct gpt_header *gh) -{ - u_int32_t orig_gh_csum = gh->gh_csum; - gh->gh_csum = 0; - gh->gh_csum = crc32(0, (unsigned char *)gh, gh->gh_size); - - if (orig_gh_csum != gh->gh_csum) - return (EINVAL); - - return 0; -} - -int -gpt_chk_parts(struct gpt_header *gh, struct gpt_partition *gp) -{ - u_int32_t checksum; - checksum = crc32(0, (unsigned char *)gp, - gh->gh_part_num * gh->gh_part_size); - - if (checksum != gh->gh_part_csum) - return (EINVAL); - - return 0; -} +int gpt_get_fstype(struct uuid *); +int gpt_get_hdr(struct buf *, void (*strat)(struct buf *), + struct disklabel *, u_int64_t, struct gpt_header *); +struct gpt_partition *gpt_get_partition_table(dev_t, void (*)(struct buf *), + struct disklabel *, struct gpt_header *, u_int64_t *); int -get_fstype(struct uuid *uuid_part) +gpt_get_fstype(struct uuid *uuid_part) { static int init = 0; - static struct uuid uuid_openbsd, uuid_msdos, uuid_chromefs, - uuid_linux, uuid_hfs, uuid_unused; + static struct uuid uuid_openbsd, uuid_msdos, uuid_chromerootfs, + uuid_chromekernelfs, uuid_linux, uuid_hfs, uuid_unused; static const uint8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD; static const uint8_t gpt_uuid_msdos[] = GPT_UUID_MSDOS; static const uint8_t gpt_uuid_chromerootfs[] = GPT_UUID_CHROMEROOTFS; + static const uint8_t gpt_uuid_chromekernelfs[] = GPT_UUID_CHROMEKERNELFS; static const uint8_t gpt_uuid_linux[] = GPT_UUID_LINUX; static const uint8_t gpt_uuid_hfs[] = GPT_UUID_APPLE_HFS; static const uint8_t gpt_uuid_unused[] = GPT_UUID_UNUSED; @@ -594,7 +579,8 @@ get_fstype(struct uuid *uuid_part) if (init == 0) { uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd); uuid_dec_be(gpt_uuid_msdos, &uuid_msdos); - uuid_dec_be(gpt_uuid_chromerootfs, &uuid_chromefs); + uuid_dec_be(gpt_uuid_chromerootfs, &uuid_chromerootfs); + uuid_dec_be(gpt_uuid_chromekernelfs, &uuid_chromekernelfs); uuid_dec_be(gpt_uuid_linux, &uuid_linux); uuid_dec_be(gpt_uuid_hfs, &uuid_hfs); uuid_dec_be(gpt_uuid_unused, &uuid_unused); @@ -602,190 +588,259 @@ get_fstype(struct uuid *uuid_part) } if (!memcmp(uuid_part, &uuid_unused, sizeof(struct uuid))) - return FS_UNUSED; + return (FS_UNUSED); else if (!memcmp(uuid_part, &uuid_openbsd, sizeof(struct uuid))) - return FS_BSDFFS; + return (FS_BSDFFS); else if (!memcmp(uuid_part, &uuid_msdos, sizeof(struct uuid))) - return FS_MSDOS; - else if (!memcmp(uuid_part, &uuid_chromefs, sizeof(struct uuid))) - return FS_EXT2FS; + return (FS_MSDOS); + else if (!memcmp(uuid_part, &uuid_chromerootfs, sizeof(struct uuid))) + return (FS_EXT2FS); + else if (!memcmp(uuid_part, &uuid_chromekernelfs, sizeof(struct uuid))) + return (FS_MSDOS); else if (!memcmp(uuid_part, &uuid_linux, sizeof(struct uuid))) - return FS_EXT2FS; + return (FS_EXT2FS); else if (!memcmp(uuid_part, &uuid_hfs, sizeof(struct uuid))) - return FS_HFS; - else - return FS_OTHER; + return (FS_HFS); + else { + DPRINTF("Unknown GUID: %02x%02x%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x-%02x%02x%02x%02x%02x%02x\n", + *(((u_int8_t *)uuid_part) + 0), + *(((u_int8_t *)uuid_part) + 1), + *(((u_int8_t *)uuid_part) + 2), + *(((u_int8_t *)uuid_part) + 3), + *(((u_int8_t *)uuid_part) + 4), + *(((u_int8_t *)uuid_part) + 5), + *(((u_int8_t *)uuid_part) + 6), + *(((u_int8_t *)uuid_part) + 7), + *(((u_int8_t *)uuid_part) + 8), + *(((u_int8_t *)uuid_part) + 9), + *(((u_int8_t *)uuid_part) + 10), + *(((u_int8_t *)uuid_part) + 11), + *(((u_int8_t *)uuid_part) + 12), + *(((u_int8_t *)uuid_part) + 13), + *(((u_int8_t *)uuid_part) + 14), + *(((u_int8_t *)uuid_part) + 15) + ); + return (FS_OTHER); + } } -/* - * If gpt partition table requested, attempt to load it and - * find disklabel inside a GPT partition. Return buffer - * for use in signalling errors if requested. - * - * XXX: readgptlabel() is based on readdoslabel(), so they should be merged - */ int -readgptlabel(struct buf *bp, void (*strat)(struct buf *), - struct disklabel *lp, daddr_t *partoffp, int spoofonly) +gpt_get_hdr(struct buf *bp, void (*strat)(struct buf *), + struct disklabel *lp, u_int64_t gptlba, struct gpt_header *gh) { - struct gpt_header gh; - struct gpt_partition *gp, *gp_tmp; - size_t gpsz; - struct uuid uuid_part, uuid_openbsd; - struct partition *pp; + u_int64_t partlastlba; + int error, partspersec; + u_int32_t orig_gh_csum, new_gh_csum; - daddr_t part_blkno; - u_int64_t gptpartoff = 0, gptpartend = DL_GETBEND(lp); - int i, altheader = 0, error, n=0, ourpart = -1, offset; + bp->b_blkno = DL_SECTOBLK(lp, gptlba); + bp->b_bcount = lp->d_secsize; + bp->b_error = 0; /* B_ERROR and b_error may have stale data. */ + CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR); + SET(bp->b_flags, B_BUSY | B_READ | B_RAW); - static const u_int8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD; - u_int8_t fstype; + DPRINTF("gpt header being read from LBA %llu\n", gptlba); - uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd); + (*strat)(bp); - if (lp->d_secpercyl == 0) - return (EINVAL); /* invalid label */ - if (lp->d_secsize == 0) - return (ENOSPC); /* disk too small */ + error = biowait(bp); + if (error) { + DPRINTF("error reading gpt from disk (%d)\n", error); + return (1); + } + memcpy(gh, bp->b_data, sizeof(struct gpt_header)); - /* - * XXX: We should not trust the primary header and instead - * use the last LBA of the disk, as defined in the standard. - */ - for (part_blkno = GPTSECTOR; ; part_blkno = gh.gh_lba_alt, - altheader = 1) { - uint32_t ghsize; - uint32_t ghpartsize; - uint32_t ghpartnum; - - /* read header record */ - bp->b_blkno = DL_BLKTOSEC(lp, part_blkno) * DL_BLKSPERSEC(lp); - offset = DL_BLKOFFSET(lp, part_blkno); - bp->b_bcount = lp->d_secsize; - bp->b_error = 0; /* B_ERROR and b_error may have stale data. */ - CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR); - SET(bp->b_flags, B_BUSY | B_READ | B_RAW); - (*strat)(bp); - error = biowait(bp); + if (letoh64(gh->gh_sig) != GPTSIGNATURE) { + DPRINTF("gpt signature: expected 0x%llx, got 0x%llx\n", + GPTSIGNATURE, letoh64(gh->gh_sig)); + return (1); + } - if (error) { - DPRINTF("error reading from disk\n"); - /*wrong*/ if (partoffp) - /*wrong*/ *partoffp = -1; - return (error); - } + if (letoh32(gh->gh_rev) != GPTREVISION) { + DPRINTF("gpt revision: expected 0x%x, got 0x%x\n", + GPTREVISION, letoh32(gh->gh_rev)); + return (1); + } - bcopy(bp->b_data + offset, &gh, sizeof(gh)); - ghsize = letoh32(gh.gh_size); - ghpartsize = letoh32(gh.gh_part_size); - ghpartnum = letoh32(gh.gh_part_num); + if (letoh64(gh->gh_lba_self) != gptlba) { + DPRINTF("gpt self lba: expected %lld, got %llu\n", + gptlba, letoh64(gh->gh_lba_self)); + return (1); + } + if (letoh32(gh->gh_size) != GPTMINHDRSIZE) { + DPRINTF("gpt header size: expected %u, got %u\n", + GPTMINHDRSIZE, letoh32(gh->gh_size)); + return (1); + } - if (letoh64(gh.gh_sig) != GPTSIGNATURE) - return (EINVAL); + if (letoh32(gh->gh_part_size) != GPTMINPARTSIZE) { + DPRINTF("gpt partition entry size: expected %u, got %u\n", + GPTMINPARTSIZE, letoh32(gh->gh_part_size)); + return (1); + } - /* we only support version 1.0 */ - if (letoh32(gh.gh_rev) != GPTREVISION) - return (EINVAL); + if (letoh32(gh->gh_part_num) > GPTPARTITIONS) { + DPRINTF("gpt partition count: expected <= %u, got %u\n", + GPTPARTITIONS, letoh32(gh->gh_part_num)); + return (1); + } - if (gpt_chk_hdr(&gh)) { - /* header broken, using alternate header */ - if (altheader) { - DPRINTF("alternate header also broken\n"); - return (EINVAL); - } + orig_gh_csum = gh->gh_csum; + gh->gh_csum = 0; + new_gh_csum = crc32(0, (unsigned char *)gh, letoh32(gh->gh_size)); + gh->gh_csum = orig_gh_csum; + if (letoh32(orig_gh_csum) != new_gh_csum) { + DPRINTF("gpt header checksum: expected 0x%x, got 0x%x\n", + new_gh_csum, orig_gh_csum); + return (1); + } - if (gh.gh_lba_alt >= DL_GETDSIZE(lp)) { - DPRINTF("alternate header's position is " - "bogous\n"); - return (EINVAL); - } + if (letoh64(gh->gh_lba_end) >= DL_GETDSIZE(lp)) { + DPRINTF("gpt last usable LBA: expected < %lld, got %llu\n", + DL_GETDSIZE(lp), letoh64(gh->gh_lba_end)); + return (1); + } - continue; - } + if (letoh64(gh->gh_lba_start) >= letoh64(gh->gh_lba_end)) { + DPRINTF("gpt first usable LBA: expected < %llu, got %llu\n", + letoh64(gh->gh_lba_end), letoh64(gh->gh_lba_start)); + return (1); + } - /* - * Header size must be greater than or equal to 92 and less - * than or equal to the logical block size. - */ - if (ghsize < GPTMINHDRSIZE || ghsize > DEV_BSIZE) - return (EINVAL); + if (letoh64(gh->gh_part_lba) <= letoh64(gh->gh_lba_end) && + letoh64(gh->gh_part_lba) >= letoh64(gh->gh_lba_start)) { + DPRINTF("gpt partition table start LBA: expected < %llu or " + "> %llu, got %llu\n", letoh64(gh->gh_lba_start), + letoh64(gh->gh_lba_end), letoh64(gh->gh_part_lba)); + return (1); + } - if (letoh64(gh.gh_lba_start) >= DL_GETDSIZE(lp) || - letoh64(gh.gh_lba_end) >= DL_GETDSIZE(lp) || - letoh64(gh.gh_part_lba) >= DL_GETDSIZE(lp)) - return (EINVAL); + partspersec = lp->d_secsize / letoh32(gh->gh_part_size); + partlastlba = letoh64(gh->gh_part_lba) + + ((letoh32(gh->gh_part_num) + partspersec - 1) / partspersec) - 1; + if (partlastlba <= letoh64(gh->gh_lba_end) && + partlastlba >= letoh64(gh->gh_lba_start)) { + DPRINTF("gpt partition table last LBA: expected < %llu or " + "> %llu, got %llu\n", letoh64(gh->gh_lba_start), + letoh64(gh->gh_lba_end), partlastlba); + return (1); + } - /* - * Size per partition entry shall be 128*(2**n) with n >= 0. - * We don't support partition entries larger than block size. - */ - if (ghpartsize % GPTMINPARTSIZE - || ghpartsize > DEV_BSIZE - || GPT_PARTSPERSEC(&gh) == 0) { - DPRINTF("invalid partition size\n"); - return (EINVAL); - } + /* + * Other possible paranoia checks: + * 1) partition table starts before primary gpt lba. + * 2) partition table extends into lowest partition. + * 3) alt partition table starts before gh_lba_end. + */ + return (0); +} - /* XXX: we don't support multiples of GPTMINPARTSIZE yet */ - if (letoh32(gh.gh_part_size) != GPTMINPARTSIZE) { - DPRINTF("partition sizes larger than %d bytes are not " - "supported", GPTMINPARTSIZE); - return (EINVAL); - } +struct gpt_partition * +gpt_get_partition_table(dev_t dev, void (*strat)(struct buf *), + struct disklabel *lp, struct gpt_header *gh, u_int64_t *gpsz) +{ + struct buf *bp; + unsigned char *gp; + int error, secs; + uint32_t partspersec; + uint32_t checksum; + + partspersec = lp->d_secsize / letoh32(gh->gh_part_size); + if (partspersec * letoh32(gh->gh_part_size) != lp->d_secsize) { + DPRINTF("gpt partition table entry invalid size %u.\n", + letoh32(gh->gh_part_size)); + return (NULL); + } + secs = (letoh32(gh->gh_part_num) + partspersec - 1) / partspersec; + + gp = mallocarray(secs, lp->d_secsize, M_DEVBUF, M_NOWAIT | M_ZERO); + if (gp == NULL) { + DPRINTF("gpt partition table can't be allocated\n"); + return (NULL); + } + *gpsz = secs * lp->d_secsize; - /* read GPT partition entry array */ - gp = mallocarray(ghpartnum, sizeof(struct gpt_partition), M_DEVBUF, M_NOWAIT|M_ZERO); - if (gp == NULL) - return (ENOMEM); - gpsz = ghpartnum * sizeof(struct gpt_partition); + bp = geteblk((int)*gpsz); + bp->b_dev = dev; - /* - * XXX: Fails if # of partition entries is no multiple of - * GPT_PARTSPERSEC(&gh) - */ - for (i = 0; i < ghpartnum / GPT_PARTSPERSEC(&gh); - i++) { - part_blkno = letoh64(gh.gh_part_lba) + i; - /* read partition record */ - bp->b_blkno = DL_BLKTOSEC(lp, part_blkno) * - DL_BLKSPERSEC(lp); - offset = DL_BLKOFFSET(lp, part_blkno); - bp->b_bcount = lp->d_secsize; - /* B_ERROR and b_error may have stale data. */ - bp->b_error = 0; - CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR); - SET(bp->b_flags, B_BUSY | B_READ | B_RAW); - (*strat)(bp); - error = biowait(bp); - if (error) { - /*wrong*/ if (partoffp) - /*wrong*/ *partoffp = -1; - free(gp, M_DEVBUF, gpsz); - return (error); - } + bp->b_blkno = DL_SECTOBLK(lp, letoh64(gh->gh_part_lba)); + bp->b_bcount = *gpsz; + /* B_ERROR and b_error may have stale data. */ + bp->b_error = 0; + CLR(bp->b_flags, B_READ | B_WRITE | B_DONE | B_ERROR); + SET(bp->b_flags, B_BUSY | B_READ | B_RAW); - bcopy(bp->b_data + offset, gp + - i * GPT_PARTSPERSEC(&gh), GPT_PARTSPERSEC(&gh) * - sizeof(struct gpt_partition)); - } + DPRINTF("gpt partition table being read from LBA %llu\n", + letoh64(gh->gh_part_lba)); - if (gpt_chk_parts(&gh, gp)) { - DPRINTF("partition entries broken, using alternate " - "header\n"); - free(gp, M_DEVBUF, gpsz); + (*strat)(bp); - if (altheader) { - DPRINTF("alternate partition entries are also " - "broken\n"); - return (EINVAL); - } + error = biowait(bp); + if (error) { + DPRINTF("gpt partition table read error %d\n", error); + free(gp, M_DEVBUF, *gpsz); + gp = NULL; + goto done; + } - continue; - } - break; + checksum = crc32(0, bp->b_data, letoh32(gh->gh_part_num) * + letoh32(gh->gh_part_size)); + if (checksum == letoh32(gh->gh_part_csum)) + memcpy(gp, bp->b_data, *gpsz); + else { + DPRINTF("gpt partition table checksum: expected %x, got %x\n", + checksum, letoh32(gh->gh_part_csum)); + free(gp, M_DEVBUF, *gpsz); + gp = NULL; } +done: + bp->b_flags |= B_INVAL; + brelse(bp); + + return ((struct gpt_partition *)gp); +} + +/* + * If gpt partition table requested, attempt to load it and + * find disklabel inside a GPT partition. Return buffer + * for use in signalling errors if requested. + * + * XXX: readgptlabel() is based on readdoslabel(), so they should be merged + */ +int +readgptlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, + daddr_t *partoffp, int spoofonly) +{ + struct gpt_header gh, altgh; + struct gpt_partition *gp, *gp_tmp; + struct uuid uuid_part, uuid_openbsd; + struct partition *pp; + static const u_int8_t gpt_uuid_openbsd[] = GPT_UUID_OPENBSD; + u_int64_t gpsz; + u_int64_t gptpartoff = 0, gptpartend = DL_GETBEND(lp); + int i, error, n=0, ourpart = -1, offset, ghinvalid, altghinvalid; + u_int8_t fstype; + + uuid_dec_be(gpt_uuid_openbsd, &uuid_openbsd); + + if (lp->d_secpercyl == 0) + return (EINVAL); /* invalid label */ + if (lp->d_secsize == 0) + return (ENOSPC); /* disk too small */ + + ghinvalid = gpt_get_hdr(bp, strat, lp, GPTSECTOR, &gh); + altghinvalid = gpt_get_hdr(bp, strat, lp, DL_GETDSIZE(lp) - 1, &altgh); + if (ghinvalid && altghinvalid) + return(EINVAL); + if (ghinvalid) + gh = altgh; + + gp = gpt_get_partition_table(bp->b_dev, strat, lp, &gh, &gpsz); + if (gp == NULL) + return (EINVAL); + /* find OpenBSD partition */ for (gp_tmp = gp, i = 0; i < letoh32(gh.gh_part_num) && ourpart == -1; gp_tmp++, i++) { @@ -803,7 +858,7 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *), * In case the disklabel read below fails, we want to * provide a fake label in i-p. */ - fstype = get_fstype(&uuid_part); + fstype = gpt_get_fstype(&uuid_part); /* * Don't set fstype/offset/size when just looking for @@ -832,15 +887,16 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *), } else spoofonly = 1; /* No disklabel to read from disk. */ + free(gp, M_DEVBUF, gpsz); + if (!partoffp) /* Must not modify *lp when partoffp is set. */ lp->d_npartitions = MAXPARTITIONS; - free(gp, M_DEVBUF, gpsz); /* record the OpenBSD partition's placement for the caller */ if (partoffp) - *partoffp = gptpartoff; + *partoffp = DL_SECTOBLK(lp, gptpartoff); else { DL_SETBSTART(lp, gptpartoff); DL_SETBEND(lp, (gptpartend < DL_GETDSIZE(lp)) ? gptpartend : @@ -851,9 +907,10 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *), if (spoofonly) return (0); - bp->b_blkno = DL_BLKTOSEC(lp, gptpartoff + DOS_LABELSECTOR) * - DL_BLKSPERSEC(lp); - offset = DL_BLKOFFSET(lp, gptpartoff + DOS_LABELSECTOR); + bp->b_blkno = DL_BLKTOSEC(lp, DL_SECTOBLK(lp, gptpartoff) + + DOS_LABELSECTOR) * DL_BLKSPERSEC(lp); + offset = DL_BLKOFFSET(lp, DL_SECTOBLK(lp, gptpartoff) + + DOS_LABELSECTOR); bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); @@ -862,7 +919,11 @@ readgptlabel(struct buf *bp, void (*strat)(struct buf *), return (bp->b_error); /* sub-GPT disklabels are always at a LABELOFFSET of 0 */ - return checkdisklabel(bp->b_data + offset, lp, gptpartoff, gptpartend); + error = checkdisklabel(bp->b_data + offset, lp, + DL_GETBSTART((struct disklabel*)(bp->b_data+offset)), + DL_GETBEND((struct disklabel *)(bp->b_data+offset))); + + return (error); } #endif diff --git a/sys/sys/disklabel.h b/sys/sys/disklabel.h index 30f5fcf8b10..68e2cea0905 100644 --- a/sys/sys/disklabel.h +++ b/sys/sys/disklabel.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disklabel.h,v 1.64 2014/08/30 10:44:02 miod Exp $ */ +/* $OpenBSD: disklabel.h,v 1.65 2015/05/09 17:11:26 krw Exp $ */ /* $NetBSD: disklabel.h,v 1.41 1996/05/10 23:07:37 mark Exp $ */ /* @@ -387,7 +387,9 @@ struct partinfo { #define GPTSIGNATURE 0x5452415020494645LL /* ASCII string "EFI PART" encoded as 64-bit */ #define GPTREVISION 0x10000 /* GPT header version 1.0 */ -#define NGPTPARTITIONS 128 +#define GPTPARTITIONS 128 +#define GPTSYSTEM 0x0 +#define GPTIGNORE 0x1 #define GPTDOSACTIVE 0x2 #define GPTMINHDRSIZE 92 #define GPTMINPARTSIZE 128 @@ -422,13 +424,8 @@ struct gpt_partition { usually odd */ u_int64_t gp_attrs; /* attribute flags */ u_int16_t gp_name[36]; /* partition name, utf-16le */ - /* the rest of the GPT partition entry, if any, is reserved by UEFI - and must be zero */ }; -#define GPT_PARTSPERSEC(gh) (DEV_BSIZE / letoh32((gh)->gh_part_size)) -#define GPT_SECOFFSET(gh, n) ((gh)->gh_part_size * n) - #define GPT_UUID_UNUSED \ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } @@ -444,6 +441,9 @@ struct gpt_partition { #define GPT_UUID_OPENBSD \ { 0x82, 0x4c, 0xc7, 0xa0, 0x36, 0xa8, 0x11, 0xe3, \ 0x89, 0x0a, 0x95, 0x25, 0x19, 0xad, 0x3f, 0x61 } +#define GPT_UUID_CHROMEKERNELFS \ + { 0xfe, 0x3a, 0x2a, 0x5d, 0x4f, 0x32, 0x41, 0xa7, \ + 0xb7, 0x25, 0xac, 0xcc, 0x32, 0x85, 0xa3, 0x09 } #define GPT_UUID_CHROMEROOTFS \ { 0x3c, 0xb8, 0xe2, 0x02, 0x3b, 0x7e, 0x47, 0xdd, \ 0x8a, 0x3c, 0x7f, 0xf2, 0xa1, 0x3c, 0xfc, 0xec } |