tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: GPT attributes in dkwedge [PATCH]



On Tue, Sep 12, 2023 at 05:21:06PM +0000, Emmanuel Dreyfus wrote:
> > But Michaels question is a good one - why can't the bootloader deal
> > with all this and pass e.g. the start offset of the root partition
> > via (optional) boot params?
> 
> I will have a look at that, but I am not sure how it works with multiboot.

multitboot lets the bootloader pass boot device information as BIOS
driver, partition number, subpartition number. This is intended
for MBR extended partitions or MBR/disklabel.

I came to another solution, that mutualize the GPT code for dkwedge
and raidframe. We parse the GPT again for raidframe, but at least
the code is not duplicated. Patch is attached.

-- 
Emmanuel Dreyfus
manu%netbsd.org@localhost
--- /dev/null	2023-09-14 08:31:14.440901131 +0200
+++ sys/dev/gpt.c	2023-09-13 10:42:30.114260653 +0200
@@ -0,0 +1,302 @@
+/*	$NetBSD$ */
+
+/*-
+ * Copyright (c) 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * EFI GUID Partition Table support for disk wedges
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/proc.h>
+#include <sys/fcntl.h>
+#include <sys/errno.h>
+#include <sys/disk.h>
+#include <sys/vnode.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+
+#include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
+#include <sys/uuid.h>
+
+/* UTF-8 encoding stuff */
+#include <fs/unicode.h>
+
+/*
+ * Copied from dkwedge_compute_pdev:
+ *
+ *	Compute the parent disk's dev_t.
+ */
+static int
+gpt_compute_pdev(const char *pname, dev_t *pdevp, enum vtype type)
+{
+	const char *name, *cp;
+	devmajor_t pmaj;
+	int punit;
+	char devname[16];
+
+	name = pname;
+	switch (type) {
+	case VBLK:
+		pmaj = devsw_name2blk(name, devname, sizeof(devname));
+		break;
+	case VCHR:
+		pmaj = devsw_name2chr(name, devname, sizeof(devname));
+		break;
+	default:
+		pmaj = NODEVMAJOR;
+		break;
+	}
+	if (pmaj == NODEVMAJOR)
+		return ENXIO;
+
+	name += strlen(devname);
+	for (cp = name, punit = 0; *cp >= '0' && *cp <= '9'; cp++)
+		punit = (punit * 10) + (*cp - '0');
+	if (cp == name) {
+		/* Invalid parent disk name. */
+		return ENXIO;
+	}
+
+	*pdevp = MAKEDISKDEV(pmaj, punit, RAW_PART);
+
+	return 0;
+}
+
+static int
+gpt_verify_header_crc(struct gpt_hdr *hdr)
+{
+	uint32_t crc;
+	int rv;
+
+	crc = hdr->hdr_crc_self;
+	hdr->hdr_crc_self = 0;
+	rv = le32toh(crc) == crc32(0, (void *)hdr, le32toh(hdr->hdr_size));
+	hdr->hdr_crc_self = crc;
+
+	return (rv);
+}
+
+int
+gpt_vn_walk(struct disk *pdk, struct vnode *vp,
+            int (*callback)(struct gpt_ent *, int, void *), void *data)
+{
+	static const struct uuid ent_type_unused = GPT_ENT_TYPE_UNUSED;
+	static const char gpt_hdr_sig[] = GPT_HDR_SIG;
+	struct buf *bp;
+	uint32_t secsize;
+	struct gpt_hdr *hdr;
+	struct gpt_ent *ent;
+	uint32_t entries, entsz;
+	daddr_t lba_start, lba_end, lba_table;
+	uint32_t gpe_crc;
+	int error;
+	u_int i;
+	size_t sz;
+
+	secsize = DEV_BSIZE << pdk->dk_blkshift;
+	bp = geteblk(secsize);
+
+	/*
+	 * Note: We don't bother with a Legacy or Protective MBR
+	 * here.  If a GPT is found, then the search stops, and
+	 * the GPT is authoritative.
+	 */
+
+	/* Read in the GPT Header. */
+	error = dkwedge_read(pdk, vp, GPT_HDR_BLKNO << pdk->dk_blkshift,
+	    bp->b_data, secsize);
+	if (error)
+		goto out;
+	hdr = bp->b_data;
+
+	/* Validate it. */
+	if (memcmp(gpt_hdr_sig, hdr->hdr_sig, sizeof(hdr->hdr_sig)) != 0) {
+		/* XXX Should check at end-of-disk. */
+		error = ESRCH;
+		goto out;
+	}
+	if (hdr->hdr_revision != htole32(GPT_HDR_REVISION)) {
+		/* XXX Should check at end-of-disk. */
+		error = ESRCH;
+		goto out;
+	}
+	if (le32toh(hdr->hdr_size) > secsize) {
+		/* XXX Should check at end-of-disk. */
+		error = ESRCH;
+		goto out;
+	}
+	if (gpt_verify_header_crc(hdr) == 0) {
+		/* XXX Should check at end-of-disk. */
+		error = ESRCH;
+		goto out;
+	}
+
+	/* XXX Now that we found it, should we validate the backup? */
+
+	{
+		struct uuid disk_guid;
+		char guid_str[UUID_STR_LEN];
+		uuid_dec_le(hdr->hdr_guid, &disk_guid);
+		uuid_snprintf(guid_str, sizeof(guid_str), &disk_guid);
+		aprint_verbose("%s: GPT GUID: %s\n", pdk->dk_name, guid_str);
+	}
+
+	entries = le32toh(hdr->hdr_entries);
+	entsz = roundup(le32toh(hdr->hdr_entsz), 8);
+	if (entsz != sizeof(struct gpt_ent)) {
+		aprint_error("%s: bogus GPT entry size: %u\n",
+		    pdk->dk_name, le32toh(hdr->hdr_entsz));
+		error = EINVAL;
+		goto out;
+	}
+	gpe_crc = le32toh(hdr->hdr_crc_table);
+
+	/* XXX Clamp entries at 512 for now. */
+	if (entries > 512) {
+		aprint_error("%s: WARNING: clamping number of GPT entries to "
+		    "512 (was %u)\n", pdk->dk_name, entries);
+		entries = 512;
+	}
+
+	lba_start = le64toh(hdr->hdr_lba_start);
+	lba_end = le64toh(hdr->hdr_lba_end);
+	lba_table = le64toh(hdr->hdr_lba_table);
+	if (lba_start < 0 || lba_end < 0 || lba_table < 0) {
+		aprint_error("%s: GPT block numbers out of range\n",
+		    pdk->dk_name);
+		error = EINVAL;
+		goto out;
+	}
+
+	brelse(bp, 0);
+
+	sz = roundup(entries * entsz, secsize);
+	bp = geteblk(sz);
+	error = dkwedge_read(pdk, vp, lba_table << pdk->dk_blkshift,
+	    bp->b_data, sz);
+	if (error) {
+		/* XXX Should check alternate location. */
+		aprint_error("%s: unable to read GPT partition array, "
+		    "error = %d\n", pdk->dk_name, error);
+		goto out;
+	}
+
+	if (crc32(0, bp->b_data, entries * entsz) != gpe_crc) {
+		/* XXX Should check alternate location. */
+		aprint_error("%s: bad GPT partition array CRC\n",
+		    pdk->dk_name);
+		error = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * Walk the partitions, adding a wedge for each type we know about.
+	 */
+	for (i = 0; i < entries; i++) {
+		struct uuid ptype_guid;
+
+		ent = (struct gpt_ent *)((char *)bp->b_data + (i * entsz));
+
+		uuid_dec_le(ent->ent_type, &ptype_guid);
+		if (memcmp(&ptype_guid, &ent_type_unused,
+			   sizeof(ptype_guid)) == 0)
+			continue;
+
+		if (callback(ent, i, data) != 0)
+			break;
+	}
+	error = 0;
+
+ out:
+	brelse(bp, 0);
+	return (error);
+}
+
+int
+gpt_walk(struct disk *pdk,
+         int (*callback)(struct gpt_ent *, int, void *), void *data)
+{
+	struct vnode *vp;
+	int error, error2;
+	dev_t pdev;
+
+	/*
+	 * Use the character device for scanning, the block device
+	 * is busy if there are already wedges attached.
+	 */
+	error = gpt_compute_pdev(pdk->dk_name, &pdev, VCHR);
+	if (error) {
+		aprint_error("%s: unable to compute pdev, error = %d\n",
+		    pdk->dk_name, error);
+		goto out;
+	}
+
+	error = cdevvp(pdev, &vp);
+	if (error) {
+		aprint_error("%s: unable to find vnode for pdev, error = %d\n",
+		    pdk->dk_name, error);
+		goto out;
+	}
+
+	error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+	if (error) {
+		aprint_error("%s: unable to lock vnode for pdev, error = %d\n",
+		    pdk->dk_name, error);
+		vrele(vp);
+		goto out;
+	}
+
+	error = VOP_OPEN(vp, FREAD | FSILENT, NOCRED);
+	if (error) {
+		if (error != ENXIO)
+			aprint_error("%s: unable to open device, error = %d\n",
+			    pdk->dk_name, error);
+		vput(vp);
+		goto out;
+	}
+	VOP_UNLOCK(vp);
+
+	error = gpt_vn_walk(pdk, vp, callback, data);
+
+	error2 = vn_close(vp, FREAD, NOCRED);
+	if (error2) {
+		aprint_error("%s: unable to close device, error = %d\n",
+		    pdk->dk_name, error2);
+		/* We'll just assume the vnode has been cleaned up. */
+	}
+
+out:
+	return error;
+}
Index: sys/sys/disk.h
===================================================================
RCS file: /cvsroot/src/sys/sys/disk.h,v
retrieving revision 1.78
diff -U4 -r1.78 disk.h
--- sys/sys/disk.h	9 May 2023 12:04:04 -0000	1.78
+++ sys/sys/disk.h	14 Sep 2023 06:31:22 -0000
@@ -532,8 +532,9 @@
 
 extern	int disk_count;			/* number of disks in global disklist */
 
 struct proc;
+struct gpt_ent;
 
 void	disk_rename(struct disk *, const char *);
 void	disk_attach(struct disk *);
 int	disk_begindetach(struct disk *, int (*)(device_t), device_t, int);
@@ -561,7 +562,13 @@
 const char *dkwedge_get_parent_name(dev_t);
 void	dkwedge_print_wnames(void);
 device_t dkwedge_find_partition(device_t, daddr_t, uint64_t);
 
+int	gpt_vn_walk(struct disk *, struct vnode *,
+		    int (*)(struct gpt_ent *, int, void *), void *);
+int	gpt_walk(struct disk *,
+		 int (*)(struct gpt_ent *, int, void *), void *);
+
+
 #endif /* _KERNEL */
 
 #endif /* _SYS_DISK_H_ */
Index: sys/dev/files.dev
===================================================================
RCS file: /cvsroot/src/sys/dev/files.dev,v
retrieving revision 1.9
diff -U4 -r1.9 files.dev
--- sys/dev/files.dev	4 Jun 2022 03:31:10 -0000	1.9
+++ sys/dev/files.dev	14 Sep 2023 06:31:22 -0000
@@ -14,8 +14,9 @@
 file	dev/dkwedge/dkwedge_mbr.c	dkwedge_method_mbr
 file	dev/dkwedge/dkwedge_rdb.c	dkwedge_method_rdb
 file	dev/firmload.c			firmload
 file	dev/fss.c			fss
+file	dev/gpt.c			kern    # XXX
 file	dev/keylock.c			keylock
 file	dev/lockstat.c			lockstat		needs-flag
 file	dev/md.c			md
 file	dev/mm.c			kern	# XXX
Index: sys/dev/dkwedge/dkwedge_gpt.c
===================================================================
RCS file: /cvsroot/src/sys/dev/dkwedge/dkwedge_gpt.c,v
retrieving revision 1.26
diff -U4 -r1.26 dkwedge_gpt.c
--- sys/dev/dkwedge/dkwedge_gpt.c	11 Apr 2020 16:00:34 -0000	1.26
+++ sys/dev/dkwedge/dkwedge_gpt.c	14 Sep 2023 06:31:22 -0000
@@ -95,213 +95,84 @@
 	return (DKW_PTYPE_UNKNOWN);
 }
 
 static int
-gpt_verify_header_crc(struct gpt_hdr *hdr)
+dkwedge_discover_gpt_cb(struct gpt_ent *ent, int partnum, void *data)
 {
-	uint32_t crc;
-	int rv;
+	struct disk *pdk = data;
+        struct dkwedge_info dkw;
+        int error;
+        size_t r, n;
+        uint8_t *c;
+	struct uuid ptype_guid, ent_guid;
+	const char *ptype;
+	int j;
+	char ptype_guid_str[UUID_STR_LEN], ent_guid_str[UUID_STR_LEN];
+
+	uuid_dec_le(ent->ent_type, &ptype_guid);
+	uuid_dec_le(ent->ent_guid, &ent_guid);
+	uuid_snprintf(ptype_guid_str, sizeof(ptype_guid_str),
+	    &ptype_guid);
+	uuid_snprintf(ent_guid_str, sizeof(ent_guid_str),
+	    &ent_guid);
+
+	memset(&dkw, 0, sizeof(dkw));
+
+	/* figure out the type */
+	ptype = gpt_ptype_guid_to_str(&ptype_guid);
+	strlcpy(dkw.dkw_ptype, ptype, sizeof(dkw.dkw_ptype));
+
+	strlcpy(dkw.dkw_parent, pdk->dk_name, sizeof(dkw.dkw_parent));
+	dkw.dkw_offset = le64toh(ent->ent_lba_start);
+	dkw.dkw_size = le64toh(ent->ent_lba_end) - dkw.dkw_offset + 1;
+
+	/* XXX Make sure it falls within the disk's data area. */
+
+	if (ent->ent_name[0] == 0x0000)
+		strlcpy(dkw.dkw_wname, ent_guid_str, sizeof(dkw.dkw_wname));
+	else {
+		c = dkw.dkw_wname;
+		r = sizeof(dkw.dkw_wname) - 1;
+		for (j = 0; j < __arraycount(ent->ent_name)
+		    && ent->ent_name[j] != 0x0000; j++) {
+			n = wput_utf8(c, r, le16toh(ent->ent_name[j]));
+			if (n == 0)
+				break;
+			c += n; r -= n;
+		}
+		*c = '\0';
+	}
 
-	crc = hdr->hdr_crc_self;
-	hdr->hdr_crc_self = 0;
-	rv = le32toh(crc) == crc32(0, (void *)hdr, le32toh(hdr->hdr_size));
-	hdr->hdr_crc_self = crc;
+	/*
+	 * Try with the partition name first.  If that fails,
+	 * use the GUID string.  If that fails, punt.
+	 */
+	if ((error = dkwedge_add(&dkw)) == EEXIST &&
+	    strcmp(dkw.dkw_wname, ent_guid_str) != 0) {
+		char orig[sizeof(dkw.dkw_wname)];
+		strlcpy(orig, dkw.dkw_wname, sizeof(orig));
+		strlcpy(dkw.dkw_wname, ent_guid_str, sizeof(dkw.dkw_wname));
+		error = dkwedge_add(&dkw);
+		if (!error)
+			aprint_error("%s: wedge named '%s' already "
+			    "existed, using '%s'\n", pdk->dk_name,
+			    orig, ent_guid_str);
+	}
+	if (error == EEXIST)
+		aprint_error("%s: wedge named '%s' already exists, "
+		    "manual intervention required\n", pdk->dk_name,
+		    dkw.dkw_wname);
+	else if (error)
+		aprint_error("%s: error %d adding entry %u (%s), "
+		    "type %s\n", pdk->dk_name, error, partnum, ent_guid_str,
+		    ptype_guid_str);
 
-	return (rv);
+	return error;
 }
 
 static int
 dkwedge_discover_gpt(struct disk *pdk, struct vnode *vp)
 {
-	static const struct uuid ent_type_unused = GPT_ENT_TYPE_UNUSED;
-	static const char gpt_hdr_sig[] = GPT_HDR_SIG;
-	struct dkwedge_info dkw;
-	struct buf *bp;
-	uint32_t secsize;
-	struct gpt_hdr *hdr;
-	struct gpt_ent *ent;
-	uint32_t entries, entsz;
-	daddr_t lba_start, lba_end, lba_table;
-	uint32_t gpe_crc;
-	int error;
-	u_int i;
-	size_t r, n, sz;
-	uint8_t *c;
-
-	secsize = DEV_BSIZE << pdk->dk_blkshift;
-	bp = geteblk(secsize);
-
-	/*
-	 * Note: We don't bother with a Legacy or Protective MBR
-	 * here.  If a GPT is found, then the search stops, and
-	 * the GPT is authoritative.
-	 */
-
-	/* Read in the GPT Header. */
-	error = dkwedge_read(pdk, vp, GPT_HDR_BLKNO << pdk->dk_blkshift,
-	    bp->b_data, secsize);
-	if (error)
-		goto out;
-	hdr = bp->b_data;
-
-	/* Validate it. */
-	if (memcmp(gpt_hdr_sig, hdr->hdr_sig, sizeof(hdr->hdr_sig)) != 0) {
-		/* XXX Should check at end-of-disk. */
-		error = ESRCH;
-		goto out;
-	}
-	if (hdr->hdr_revision != htole32(GPT_HDR_REVISION)) {
-		/* XXX Should check at end-of-disk. */
-		error = ESRCH;
-		goto out;
-	}
-	if (le32toh(hdr->hdr_size) > secsize) {
-		/* XXX Should check at end-of-disk. */
-		error = ESRCH;
-		goto out;
-	}
-	if (gpt_verify_header_crc(hdr) == 0) {
-		/* XXX Should check at end-of-disk. */
-		error = ESRCH;
-		goto out;
-	}
-
-	/* XXX Now that we found it, should we validate the backup? */
-
-	{
-		struct uuid disk_guid;
-		char guid_str[UUID_STR_LEN];
-		uuid_dec_le(hdr->hdr_guid, &disk_guid);
-		uuid_snprintf(guid_str, sizeof(guid_str), &disk_guid);
-		aprint_verbose("%s: GPT GUID: %s\n", pdk->dk_name, guid_str);
-	}
-
-	entries = le32toh(hdr->hdr_entries);
-	entsz = roundup(le32toh(hdr->hdr_entsz), 8);
-	if (entsz != sizeof(struct gpt_ent)) {
-		aprint_error("%s: bogus GPT entry size: %u\n",
-		    pdk->dk_name, le32toh(hdr->hdr_entsz));
-		error = EINVAL;
-		goto out;
-	}
-	gpe_crc = le32toh(hdr->hdr_crc_table);
-
-	/* XXX Clamp entries at 512 for now. */
-	if (entries > 512) {
-		aprint_error("%s: WARNING: clamping number of GPT entries to "
-		    "512 (was %u)\n", pdk->dk_name, entries);
-		entries = 512;
-	}
-
-	lba_start = le64toh(hdr->hdr_lba_start);
-	lba_end = le64toh(hdr->hdr_lba_end);
-	lba_table = le64toh(hdr->hdr_lba_table);
-	if (lba_start < 0 || lba_end < 0 || lba_table < 0) {
-		aprint_error("%s: GPT block numbers out of range\n",
-		    pdk->dk_name);
-		error = EINVAL;
-		goto out;
-	}
-
-	brelse(bp, 0);
-
-	sz = roundup(entries * entsz, secsize);
-	bp = geteblk(sz);
-	error = dkwedge_read(pdk, vp, lba_table << pdk->dk_blkshift,
-	    bp->b_data, sz);
-	if (error) {
-		/* XXX Should check alternate location. */
-		aprint_error("%s: unable to read GPT partition array, "
-		    "error = %d\n", pdk->dk_name, error);
-		goto out;
-	}
-
-	if (crc32(0, bp->b_data, entries * entsz) != gpe_crc) {
-		/* XXX Should check alternate location. */
-		aprint_error("%s: bad GPT partition array CRC\n",
-		    pdk->dk_name);
-		error = EINVAL;
-		goto out;
-	}
-
-	/*
-	 * Walk the partitions, adding a wedge for each type we know about.
-	 */
-	for (i = 0; i < entries; i++) {
-		struct uuid ptype_guid, ent_guid;
-		const char *ptype;
-		int j;
-		char ptype_guid_str[UUID_STR_LEN], ent_guid_str[UUID_STR_LEN];
-
-		ent = (struct gpt_ent *)((char *)bp->b_data + (i * entsz));
-
-		uuid_dec_le(ent->ent_type, &ptype_guid);
-		if (memcmp(&ptype_guid, &ent_type_unused,
-			   sizeof(ptype_guid)) == 0)
-			continue;
-
-		uuid_dec_le(ent->ent_guid, &ent_guid);
-
-		uuid_snprintf(ptype_guid_str, sizeof(ptype_guid_str),
-		    &ptype_guid);
-		uuid_snprintf(ent_guid_str, sizeof(ent_guid_str),
-		    &ent_guid);
-
-		memset(&dkw, 0, sizeof(dkw));
-
-		/* figure out the type */
-		ptype = gpt_ptype_guid_to_str(&ptype_guid);
-		strlcpy(dkw.dkw_ptype, ptype, sizeof(dkw.dkw_ptype));
-
-		strlcpy(dkw.dkw_parent, pdk->dk_name, sizeof(dkw.dkw_parent));
-		dkw.dkw_offset = le64toh(ent->ent_lba_start);
-		dkw.dkw_size = le64toh(ent->ent_lba_end) - dkw.dkw_offset + 1;
-
-		/* XXX Make sure it falls within the disk's data area. */
-
-		if (ent->ent_name[0] == 0x0000)
-			strlcpy(dkw.dkw_wname, ent_guid_str, sizeof(dkw.dkw_wname));
-		else {
-			c = dkw.dkw_wname;
-			r = sizeof(dkw.dkw_wname) - 1;
-			for (j = 0; j < __arraycount(ent->ent_name)
-			    && ent->ent_name[j] != 0x0000; j++) {
-				n = wput_utf8(c, r, le16toh(ent->ent_name[j]));
-				if (n == 0)
-					break;
-				c += n; r -= n;
-			}
-			*c = '\0';
-		}
-
-		/*
-		 * Try with the partition name first.  If that fails,
-		 * use the GUID string.  If that fails, punt.
-		 */
-		if ((error = dkwedge_add(&dkw)) == EEXIST &&
-		    strcmp(dkw.dkw_wname, ent_guid_str) != 0) {
-			char orig[sizeof(dkw.dkw_wname)];
-			strlcpy(orig, dkw.dkw_wname, sizeof(orig));
-			strlcpy(dkw.dkw_wname, ent_guid_str, sizeof(dkw.dkw_wname));
-			error = dkwedge_add(&dkw);
-			if (!error)
-				aprint_error("%s: wedge named '%s' already "
-				    "existed, using '%s'\n", pdk->dk_name,
-				    orig, ent_guid_str);
-		}
-		if (error == EEXIST)
-			aprint_error("%s: wedge named '%s' already exists, "
-			    "manual intervention required\n", pdk->dk_name,
-			    dkw.dkw_wname);
-		else if (error)
-			aprint_error("%s: error %d adding entry %u (%s), "
-			    "type %s\n", pdk->dk_name, error, i, ent_guid_str,
-			    ptype_guid_str);
-	}
-	error = 0;
-
- out:
-	brelse(bp, 0);
-	return (error);
+	return gpt_vn_walk(pdk, vp, dkwedge_discover_gpt_cb, pdk);
 }
 
 DKWEDGE_DISCOVERY_METHOD_DECL(GPT, 0, dkwedge_discover_gpt);
Index: sys/dev/raidframe/rf_netbsdkintf.c
===================================================================
RCS file: /cvsroot/src/sys/dev/raidframe/rf_netbsdkintf.c,v
retrieving revision 1.412
diff -U4 -r1.412 rf_netbsdkintf.c
--- sys/dev/raidframe/rf_netbsdkintf.c	15 Jun 2023 09:15:54 -0000	1.412
+++ sys/dev/raidframe/rf_netbsdkintf.c	14 Sep 2023 06:31:23 -0000
@@ -119,9 +119,11 @@
 #include <sys/ioctl.h>
 #include <sys/fcntl.h>
 #include <sys/systm.h>
 #include <sys/vnode.h>
+#include <sys/uuid.h>
 #include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
 #include <sys/conf.h>
 #include <sys/buf.h>
 #include <sys/bufq.h>
 #include <sys/reboot.h>
@@ -523,8 +525,77 @@
 	
 	return 0;
 }
 
+struct rf_gptroot_ctx {
+	uint64_t lba_start;
+	uint64_t lba_end;
+	int first_ffs;
+	int first_bootme;
+};
+
+static int
+rf_gptroot_cb(struct gpt_ent *ent, int partnum, void *data)
+{
+	struct rf_gptroot_ctx *ctx = data;
+	static const struct uuid ent_type_ffs = GPT_ENT_TYPE_NETBSD_FFS;
+	struct uuid ptype_guid;
+
+	if (le64toh(ent->ent_attr) & GPT_ENT_ATTR_BOOTME) {
+		ctx->lba_start = le64toh(ent->ent_lba_start);
+		ctx->lba_end = le64toh(ent->ent_lba_end);
+		ctx->first_bootme = partnum;
+		return 1;
+	}
+
+	uuid_dec_le(ent->ent_type, &ptype_guid);
+
+	if (ctx->first_ffs == -1 &&
+	    memcmp(&ptype_guid, &ent_type_ffs, sizeof(ptype_guid)) == 0) {
+		ctx->lba_start = le64toh(ent->ent_lba_start);
+		ctx->lba_end = le64toh(ent->ent_lba_end);
+		ctx->first_ffs = partnum;
+	}
+
+	return 0;
+}
+
+static int
+rf_gptroot(struct disk *pdk, device_t *rdevp)
+{
+	struct rf_gptroot_ctx ctx = { -1, -1, -1, -1 };
+	int partnum;
+	int error;
+
+	error = gpt_walk(pdk, rf_gptroot_cb, &ctx);
+	if (error) 
+		goto out;
+
+	error = ESRCH;
+
+	if (ctx.first_bootme != -1)
+		partnum = ctx.first_bootme;
+	else if (ctx.first_ffs != -1)
+		partnum = ctx.first_ffs;
+	else
+		partnum = -1;
+
+	if (partnum != -1) {
+		device_t rdev = NULL;
+		device_t pdev = NULL;
+		uint64_t start = ctx.lba_start;
+		uint64_t nblks = ctx.lba_end - ctx.lba_start + 1;
+ 
+		 if ((pdev = device_find_by_xname(pdk->dk_name)) &&
+		    (rdev = dkwedge_find_partition(pdev, start, nblks))) {
+			*rdevp = rdev;
+			error = 0;
+		}
+	}
+out:
+	return error;
+}
+
 
 static void
 rf_buildroothack(RF_ConfigSet_t *config_sets)
 {
@@ -600,10 +671,16 @@
 	 * root.
 	 */
 	if (num_root == 1) {
 		device_t candidate_root;
+		struct disk *pdk;
+
 		dksc = &rsc->sc_dksc;
-		if (dksc->sc_dkdev.dk_nwedges != 0) {
+		pdk = &dksc->sc_dkdev;
+
+		if (rf_gptroot(pdk, &candidate_root) == 0) {
+			/* Nothing to do */
+		} else if (dksc->sc_dkdev.dk_nwedges != 0) {
 			char cname[sizeof(cset->ac->devname)];
 			/* XXX: assume partition 'a' first */
 			snprintf(cname, sizeof(cname), "%s%c",
 			    device_xname(dksc->sc_dev), 'a');


Home | Main Index | Thread Index | Old Index