git: 13cb004130d2 - main - release: Support -DNO_ROOT image building

From: Jessica Clarke <jrtc27_at_FreeBSD.org>
Date: Mon, 28 Feb 2022 22:41:08 UTC
The branch main has been updated by jrtc27:

URL: https://cgit.FreeBSD.org/src/commit/?id=13cb004130d2b62f79fe421eaf4a7973efd6a505

commit 13cb004130d2b62f79fe421eaf4a7973efd6a505
Author:     Jessica Clarke <jrtc27@FreeBSD.org>
AuthorDate: 2022-02-28 22:37:03 +0000
Commit:     Jessica Clarke <jrtc27@FreeBSD.org>
CommitDate: 2022-02-28 22:37:03 +0000

    release: Support -DNO_ROOT image building
    
    This requires a bunch of METALOG mangling to include the files we inject
    into the tree. The mkisoimages.sh and make-memstick.sh scripts are now
    called with the current directory inside the tree so that the relative
    paths in the METALOG match up with the current directory. The scripts do
    not require this when not using a METALOG, but for simplicity we always
    do so. The Makefile mangles the real METALOG created from the install,
    as those files are shared across all uses of the tree, but the shell
    scripts create a temporary copy of the METALOG that they mangle as their
    tree modifications are specific to that image. We also need to pass -D
    to makefs to turn any duplicate METALOG entry errors into warnings, as
    we have many (harmless) instances of those.
    
    Whilst dvd1.iso should work, the !NOPKG code will need more work to
    support this.
    
    All media will also lack mergemaster and etcupdate trees, since more
    work is needed to add -DNO_ROOT modes to them. Users of install media
    built this way will have to manually bootstrap them.
    
    Reviewed by:    brooks, gjb
    Differential Revision:  https://reviews.freebsd.org/D33999
---
 release/Makefile               | 51 +++++++++++++++++++++++++++++++++----
 release/amd64/make-memstick.sh | 42 +++++++++++++++++++++---------
 release/amd64/mkisoimages.sh   | 32 ++++++++++++++++++++---
 release/arm64/make-memstick.sh | 38 +++++++++++++++++++--------
 release/arm64/mkisoimages.sh   | 31 +++++++++++++++++++---
 release/i386/make-memstick.sh  | 40 +++++++++++++++++++++--------
 release/i386/mkisoimages.sh    | 36 +++++++++++++++++++++++---
 release/powerpc/mkisoimages.sh | 58 +++++++++++++++++++++++++++++++++++-------
 release/riscv/make-memstick.sh | 38 +++++++++++++++++++--------
 release/riscv/mkisoimages.sh   | 31 +++++++++++++++++++---
 10 files changed, 327 insertions(+), 70 deletions(-)

diff --git a/release/Makefile b/release/Makefile
index 646b9f8738d2..db9cc6b22cbe 100644
--- a/release/Makefile
+++ b/release/Makefile
@@ -117,12 +117,15 @@ clean: beforeclean
 base.txz:
 	mkdir -p ${DISTDIR}
 	cd ${WORLDDIR} && ${IMAKE} distributeworld DISTDIR=${.OBJDIR}/${DISTDIR}
+# TODO: Add NO_ROOT mode to mm-tree.sh and etcupdate
+.if !defined(NO_ROOT)
 # Set up mergemaster root database
 	sh ${.CURDIR}/scripts/mm-mtree.sh -m ${WORLDDIR} -F \
 	    "TARGET_ARCH=${TARGET_ARCH} TARGET=${TARGET} ${.MAKE.JOBS:D-j${.MAKE.JOBS}}" \
 	    -D "${.OBJDIR}/${DISTDIR}/base"
 	etcupdate extract -B -M "TARGET_ARCH=${TARGET_ARCH} TARGET=${TARGET}" \
 	    -s ${WORLDDIR} -d "${.OBJDIR}/${DISTDIR}/base/var/db/etcupdate"
+.endif
 # Package all components
 	cd ${WORLDDIR} && ${IMAKE} packageworld DISTDIR=${.OBJDIR}/${DISTDIR}
 	mv ${DISTDIR}/*.txz .
@@ -163,6 +166,12 @@ disc1: packagesystem
 	for dist in MANIFEST $$(ls *.txz | grep -vE -- '(base|lib32)-dbg'); \
 	    do cp $${dist} ${.TARGET}/usr/freebsd-dist; \
 	done
+.if defined(NO_ROOT)
+	echo "./usr/freebsd-dist type=dir uname=root gname=wheel mode=0755" >> ${.TARGET}/METALOG
+	for dist in MANIFEST $$(ls *.txz | grep -vE -- '(base|lib32)-dbg'); \
+	    do echo "./usr/freebsd-dist/$${dist} type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG; \
+	done
+.endif
 # Set up installation environment
 	ln -fs /tmp/bsdinstall_etc/resolv.conf ${.TARGET}/etc/resolv.conf
 	echo sendmail_enable=\"NONE\" > ${.TARGET}/etc/rc.conf
@@ -171,6 +180,13 @@ disc1: packagesystem
 	echo vfs.mountroot.timeout=\"10\" >> ${.TARGET}/boot/loader.conf
 	echo kernels_autodetect=\"NO\" >> ${.TARGET}/boot/loader.conf
 	cp ${.CURDIR}/rc.local ${.TARGET}/etc
+.if defined(NO_ROOT)
+	echo "./etc/resolv.conf type=link uname=root gname=wheel mode=0644 link=/tmp/bsdinstall_etc/resolv.conf" >> ${.TARGET}/METALOG
+	echo "./etc/rc.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/sysctl.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./boot/loader.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/rc.local type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+.endif
 	touch ${.TARGET}
 
 bootonly: packagesystem
@@ -187,6 +203,10 @@ bootonly: packagesystem
 # Copy manifest only (no distfiles) to get checksums
 	mkdir -p ${.TARGET}/usr/freebsd-dist
 	cp MANIFEST ${.TARGET}/usr/freebsd-dist
+.if defined(NO_ROOT)
+	echo "./usr/freebsd-dist type=dir uname=root gname=wheel mode=0755" >> ${.TARGET}/METALOG
+	echo "./usr/freebsd-dist/MANIFEST type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+.endif
 # Set up installation environment
 	ln -fs /tmp/bsdinstall_etc/resolv.conf ${.TARGET}/etc/resolv.conf
 	echo sendmail_enable=\"NONE\" > ${.TARGET}/etc/rc.conf
@@ -195,6 +215,13 @@ bootonly: packagesystem
 	echo vfs.mountroot.timeout=\"10\" >> ${.TARGET}/boot/loader.conf
 	echo kernels_autodetect=\"NO\" >> ${.TARGET}/boot/loader.conf
 	cp ${.CURDIR}/rc.local ${.TARGET}/etc
+.if defined(NO_ROOT)
+	echo "./etc/resolv.conf type=link uname=root gname=wheel mode=0644 link=/tmp/bsdinstall_etc/resolv.conf" >> ${.TARGET}/METALOG
+	echo "./etc/rc.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/sysctl.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./boot/loader.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/rc.local type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+.endif
 
 dvd: packagesystem
 # Install system
@@ -208,6 +235,12 @@ dvd: packagesystem
 	for dist in MANIFEST $$(ls *.txz | grep -v -- '(base|lib32)-dbg'); \
 	    do cp $${dist} ${.TARGET}/usr/freebsd-dist; \
 	done
+.if defined(NO_ROOT)
+	echo "./usr/freebsd-dist type=dir uname=root gname=wheel mode=0755" >> ${.TARGET}/METALOG
+	for dist in MANIFEST $$(ls *.txz | grep -vE -- '(base|lib32)-dbg'); \
+	    do echo "./usr/freebsd-dist/$${dist} type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG; \
+	done
+.endif
 # Set up installation environment
 	ln -fs /tmp/bsdinstall_etc/resolv.conf ${.TARGET}/etc/resolv.conf
 	echo sendmail_enable=\"NONE\" > ${.TARGET}/etc/rc.conf
@@ -216,31 +249,39 @@ dvd: packagesystem
 	echo vfs.mountroot.timeout=\"10\" >> ${.TARGET}/boot/loader.conf
 	echo kernels_autodetect=\"NO\" >> ${.TARGET}/boot/loader.conf
 	cp ${.CURDIR}/rc.local ${.TARGET}/etc
+.if defined(NO_ROOT)
+	echo "./etc/resolv.conf type=link uname=root gname=wheel mode=0644 link=/tmp/bsdinstall_etc/resolv.conf" >> ${.TARGET}/METALOG
+	echo "./etc/rc.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/sysctl.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./boot/loader.conf type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+	echo "./etc/rc.local type=file uname=root gname=wheel mode=0644" >> ${.TARGET}/METALOG
+.endif
 	touch ${.TARGET}
 
 release.iso: disc1.iso
 disc1.iso: disc1
-	sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_CD ${.TARGET} disc1 ${XTRADIR}
+	cd disc1 && sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_CD ../${.TARGET} .${NO_ROOT:D/METALOG} ${XTRADIR}
 
 dvd1.iso: dvd pkg-stage
-	sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_DVD ${.TARGET} dvd ${XTRADIR}
+	cd dvd && sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_DVD ../${.TARGET} .${NO_ROOT:D/METALOG} ${XTRADIR}
 
 bootonly.iso: bootonly
-	sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_BO ${.TARGET} bootonly ${XTRADIR}
+	cd bootonly && sh ${.CURDIR}/${TARGET}/mkisoimages.sh -b ${VOLUME_LABEL}_BO ../${.TARGET} .${NO_ROOT:D/METALOG} ${XTRADIR}
 
 memstick: memstick.img
 memstick.img: disc1
-	sh ${.CURDIR}/${TARGET}/make-memstick.sh disc1 ${.TARGET}
+	cd disc1 && sh ${.CURDIR}/${TARGET}/make-memstick.sh .${NO_ROOT:D/METALOG} ../${.TARGET}
 
 mini-memstick: mini-memstick.img
 mini-memstick.img: bootonly
-	sh ${.CURDIR}/${TARGET}/make-memstick.sh bootonly ${.TARGET}
+	cd bootonly && sh ${.CURDIR}/${TARGET}/make-memstick.sh .${NO_ROOT:D/METALOG} ../${.TARGET}
 
 packagesystem: base.txz kernel.txz ${EXTRA_PACKAGES}
 	sh ${.CURDIR}/scripts/make-manifest.sh *.txz > MANIFEST
 	touch ${.TARGET}
 
 pkg-stage:
+# TODO: Support for -DNO_ROOT
 .if !defined(NOPKG) || empty(NOPKG)
 	env PORTSDIR=${PORTSDIR} REPOS_DIR=${.CURDIR}/pkg_repos/ \
 		sh ${.CURDIR}/scripts/pkg-stage.sh
diff --git a/release/amd64/make-memstick.sh b/release/amd64/make-memstick.sh
index c0e405c3a976..835dc126d61d 100755
--- a/release/amd64/make-memstick.sh
+++ b/release/amd64/make-memstick.sh
@@ -5,7 +5,7 @@
 # clean up after itself very well for error conditions on purpose so the
 # problem can be diagnosed (full filesystem most likely but ...).
 #
-# Usage: make-memstick.sh <directory tree> <image filename>
+# Usage: make-memstick.sh <directory tree or manifest> <image filename>
 #
 # $FreeBSD$
 #
@@ -19,12 +19,20 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin
 export PATH
 
 if [ $# -ne 2 ]; then
-	echo "make-memstick.sh /path/to/directory /path/to/image/file"
+	echo "make-memstick.sh /path/to/directory/or/manifest /path/to/image/file"
 	exit 1
 fi
 
-if [ ! -d ${1} ]; then
-	echo "${1} must be a directory"
+MAKEFSARG=${1}
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
 	exit 1
 fi
 
@@ -33,20 +41,30 @@ if [ -e ${2} ]; then
 	exit 1
 fi
 
-echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab
-echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local
-makefs -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${1}
-rm ${1}/etc/fstab
-rm ${1}/etc/rc.conf.local
+echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${BASEBITSDIR}/etc/fstab
+echo 'root_rw_mount="NO"' > ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+makefs -D -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG}
+rm ${BASEBITSDIR}/etc/fstab
+rm ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 # Make an ESP in a file.
 espfilename=$(mktemp /tmp/efiboot.XXXXXX)
-make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi
+make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi
 
 mkimg -s mbr \
-    -b ${1}/boot/mbr \
+    -b ${BASEBITSDIR}/boot/mbr \
     -p efi:=${espfilename} \
-    -p freebsd:-"mkimg -s bsd -b ${1}/boot/boot -p freebsd-ufs:=${2}.part" \
+    -p freebsd:-"mkimg -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \
     -a 2 \
     -o ${2}
 rm ${espfilename}
diff --git a/release/amd64/mkisoimages.sh b/release/amd64/mkisoimages.sh
index 7f79ddc800e9..90e6aed5e7ec 100644
--- a/release/amd64/mkisoimages.sh
+++ b/release/amd64/mkisoimages.sh
@@ -41,7 +41,23 @@ if [ -z $MKIMG ]; then
 fi
 
 if [ "$1" = "-b" ]; then
-	BASEBITSDIR="$4"
+	MAKEFSARG="$4"
+else
+	MAKEFSARG="$3"
+fi
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
+	exit 1
+fi
+
+if [ "$1" = "-b" ]; then
 	# This is highly x86-centric and will be used directly below.
 	bootable="-o bootimage=i386;$BASEBITSDIR/boot/cdboot -o no-emul-boot"
 
@@ -54,7 +70,6 @@ if [ "$1" = "-b" ]; then
 
 	shift
 else
-	BASEBITSDIR="$3"
 	bootable=""
 fi
 
@@ -65,12 +80,23 @@ fi
 
 LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift
 NAME="$1"; shift
+# MAKEFSARG extracted already
+shift
 
 publisher="The FreeBSD Project.  https://www.FreeBSD.org/"
 echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab"
-$MAKEFS -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@"
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+$MAKEFS -D -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@"
 rm -f "$BASEBITSDIR/etc/fstab"
 rm -f ${espfilename}
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 if [ "$bootable" != "" ]; then
 	# Look for the EFI System Partition image we dropped in the ISO image.
diff --git a/release/arm64/make-memstick.sh b/release/arm64/make-memstick.sh
index 0cde77b018b8..0dd6dcfaf4dd 100755
--- a/release/arm64/make-memstick.sh
+++ b/release/arm64/make-memstick.sh
@@ -5,7 +5,7 @@
 # clean up after itself very well for error conditions on purpose so the
 # problem can be diagnosed (full filesystem most likely but ...).
 #
-# Usage: make-memstick.sh <directory tree> <image filename>
+# Usage: make-memstick.sh <directory tree or manifest> <image filename>
 #
 # $FreeBSD$
 #
@@ -19,12 +19,20 @@ scriptdir=$(dirname $(realpath $0))
 . ${scriptdir}/../../tools/boot/install-boot.sh
 
 if [ $# -ne 2 ]; then
-	echo "make-memstick.sh /path/to/directory /path/to/image/file"
+	echo "make-memstick.sh /path/to/directory/or/manifest /path/to/image/file"
 	exit 1
 fi
 
-if [ ! -d ${1} ]; then
-	echo "${1} must be a directory"
+MAKEFSARG=${1}
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
 	exit 1
 fi
 
@@ -33,15 +41,25 @@ if [ -e ${2} ]; then
 	exit 1
 fi
 
-echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab
-echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local
-makefs -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${1}
-rm ${1}/etc/fstab
-rm ${1}/etc/rc.conf.local
+echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${BASEBITSDIR}/etc/fstab
+echo 'root_rw_mount="NO"' > ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+makefs -D -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG}
+rm ${BASEBITSDIR}/etc/fstab
+rm ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 # Make an ESP in a file.
 espfilename=$(mktemp /tmp/efiboot.XXXXXX)
-make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi
+make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi
 
 mkimg -s gpt \
     -p efi:=${espfilename} \
diff --git a/release/arm64/mkisoimages.sh b/release/arm64/mkisoimages.sh
index 8d260883c294..b90100286d4a 100644
--- a/release/arm64/mkisoimages.sh
+++ b/release/arm64/mkisoimages.sh
@@ -37,8 +37,23 @@ if [ -z $MKIMG ]; then
 fi
 
 if [ "$1" = "-b" ]; then
-	BASEBITSDIR="$4"
+	MAKEFSARG="$4"
+else
+	MAKEFSARG="$3"
+fi
 
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
+	exit 1
+fi
+
+if [ "$1" = "-b" ]; then
 	# Make an EFI system partition.
 	espfilename=$(mktemp /tmp/efiboot.XXXXXX)
 	# ESP file size in KB.
@@ -49,7 +64,6 @@ if [ "$1" = "-b" ]; then
 
 	shift
 else
-	BASEBITSDIR="$3"
 	bootable=""
 fi
 
@@ -60,12 +74,23 @@ fi
 
 LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift
 NAME="$1"; shift
+# MAKEFSARG extracted already
+shift
 
 publisher="The FreeBSD Project.  https://www.FreeBSD.org/"
 echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab"
-$MAKEFS -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@"
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+$MAKEFS -D -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@"
 rm -f "$BASEBITSDIR/etc/fstab"
 rm -f ${espfilename}
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 if [ "$bootable" != "" ]; then
 	# Look for the EFI System Partition image we dropped in the ISO image.
diff --git a/release/i386/make-memstick.sh b/release/i386/make-memstick.sh
index 6774e86ae550..715e4582a4ef 100755
--- a/release/i386/make-memstick.sh
+++ b/release/i386/make-memstick.sh
@@ -5,7 +5,7 @@
 # clean up after itself very well for error conditions on purpose so the
 # problem can be diagnosed (full filesystem most likely but ...).
 #
-# Usage: make-memstick.sh <directory tree> <image filename>
+# Usage: make-memstick.sh <directory tree or manifest> <image filename>
 #
 # $FreeBSD$
 #
@@ -16,12 +16,20 @@ PATH=/bin:/usr/bin:/sbin:/usr/sbin
 export PATH
 
 if [ $# -ne 2 ]; then
-	echo "make-memstick.sh /path/to/directory /path/to/image/file"
+	echo "make-memstick.sh /path/to/directory/or/manifest /path/to/image/file"
 	exit 1
 fi
 
-if [ ! -d ${1} ]; then
-	echo "${1} must be a directory"
+MAKEFSARG=${1}
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
 	exit 1
 fi
 
@@ -30,15 +38,25 @@ if [ -e ${2} ]; then
 	exit 1
 fi
 
-echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab
-echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local
-makefs -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${1}
-rm ${1}/etc/fstab
-rm ${1}/etc/rc.conf.local
+echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${BASEBITSDIR}/etc/fstab
+echo 'root_rw_mount="NO"' > ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+makefs -D -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG}
+rm ${BASEBITSDIR}/etc/fstab
+rm ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 mkimg -s mbr \
-    -b ${1}/boot/mbr \
-    -p freebsd:-"mkimg -s bsd -b ${1}/boot/boot -p freebsd-ufs:=${2}.part" \
+    -b ${BASEBITSDIR}/boot/mbr \
+    -p freebsd:-"mkimg -s bsd -b ${BASEBITSDIR}/boot/boot -p freebsd-ufs:=${2}.part" \
     -o ${2}
 rm ${2}.part
 
diff --git a/release/i386/mkisoimages.sh b/release/i386/mkisoimages.sh
index b9eb893edeef..a408fa7cddb2 100644
--- a/release/i386/mkisoimages.sh
+++ b/release/i386/mkisoimages.sh
@@ -25,9 +25,26 @@
 
 set -e
 
+if [ "$1" = "-b" ]; then
+	MAKEFSARG="$4"
+else
+	MAKEFSARG="$3"
+fi
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
+	exit 1
+fi
+
 if [ "$1" = "-b" ]; then
 	# This is highly x86-centric and will be used directly below.
-	bootable="-o bootimage=i386;$4/boot/cdboot -o no-emul-boot"
+	bootable="-o bootimage=i386;$BASEBITSDIR/boot/cdboot -o no-emul-boot"
 	shift
 else
 	bootable=""
@@ -40,8 +57,19 @@ fi
 
 LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift
 NAME="$1"; shift
+# MAKEFSARG extracted already
+shift
 
 publisher="The FreeBSD Project.  https://www.FreeBSD.org/"
-echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$1/etc/fstab"
-makefs -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@"
-rm -f "$1/etc/fstab"
+echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab"
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+makefs -D -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@"
+rm -f "$BASEBITSDIR/etc/fstab"
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
diff --git a/release/powerpc/mkisoimages.sh b/release/powerpc/mkisoimages.sh
index 2d5ea76ca7a2..362604170fd1 100644
--- a/release/powerpc/mkisoimages.sh
+++ b/release/powerpc/mkisoimages.sh
@@ -25,6 +25,23 @@
 
 set -e
 
+if [ "$1" = "-b" ]; then
+	MAKEFSARG="$4"
+else
+	MAKEFSARG="$3"
+fi
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
+	exit 1
+fi
+
 if [ "$1" = "-b" ]; then
 	bootable=1
 	shift
@@ -39,6 +56,14 @@ fi
 
 LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift
 NAME="$1"; shift
+# MAKEFSARG extracted already
+shift
+
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
 
 if [ -n "$bootable" ]; then
 	echo "Building bootable disc"
@@ -48,14 +73,14 @@ if [ -n "$bootable" ]; then
 	bzip2 -d /tmp/hfs-boot-block.bz2
 	OFFSET=$(hd /tmp/hfs-boot-block | grep 'Loader START' | cut -f 1 -d ' ')
 	OFFSET=0x$(echo 0x$OFFSET | awk '{printf("%x\n",$1/512);}')
-	dd if="$1/boot/loader" of=/tmp/hfs-boot-block seek=$OFFSET conv=notrunc
+	dd if="$BASEBITSDIR/boot/loader" of=/tmp/hfs-boot-block seek=$OFFSET conv=notrunc
 
 	bootable="-o bootimage=macppc;/tmp/hfs-boot-block -o no-emul-boot"
 
 	# pSeries/PAPR boot code
-	mkdir -p "$1/ppc/chrp"
-	cp "$1/boot/loader" "$1/ppc/chrp"
-	cat > "$1/ppc/bootinfo.txt" << EOF
+	mkdir -p "$BASEBITSDIR/ppc/chrp"
+	cp "$BASEBITSDIR/boot/loader" "$BASEBITSDIR/ppc/chrp"
+	cat > "$BASEBITSDIR/ppc/bootinfo.txt" << EOF
 <chrp-boot>
 <description>FreeBSD Install</description>
 <os-name>FreeBSD</os-name>
@@ -63,14 +88,29 @@ if [ -n "$bootable" ]; then
 </chrp-boot>
 EOF
 	bootable="$bootable -o chrp-boot"
+	if [ -n "${METALOG}" ]; then
+		echo "./ppc type=dir uname=root gname=wheel mode=0755" >> ${metalogfilename}
+		echo "./ppc/chrp type=dir uname=root gname=wheel mode=0755" >> ${metalogfilename}
+		echo "./ppc/chrp/loader type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+		echo "./ppc/bootinfo.txt type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	fi
 
 	# Petitboot config for PS3/PowerNV
-	echo FreeBSD Install=\'/boot/kernel/kernel vfs.root.mountfrom=cd9660:/dev/iso9660/$LABEL\' > "$1/etc/kboot.conf"
+	echo FreeBSD Install=\'/boot/kernel/kernel vfs.root.mountfrom=cd9660:/dev/iso9660/$LABEL\' > "$BASEBITSDIR/etc/kboot.conf"
+	if [ -n "${METALOG}" ]; then
+		echo "./etc/kboot.conf type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	fi
 fi
 
 publisher="The FreeBSD Project.  https://www.FreeBSD.org/"
-echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$1/etc/fstab"
-makefs -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@"
-rm -f "$1/etc/fstab"
+echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab"
+if [ -n "${METALOG}" ]; then
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+fi
+makefs -D -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@"
+rm -f "$BASEBITSDIR/etc/fstab"
 rm -f /tmp/hfs-boot-block
-rm -rf "$1/ppc"
+rm -rf "$BASEBITSDIR/ppc"
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
diff --git a/release/riscv/make-memstick.sh b/release/riscv/make-memstick.sh
index 0cde77b018b8..0dd6dcfaf4dd 100755
--- a/release/riscv/make-memstick.sh
+++ b/release/riscv/make-memstick.sh
@@ -5,7 +5,7 @@
 # clean up after itself very well for error conditions on purpose so the
 # problem can be diagnosed (full filesystem most likely but ...).
 #
-# Usage: make-memstick.sh <directory tree> <image filename>
+# Usage: make-memstick.sh <directory tree or manifest> <image filename>
 #
 # $FreeBSD$
 #
@@ -19,12 +19,20 @@ scriptdir=$(dirname $(realpath $0))
 . ${scriptdir}/../../tools/boot/install-boot.sh
 
 if [ $# -ne 2 ]; then
-	echo "make-memstick.sh /path/to/directory /path/to/image/file"
+	echo "make-memstick.sh /path/to/directory/or/manifest /path/to/image/file"
 	exit 1
 fi
 
-if [ ! -d ${1} ]; then
-	echo "${1} must be a directory"
+MAKEFSARG=${1}
+
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
 	exit 1
 fi
 
@@ -33,15 +41,25 @@ if [ -e ${2} ]; then
 	exit 1
 fi
 
-echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${1}/etc/fstab
-echo 'root_rw_mount="NO"' > ${1}/etc/rc.conf.local
-makefs -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${1}
-rm ${1}/etc/fstab
-rm ${1}/etc/rc.conf.local
+echo '/dev/ufs/FreeBSD_Install / ufs ro,noatime 1 1' > ${BASEBITSDIR}/etc/fstab
+echo 'root_rw_mount="NO"' > ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	echo "./etc/rc.conf.local type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+makefs -D -B little -o label=FreeBSD_Install -o version=2 ${2}.part ${MAKEFSARG}
+rm ${BASEBITSDIR}/etc/fstab
+rm ${BASEBITSDIR}/etc/rc.conf.local
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 # Make an ESP in a file.
 espfilename=$(mktemp /tmp/efiboot.XXXXXX)
-make_esp_file ${espfilename} ${fat32min} ${1}/boot/loader.efi
+make_esp_file ${espfilename} ${fat32min} ${BASEBITSDIR}/boot/loader.efi
 
 mkimg -s gpt \
     -p efi:=${espfilename} \
diff --git a/release/riscv/mkisoimages.sh b/release/riscv/mkisoimages.sh
index 8d260883c294..b90100286d4a 100644
--- a/release/riscv/mkisoimages.sh
+++ b/release/riscv/mkisoimages.sh
@@ -37,8 +37,23 @@ if [ -z $MKIMG ]; then
 fi
 
 if [ "$1" = "-b" ]; then
-	BASEBITSDIR="$4"
+	MAKEFSARG="$4"
+else
+	MAKEFSARG="$3"
+fi
 
+if [ -f ${MAKEFSARG} ]; then
+	BASEBITSDIR=`dirname ${MAKEFSARG}`
+	METALOG=${MAKEFSARG}
+elif [ -d ${MAKEFSARG} ]; then
+	BASEBITSDIR=${MAKEFSARG}
+	METALOG=
+else
+	echo "${MAKEFSARG} must exist"
+	exit 1
+fi
+
+if [ "$1" = "-b" ]; then
 	# Make an EFI system partition.
 	espfilename=$(mktemp /tmp/efiboot.XXXXXX)
 	# ESP file size in KB.
@@ -49,7 +64,6 @@ if [ "$1" = "-b" ]; then
 
 	shift
 else
-	BASEBITSDIR="$3"
 	bootable=""
 fi
 
@@ -60,12 +74,23 @@ fi
 
 LABEL=`echo "$1" | tr '[:lower:]' '[:upper:]'`; shift
 NAME="$1"; shift
+# MAKEFSARG extracted already
+shift
 
 publisher="The FreeBSD Project.  https://www.FreeBSD.org/"
 echo "/dev/iso9660/$LABEL / cd9660 ro 0 0" > "$BASEBITSDIR/etc/fstab"
-$MAKEFS -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$@"
+if [ -n "${METALOG}" ]; then
+	metalogfilename=$(mktemp /tmp/metalog.XXXXXX)
+	cat ${METALOG} > ${metalogfilename}
+	echo "./etc/fstab type=file uname=root gname=wheel mode=0644" >> ${metalogfilename}
+	MAKEFSARG=${metalogfilename}
+fi
+$MAKEFS -D -t cd9660 $bootable -o rockridge -o label="$LABEL" -o publisher="$publisher" "$NAME" "$MAKEFSARG" "$@"
 rm -f "$BASEBITSDIR/etc/fstab"
 rm -f ${espfilename}
+if [ -n "${METALOG}" ]; then
+	rm ${metalogfilename}
+fi
 
 if [ "$bootable" != "" ]; then
 	# Look for the EFI System Partition image we dropped in the ISO image.