Module Name: src
Committed By: mrg
Date: Mon May 17 08:50:36 UTC 2021
Modified Files:
src/sys/kern: files.kern subr_disk.c subr_disk_mbr.c
src/sys/lib/libkern: Makefile.libkern libkern.h
src/sys/lib/libsa: Makefile disklabel.c stand.h
src/sys/sys: disklabel.h
Added Files:
src/sys/lib/libkern: disklabel_swap.c dkcksum.c
Removed Files:
src/sys/lib/libsa: dkcksum.c
Log Message:
move bi-endian disklabel support from the kernel and libsa into libkern.
- dkcksum() and dkcksum_sized() move from subr_disk.c and from
libsa into libkern/dkcksum.c (which is missing _sized() version),
using the version from usr.sbin/disklabel.
- swap_disklabel() moves from subr_disk_mbr.c into libkern, now called
disklabel_swap(). (the sh3 version should be updated to use this.)
- DISKLABEL_EI becomes a first-class option with opt_disklabel.h.
- add libkern.h to libsa/disklabel.c.
this enables future work for bi-endian libsa/ufs.c (relevant for ffsv1,
ffsv2, lfsv1, and lfsv2), as well as making it possible for ports not
using subr_disk_mbr.c to include bi-endian disklabel support (which,
afaict, includes any disk on mbr-supporting platforms that do not have
an mbr as well as disklabel.)
builds successsfully on: alpha, i386, amd64, sun2, sun3, evbarm64,
evbarm64-eb, sparc, and sparc64. tested in anita on i386 and sparc,
testing in hardware on evbarm64*.
To generate a diff of this commit:
cvs rdiff -u -r1.54 -r1.55 src/sys/kern/files.kern
cvs rdiff -u -r1.132 -r1.133 src/sys/kern/subr_disk.c
cvs rdiff -u -r1.56 -r1.57 src/sys/kern/subr_disk_mbr.c
cvs rdiff -u -r1.50 -r1.51 src/sys/lib/libkern/Makefile.libkern
cvs rdiff -u -r0 -r1.1 src/sys/lib/libkern/disklabel_swap.c \
src/sys/lib/libkern/dkcksum.c
cvs rdiff -u -r1.142 -r1.143 src/sys/lib/libkern/libkern.h
cvs rdiff -u -r1.93 -r1.94 src/sys/lib/libsa/Makefile
cvs rdiff -u -r1.10 -r1.11 src/sys/lib/libsa/disklabel.c
cvs rdiff -u -r1.5 -r0 src/sys/lib/libsa/dkcksum.c
cvs rdiff -u -r1.82 -r1.83 src/sys/lib/libsa/stand.h
cvs rdiff -u -r1.124 -r1.125 src/sys/sys/disklabel.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/files.kern
diff -u src/sys/kern/files.kern:1.54 src/sys/kern/files.kern:1.55
--- src/sys/kern/files.kern:1.54 Sun Nov 1 18:51:02 2020
+++ src/sys/kern/files.kern Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-# $NetBSD: files.kern,v 1.54 2020/11/01 18:51:02 pgoyette Exp $
+# $NetBSD: files.kern,v 1.55 2021/05/17 08:50:36 mrg Exp $
#
# kernel sources
@@ -115,6 +115,7 @@ file kern/subr_device.c kern
file kern/subr_devsw.c kern
file kern/subr_disk.c kern
file kern/subr_disklabel.c kern
+defopt opt_disklabel.h DISKLABEL_EI
file kern/subr_disk_open.c kern
file kern/subr_emul.c kern
file kern/subr_evcnt.c kern
Index: src/sys/kern/subr_disk.c
diff -u src/sys/kern/subr_disk.c:1.132 src/sys/kern/subr_disk.c:1.133
--- src/sys/kern/subr_disk.c:1.132 Sat Oct 17 09:42:35 2020
+++ src/sys/kern/subr_disk.c Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_disk.c,v 1.132 2020/10/17 09:42:35 mlelstv Exp $ */
+/* $NetBSD: subr_disk.c,v 1.133 2021/05/17 08:50:36 mrg Exp $ */
/*-
* Copyright (c) 1996, 1997, 1999, 2000, 2009 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.132 2020/10/17 09:42:35 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_disk.c,v 1.133 2021/05/17 08:50:36 mrg Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -81,29 +81,6 @@ __KERNEL_RCSID(0, "$NetBSD: subr_disk.c,
#include <lib/libkern/libkern.h>
/*
- * Compute checksum for disk label.
- */
-u_int
-dkcksum(struct disklabel *lp)
-{
-
- return dkcksum_sized(lp, lp->d_npartitions);
-}
-
-u_int
-dkcksum_sized(struct disklabel *lp, size_t npartitions)
-{
- uint16_t *start, *end;
- uint16_t sum = 0;
-
- start = (uint16_t *)lp;
- end = (uint16_t *)&lp->d_partitions[npartitions];
- while (start < end)
- sum ^= *start++;
- return sum;
-}
-
-/*
* Disk error is the preface to plaintive error messages
* about failing disk transfers. It prints messages of the form
Index: src/sys/kern/subr_disk_mbr.c
diff -u src/sys/kern/subr_disk_mbr.c:1.56 src/sys/kern/subr_disk_mbr.c:1.57
--- src/sys/kern/subr_disk_mbr.c:1.56 Thu Nov 7 20:34:29 2019
+++ src/sys/kern/subr_disk_mbr.c Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_disk_mbr.c,v 1.56 2019/11/07 20:34:29 kamil Exp $ */
+/* $NetBSD: subr_disk_mbr.c,v 1.57 2021/05/17 08:50:36 mrg Exp $ */
/*
* Copyright (c) 1982, 1986, 1988 Regents of the University of California.
@@ -54,7 +54,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_disk_mbr.c,v 1.56 2019/11/07 20:34:29 kamil Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_disk_mbr.c,v 1.57 2021/05/17 08:50:36 mrg Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_mbr.h"
+#include "opt_disklabel.h"
+#endif /* _KERNEL_OPT */
#include <sys/param.h>
#include <sys/systm.h>
@@ -72,10 +77,6 @@ __KERNEL_RCSID(0, "$NetBSD: subr_disk_mb
#include <sys/kauth.h>
-#ifdef _KERNEL_OPT
-#include "opt_mbr.h"
-#endif /* _KERNEL_OPT */
-
typedef struct mbr_partition mbr_partition_t;
/*
@@ -117,10 +118,6 @@ static int validate_label(mbr_args_t *,
static int look_netbsd_part(mbr_args_t *, mbr_partition_t *, int, uint);
static int write_netbsd_label(mbr_args_t *, mbr_partition_t *, int, uint);
-#ifdef DISKLABEL_EI
-static void swap_disklabel(struct disklabel *, struct disklabel *);
-#endif
-
static int
read_sector(mbr_args_t *a, uint sector, int count)
{
@@ -659,7 +656,7 @@ corrupted:
case READ_LABEL:
#ifdef DISKLABEL_EI
if (swapped)
- swap_disklabel(a->lp, dlp);
+ disklabel_swap(a->lp, dlp);
else
*a->lp = *dlp;
#else
@@ -675,7 +672,7 @@ corrupted:
#ifdef DISKLABEL_EI
/* DO NOT swap a->lp itself for later references. */
if (swapped)
- swap_disklabel(dlp, a->lp);
+ disklabel_swap(dlp, a->lp);
else
*dlp = *a->lp;
#else
@@ -744,83 +741,3 @@ write_netbsd_label(mbr_args_t *a, mbr_pa
return validate_label(a, ptn_base);
}
-
-#ifdef DISKLABEL_EI
-/*
- * from sh3/disksubr.c with modifications:
- * - update d_checksum properly
- * - replace memcpy(9) by memmove(9) as a precaution
- */
-static void
-swap_disklabel(struct disklabel *nlp, struct disklabel *olp)
-{
- int i;
- uint16_t npartitions;
-
-#define SWAP16(x) nlp->x = bswap16(olp->x)
-#define SWAP32(x) nlp->x = bswap32(olp->x)
-
- SWAP32(d_magic);
- SWAP16(d_type);
- SWAP16(d_subtype);
- /* Do not need to swap char strings. */
- memmove(nlp->d_typename, olp->d_typename, sizeof(nlp->d_typename));
-
- /* XXX What should we do for d_un (an union of char and pointers) ? */
- memmove(nlp->d_packname, olp->d_packname, sizeof(nlp->d_packname));
-
- SWAP32(d_secsize);
- SWAP32(d_nsectors);
- SWAP32(d_ntracks);
- SWAP32(d_ncylinders);
- SWAP32(d_secpercyl);
- SWAP32(d_secperunit);
-
- SWAP16(d_sparespertrack);
- SWAP16(d_sparespercyl);
-
- SWAP32(d_acylinders);
-
- SWAP16(d_rpm);
- SWAP16(d_interleave);
- SWAP16(d_trackskew);
- SWAP16(d_cylskew);
- SWAP32(d_headswitch);
- SWAP32(d_trkseek);
- SWAP32(d_flags);
- for (i = 0; i < NDDATA; i++)
- SWAP32(d_drivedata[i]);
- for (i = 0; i < NSPARE; i++)
- SWAP32(d_spare[i]);
- SWAP32(d_magic2);
- /* d_checksum is updated later. */
-
- SWAP16(d_npartitions);
- SWAP32(d_bbsize);
- SWAP32(d_sbsize);
- for (i = 0; i < MAXPARTITIONS; i++) {
- SWAP32(d_partitions[i].p_size);
- SWAP32(d_partitions[i].p_offset);
- SWAP32(d_partitions[i].p_fsize);
- /* p_fstype and p_frag is uint8_t, so no need to swap. */
- nlp->d_partitions[i].p_fstype = olp->d_partitions[i].p_fstype;
- nlp->d_partitions[i].p_frag = olp->d_partitions[i].p_frag;
- SWAP16(d_partitions[i].p_cpg);
- }
-
-#undef SWAP16
-#undef SWAP32
-
- /* Update checksum in the target endian. */
- nlp->d_checksum = 0;
- npartitions = nlp->d_magic == DISKMAGIC ?
- nlp->d_npartitions : olp->d_npartitions;
- /*
- * npartitions can be larger than MAXPARTITIONS when the label was not
- * validated by setdisklabel. If so, the label is intentionally(?)
- * corrupted and checksum should be meaningless.
- */
- if (npartitions <= MAXPARTITIONS)
- nlp->d_checksum = dkcksum_sized(nlp, npartitions);
-}
-#endif /* DISKLABEL_EI */
Index: src/sys/lib/libkern/Makefile.libkern
diff -u src/sys/lib/libkern/Makefile.libkern:1.50 src/sys/lib/libkern/Makefile.libkern:1.51
--- src/sys/lib/libkern/Makefile.libkern:1.50 Mon Jan 25 12:45:49 2021
+++ src/sys/lib/libkern/Makefile.libkern Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile.libkern,v 1.50 2021/01/25 12:45:49 thorpej Exp $
+# $NetBSD: Makefile.libkern,v 1.51 2021/05/17 08:50:36 mrg Exp $
#
# Variable definitions for libkern.
@@ -99,6 +99,9 @@ SRCS+= explicit_memset.c consttime_memeq
SRCS+= entpool.c
+SRCS+= dkcksum.c
+SRCS+= disklabel_swap.c
+
.PATH: ${NETBSDSRCDIR}/common/lib/libc/cdb
SRCS+= cdbr.c
SRCS+= mi_vector_hash.c
Index: src/sys/lib/libkern/libkern.h
diff -u src/sys/lib/libkern/libkern.h:1.142 src/sys/lib/libkern/libkern.h:1.143
--- src/sys/lib/libkern/libkern.h:1.142 Thu Jan 21 15:43:37 2021
+++ src/sys/lib/libkern/libkern.h Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: libkern.h,v 1.142 2021/01/21 15:43:37 thorpej Exp $ */
+/* $NetBSD: libkern.h,v 1.143 2021/05/17 08:50:36 mrg Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -542,4 +542,9 @@ int strnvisx(char *, size_t, const char
#define VIS_SAFE 0x20
#define VIS_TRIM 0x40
+struct disklabel;
+void disklabel_swap(struct disklabel *, struct disklabel *);
+uint16_t dkcksum(const struct disklabel *);
+uint16_t dkcksum_sized(const struct disklabel *, size_t);
+
#endif /* !_LIB_LIBKERN_LIBKERN_H_ */
Index: src/sys/lib/libsa/Makefile
diff -u src/sys/lib/libsa/Makefile:1.93 src/sys/lib/libsa/Makefile:1.94
--- src/sys/lib/libsa/Makefile:1.93 Mon Sep 7 01:54:26 2020
+++ src/sys/lib/libsa/Makefile Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.93 2020/09/07 01:54:26 mrg Exp $
+# $NetBSD: Makefile,v 1.94 2021/05/17 08:50:36 mrg Exp $
LIB= sa
LIBISPRIVATE?= yes
@@ -46,7 +46,7 @@ SRCS+= memcmp.c memcpy.c memmove.c memse
SRCS+= bcopy.c bzero.c # Remove me eventually.
# io routines
-SRCS+= closeall.c dev.c disklabel.c dkcksum.c ioctl.c nullfs.c stat.c fstat.c
+SRCS+= closeall.c dev.c disklabel.c ioctl.c nullfs.c stat.c fstat.c
SRCS+= close.c lseek.c open.c read.c write.c
.if (${SA_USE_CREAD} == "yes")
CPPFLAGS+= -D__INTERNAL_LIBSA_CREAD
Index: src/sys/lib/libsa/disklabel.c
diff -u src/sys/lib/libsa/disklabel.c:1.10 src/sys/lib/libsa/disklabel.c:1.11
--- src/sys/lib/libsa/disklabel.c:1.10 Sat Nov 24 13:20:54 2007
+++ src/sys/lib/libsa/disklabel.c Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: disklabel.c,v 1.10 2007/11/24 13:20:54 isaki Exp $ */
+/* $NetBSD: disklabel.c,v 1.11 2021/05/17 08:50:36 mrg Exp $ */
/*-
* Copyright (c) 1993
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <sys/disklabel.h>
+#include <lib/libkern/libkern.h>
#include "stand.h"
Index: src/sys/lib/libsa/stand.h
diff -u src/sys/lib/libsa/stand.h:1.82 src/sys/lib/libsa/stand.h:1.83
--- src/sys/lib/libsa/stand.h:1.82 Sat Aug 27 18:59:18 2016
+++ src/sys/lib/libsa/stand.h Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: stand.h,v 1.82 2016/08/27 18:59:18 dholland Exp $ */
+/* $NetBSD: stand.h,v 1.83 2021/05/17 08:50:36 mrg Exp $ */
/*
* Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
@@ -246,7 +246,6 @@ void *alloc(size_t) __compactcall;
void dealloc(void *, size_t) __compactcall;
struct disklabel;
char *getdisklabel(const char *, struct disklabel *);
-int dkcksum(const struct disklabel *);
void printf(const char *, ...)
__attribute__((__format__(__printf__, 1, 2)));
Index: src/sys/sys/disklabel.h
diff -u src/sys/sys/disklabel.h:1.124 src/sys/sys/disklabel.h:1.125
--- src/sys/sys/disklabel.h:1.124 Mon Mar 30 09:32:46 2020
+++ src/sys/sys/disklabel.h Mon May 17 08:50:36 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: disklabel.h,v 1.124 2020/03/30 09:32:46 wiz Exp $ */
+/* $NetBSD: disklabel.h,v 1.125 2021/05/17 08:50:36 mrg Exp $ */
/*
* Copyright (c) 1987, 1988, 1993
@@ -498,8 +498,6 @@ int disk_read_sectors(void (*)(struct bu
struct buf *, unsigned int, int);
void diskerr(const struct buf *, const char *, const char *, int,
int, const struct disklabel *);
-u_int dkcksum(struct disklabel *);
-u_int dkcksum_sized(struct disklabel *, size_t);
int setdisklabel(struct disklabel *, struct disklabel *, u_long,
struct cpu_disklabel *);
const char *readdisklabel(dev_t, void (*)(struct buf *),
Added files:
Index: src/sys/lib/libkern/disklabel_swap.c
diff -u /dev/null src/sys/lib/libkern/disklabel_swap.c:1.1
--- /dev/null Mon May 17 08:50:36 2021
+++ src/sys/lib/libkern/disklabel_swap.c Mon May 17 08:50:36 2021
@@ -0,0 +1,135 @@
+/* $NetBSD: disklabel_swap.c,v 1.1 2021/05/17 08:50:36 mrg Exp $ */
+
+/*
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: disklabel_swap.c,v 1.1 2021/05/17 08:50:36 mrg Exp $");
+
+#ifdef _KERNEL_OPT
+#include "opt_disklabel.h"
+#endif /* _KERNEL_OPT */
+
+#if defined(DISKLABEL_EI) || defined(LIBSA_DISKLABEL_EI)
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/disklabel.h>
+#include <sys/conf.h>
+#include <lib/libkern/libkern.h>
+
+/*
+ * from sh3/disksubr.c and kern/subr_disk_mbr.c with modifications:
+ * - update d_checksum properly
+ * - replace memcpy(9) by memmove(9) as a precaution
+ * - avoid memmove(9) for libkern version, check if the labels
+ * are the same and skip copying in-place.
+ */
+void
+disklabel_swap(struct disklabel *nlp, struct disklabel *olp)
+{
+ int i;
+ uint16_t npartitions;
+
+#define SWAP16(x) nlp->x = bswap16(olp->x)
+#define SWAP32(x) nlp->x = bswap32(olp->x)
+
+ SWAP32(d_magic);
+ SWAP16(d_type);
+ SWAP16(d_subtype);
+ if (nlp != olp) {
+ /* Do not need to swap char strings. */
+ memcpy(nlp->d_typename, olp->d_typename,
+ sizeof(nlp->d_typename));
+
+ /*
+ * XXX What should we do for d_un (an union of char and
+ * pointers)?
+ */
+ memcpy(nlp->d_packname, olp->d_packname,
+ sizeof(nlp->d_packname));
+ }
+
+ SWAP32(d_secsize);
+ SWAP32(d_nsectors);
+ SWAP32(d_ntracks);
+ SWAP32(d_ncylinders);
+ SWAP32(d_secpercyl);
+ SWAP32(d_secperunit);
+
+ SWAP16(d_sparespertrack);
+ SWAP16(d_sparespercyl);
+
+ SWAP32(d_acylinders);
+
+ SWAP16(d_rpm);
+ SWAP16(d_interleave);
+ SWAP16(d_trackskew);
+ SWAP16(d_cylskew);
+ SWAP32(d_headswitch);
+ SWAP32(d_trkseek);
+ SWAP32(d_flags);
+ for (i = 0; i < NDDATA; i++)
+ SWAP32(d_drivedata[i]);
+ for (i = 0; i < NSPARE; i++)
+ SWAP32(d_spare[i]);
+ SWAP32(d_magic2);
+ /* d_checksum is updated later. */
+
+ SWAP16(d_npartitions);
+ SWAP32(d_bbsize);
+ SWAP32(d_sbsize);
+ for (i = 0; i < MAXPARTITIONS; i++) {
+ SWAP32(d_partitions[i].p_size);
+ SWAP32(d_partitions[i].p_offset);
+ SWAP32(d_partitions[i].p_fsize);
+ /* p_fstype and p_frag is uint8_t, so no need to swap. */
+ nlp->d_partitions[i].p_fstype = olp->d_partitions[i].p_fstype;
+ nlp->d_partitions[i].p_frag = olp->d_partitions[i].p_frag;
+ SWAP16(d_partitions[i].p_cpg);
+ }
+
+#undef SWAP16
+#undef SWAP32
+
+ /* Update checksum in the target endian. */
+ nlp->d_checksum = 0;
+ npartitions = nlp->d_magic == DISKMAGIC ?
+ nlp->d_npartitions : olp->d_npartitions;
+ /*
+ * npartitions can be larger than MAXPARTITIONS when the label was not
+ * validated by setdisklabel. If so, the label is intentionally(?)
+ * corrupted and checksum should be meaningless.
+ */
+ if (npartitions <= MAXPARTITIONS)
+ nlp->d_checksum = dkcksum_sized(nlp, npartitions);
+}
+#endif /* DISKLABEL_EI || LIBSA_DISKLABEL_EI */
Index: src/sys/lib/libkern/dkcksum.c
diff -u /dev/null src/sys/lib/libkern/dkcksum.c:1.1
--- /dev/null Mon May 17 08:50:36 2021
+++ src/sys/lib/libkern/dkcksum.c Mon May 17 08:50:36 2021
@@ -0,0 +1,67 @@
+/* $NetBSD: dkcksum.c,v 1.1 2021/05/17 08:50:36 mrg Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
+ *
+ * from: NetBSD: dkcksum.c,v 1.14 2013/05/03 16:05:12 matt Exp
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)dkcksum.c 8.1 (Berkeley) 6/5/93";
+#else
+__RCSID("$NetBSD: dkcksum.c,v 1.1 2021/05/17 08:50:36 mrg Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/disklabel.h>
+#include <lib/libkern/libkern.h>
+
+uint16_t
+dkcksum(const struct disklabel *lp)
+{
+
+ return dkcksum_sized(lp, lp->d_npartitions);
+}
+
+uint16_t
+dkcksum_sized(const struct disklabel *lp, size_t npartitions)
+{
+ const uint16_t *start, *end;
+ uint16_t sum;
+
+ sum = 0;
+ start = (const uint16_t *)lp;
+ end = (const uint16_t *)&lp->d_partitions[npartitions];
+ while (start < end) {
+ sum ^= *start++;
+ }
+ return sum;
+}