#	$OpenBSD$

.include <bsd.own.mk>

# Stock ramdisk_cd outer-image size, retained as an override point.
BSDDD_FSSIZE?=	11392
BSDDD_DD_IF?=	/dev/zero
BSDDD_WIPE_TIMEOUT?=	0

BSDDD_BASEDIR=	${.CURDIR}/..
BSDDD_TOP=	${.CURDIR}/../../../..
BSDDD_UTILS=	${BSDDD_BASEDIR}/../../miniroot
BSDDD_MTREE=	${BSDDD_UTILS}/mtree.conf
BSDDD_EFIBOOT=	${DESTDIR}/usr/mdec/BOOTX64.EFI \
		${DESTDIR}/usr/mdec/BOOTIA32.EFI
BSDDD_MOUNT_ARGS_MSDOS=	-o-s

BSDDD_RAMDISK=	RAMDISK_CD_DD
BSDDD_KERNEL=	${.OBJDIR}/bsd
BSDDD_FS=	miniroot${OSrev}_dd.img
BSDDD_BUILDOBJDIR=	${.OBJDIR}/build
BSDDD_KERNELOBJDIR=	${BSDDD_BUILDOBJDIR}/kernel/${BSDDD_RAMDISK}
BSDDD_INSTBIN=	${BSDDD_BUILDOBJDIR}/instbin
BSDDD_RDOBJDIR=	${.OBJDIR}/rdobj
BSDDD_MOUNT_POINT=	${.OBJDIR}/mnt
BSDDD_VND=	${.OBJDIR}/vnd
BSDDD_BOOT=	${.OBJDIR}/boot
BSDDD_OBJCHECK=	${.OBJDIR}/.bsddd-obj-ok
BSDDD_MAKEFILE=	${.CURDIR}/Makefile.bsddd
BSDDD_KERNELCONF=	${.CURDIR}/${BSDDD_RAMDISK}
BSDDD_BASECONF=	${BSDDD_TOP}/sys/arch/${MACHINE}/conf/RAMDISK_CD
BSDDD_KERNELCONFDEPS=	${BSDDD_BASECONF}
BSDDD_LISTS=	${BSDDD_BASEDIR}/list ${.CURDIR}/list.dd
BSDDD_SCRIPTSRC=	${.CURDIR}/bsddd
BSDDD_SCRIPT=	${BSDDD_RDOBJDIR}/bsddd
BSDDD_PROFILE=	${.CURDIR}/dot.profile
# Stock 7360-block rdroot; keep paired with RAMDISK_CD_DD MINIROOTSIZE.
BSDDD_RDROOT_SIZE?=	3680k
BSDDD_MRMAKEFSARGS?=	-s ${BSDDD_RDROOT_SIZE} \
		-o rdroot,minfree=0,bsize=4096,fsize=512,density=4096

.PHONY: bsddd
bsddd: bsddd.rd ${BSDDD_FS}

${BSDDD_OBJCHECK}:
	@if [ "${.OBJDIR}" = "${.CURDIR}" ]; then \
		echo "private object directory is not active;" >&2; \
		echo "run 'make -f Makefile.bsddd obj' separately first" >&2; \
		exit 1; \
	fi
	touch $@

${BSDDD_KERNEL}: ${BSDDD_OBJCHECK} ${BSDDD_MAKEFILE} \
	    ${BSDDD_KERNELCONF} ${BSDDD_KERNELCONFDEPS}
	install -d -o ${BUILDUSER} -g ${WOBJGROUP} ${BSDDD_KERNELOBJDIR}
	su ${BUILDUSER} -c \
	    'config -b ${BSDDD_KERNELOBJDIR} -s ${BSDDD_TOP}/sys \
	    ${BSDDD_KERNELCONF} && cd ${BSDDD_KERNELOBJDIR} && \
	    MAKEOBJDIR=${BSDDD_KERNELOBJDIR} ${MAKE} clean && \
	    exec env MAKEOBJDIR=${BSDDD_KERNELOBJDIR} ${MAKE} ${MFLAGS}'
	cp -p ${BSDDD_KERNELOBJDIR}/bsd $@

bsddd.gz: bsddd.rd
	objcopy -g -x -R .comment -R .SUNW_ctf \
	    -K rd_root_size -K rd_root_image \
	    bsddd.rd bsddd.strip
	gzip -9cn bsddd.strip > bsddd.gz

.PHONY: bsddd-stock-deps bsddd-instbin
bsddd-stock-deps: ${BSDDD_OBJCHECK} ${BSDDD_MAKEFILE}
	@_objroot=`cd ${BSDDD_BASEDIR} && ${MAKE} -V BSDOBJDIR`; \
	if [ ! -d "$$_objroot" ]; then \
		echo "normal OpenBSD object root does not exist: $$_objroot" >&2; \
		echo "create it before building bsddd" >&2; \
		exit 1; \
	fi
	cd ${BSDDD_TOP}/lib && ${MAKE} obj
	cd ${BSDDD_TOP}/distrib/special && ${MAKE} obj
	cd ${BSDDD_BASEDIR} && ${MAKE} obj
	@_srcdir=`cd ${BSDDD_BASEDIR} && pwd`; \
	_objdir=`cd ${BSDDD_BASEDIR} && ${MAKE} -V .OBJDIR`; \
	if [ "$$_objdir" = "$$_srcdir" ] || [ ! -d "$$_objdir" ]; then \
		echo "normal ramdisk_cd object directory is not active" >&2; \
		exit 1; \
	fi
	cd ${BSDDD_TOP}/distrib/special/libstubs && ${MAKE} ${MFLAGS}

bsddd-instbin: bsddd-stock-deps
	cd ${BSDDD_BASEDIR} && ${MAKE} ${MFLAGS} instbin
	install -d ${BSDDD_BUILDOBJDIR}
	@_objdir=`cd ${BSDDD_BASEDIR} && ${MAKE} -V .OBJDIR`; \
	if [ ! -f "$$_objdir/instbin" ]; then \
		echo "stock ramdisk_cd instbin was not built" >&2; \
		exit 1; \
	fi; \
	cp -p "$$_objdir/instbin" ${BSDDD_INSTBIN}

bsddd.rd: bsddd-files bsddd-instbin ${BSDDD_KERNEL}
	install -d ${BSDDD_RDOBJDIR}
	rm -f ${BSDDD_RDOBJDIR}/instbin \
	    ${BSDDD_RDOBJDIR}/mr.fs \
	    ${BSDDD_RDOBJDIR}/bsd.rd
	cp -p ${BSDDD_INSTBIN} ${BSDDD_RDOBJDIR}/instbin
	rm -rf ${BSDDD_RDOBJDIR}/mr.fs.d
	install -d -o root -g wheel ${BSDDD_RDOBJDIR}/mr.fs.d
	mtree -def ${BSDDD_MTREE} -p ${BSDDD_RDOBJDIR}/mr.fs.d -u
	CURDIR=${BSDDD_BASEDIR} OBJDIR=${BSDDD_RDOBJDIR} OSrev=${OSrev} \
	    TARGDIR=${BSDDD_RDOBJDIR}/mr.fs.d UTILS=${BSDDD_UTILS} \
	    RELEASEDIR=${RELEASEDIR} sh ${BSDDD_UTILS}/runlist.sh \
	    ${BSDDD_LISTS}
	rm ${BSDDD_RDOBJDIR}/mr.fs.d/instbin
	makefs ${BSDDD_MRMAKEFSARGS} ${BSDDD_RDOBJDIR}/mr.fs \
	    ${BSDDD_RDOBJDIR}/mr.fs.d
	cp -p ${BSDDD_KERNEL} ${BSDDD_RDOBJDIR}/bsd.rd
	rdsetroot ${BSDDD_RDOBJDIR}/bsd.rd ${BSDDD_RDOBJDIR}/mr.fs
	cp ${BSDDD_RDOBJDIR}/bsd.rd $@

${BSDDD_FS}: bsddd.gz
	-umount -f ${BSDDD_MOUNT_POINT} >/dev/null 2>&1
	@if [ -e ${BSDDD_VND} ] && [ ! -s ${BSDDD_VND} ]; then \
		rm -f ${BSDDD_VND}; \
	fi
	@if [ -e ${BSDDD_VND} ]; then \
		echo "stale private vnd state; run" \
		    "'make -f Makefile.bsddd unconfig-bsddd' first" >&2; \
		exit 1; \
	fi
	install -d ${BSDDD_MOUNT_POINT}
	dd if=/dev/zero of=${BSDDD_FS} bs=512 count=${BSDDD_FSSIZE}
	vnconfig -v ${.OBJDIR}/${BSDDD_FS} > ${BSDDD_VND}
	fdisk -yi -l ${BSDDD_FSSIZE} -b 960 -f ${DESTDIR}/usr/mdec/mbr \
	    `cat ${BSDDD_VND}`
	echo '/ *' | disklabel -wAT- `cat ${BSDDD_VND}`
	newfs -t msdos /dev/r`cat ${BSDDD_VND}`i
	mount ${BSDDD_MOUNT_ARGS_MSDOS} /dev/`cat ${BSDDD_VND}`i \
	    ${BSDDD_MOUNT_POINT}
	mkdir -p ${BSDDD_MOUNT_POINT}/efi/boot
	cp ${BSDDD_EFIBOOT} ${BSDDD_MOUNT_POINT}/efi/boot
	umount ${BSDDD_MOUNT_POINT}
	newfs -O 1 -m 0 -o space -i 524288 -c ${BSDDD_FSSIZE} \
	    /dev/r`cat ${BSDDD_VND}`a
	mount /dev/`cat ${BSDDD_VND}`a ${BSDDD_MOUNT_POINT}
	objcopy -S -R .comment ${DESTDIR}/usr/mdec/boot ${BSDDD_BOOT}
	installboot -v -r ${BSDDD_MOUNT_POINT} `cat ${BSDDD_VND}` \
	    ${DESTDIR}/usr/mdec/biosboot ${BSDDD_BOOT}
	install -c -m 555 -o root -g wheel bsddd.gz \
	    ${BSDDD_MOUNT_POINT}/bsd
	df -i ${BSDDD_MOUNT_POINT}
	umount ${BSDDD_MOUNT_POINT}
	vnconfig -u `cat ${BSDDD_VND}`
	rm -f ${BSDDD_VND}

.PHONY: bsddd-check bsddd-files
bsddd-check:
	@case "${BSDDD_DD_IF}" in \
	/dev/zero|/dev/urandom) ;; \
	*) echo "BSDDD_DD_IF must be /dev/zero or /dev/urandom" >&2; exit 1;; \
	esac
	@case "${BSDDD_WIPE_TIMEOUT}" in \
	''|*[!0-9]*|0[0-9]*) \
		echo "BSDDD_WIPE_TIMEOUT must be 0 or a positive decimal integer" >&2; \
		exit 1;; \
	esac
	@if ! [ "${BSDDD_WIPE_TIMEOUT}" -le 2147483647 ]; then \
		echo "BSDDD_WIPE_TIMEOUT exceeds 2147483647" >&2; \
		exit 1; \
	fi
	test -s ${BSDDD_SCRIPTSRC}
	test -s ${BSDDD_PROFILE}
	test -s ${.CURDIR}/list.dd

bsddd-files: ${BSDDD_OBJCHECK} bsddd-check ${BSDDD_SCRIPTSRC} \
	    ${BSDDD_PROFILE} ${.CURDIR}/list.dd
	install -d ${BSDDD_RDOBJDIR}
	rm -f ${BSDDD_SCRIPT}.tmp
	sed -e 's|^DD_IF=.*|DD_IF=${BSDDD_DD_IF}|' \
	    -e 's|^WIPE_TIMEOUT=.*|WIPE_TIMEOUT=${BSDDD_WIPE_TIMEOUT}|' \
	    ${BSDDD_SCRIPTSRC} > \
	    ${BSDDD_SCRIPT}.tmp
	grep -Fqx 'DD_IF=${BSDDD_DD_IF}' ${BSDDD_SCRIPT}.tmp
	grep -Fqx 'WIPE_TIMEOUT=${BSDDD_WIPE_TIMEOUT}' ${BSDDD_SCRIPT}.tmp
	mv ${BSDDD_SCRIPT}.tmp ${BSDDD_SCRIPT}

.PHONY: unconfig-bsddd
unconfig-bsddd:
	-umount -f ${BSDDD_MOUNT_POINT} >/dev/null 2>&1
	@if [ -e ${BSDDD_VND} ] && [ ! -s ${BSDDD_VND} ]; then \
		rm -f ${BSDDD_VND}; \
	elif [ -f ${BSDDD_VND} ]; then \
		_vnd=`cat ${BSDDD_VND}`; \
		_unit=$${_vnd#vnd}; \
		if [ "vnd$$_unit" != "$$_vnd" ] || [ -z "$$_unit" ]; then \
			echo "invalid private vnd state: $$_vnd" >&2; exit 1; \
		fi; \
		case "$$_unit" in \
		*[!0-9]*) echo "invalid private vnd state: $$_vnd" >&2; exit 1;; \
		esac; \
		_info=`vnconfig -l "$$_vnd"` || exit 1; \
		case "$$_info" in \
		"$$_vnd: not in use") rm -f ${BSDDD_VND} ;; \
		"$$_vnd: covering ${.OBJDIR}/${BSDDD_FS} on "*) \
			vnconfig -u "$$_vnd" && rm -f ${BSDDD_VND} ;; \
		*) echo "refusing to detach vnd not owned by bsddd: $$_info" >&2; \
			exit 1 ;; \
		esac; \
	fi

.ifdef RELEASEDIR
.PHONY: install-bsddd
install-bsddd: bsddd.gz ${BSDDD_FS}
	cp bsddd.gz ${RELEASEDIR}/bsddd.rd
	cp ${BSDDD_FS} ${RELEASEDIR}
	chmod a+r ${RELEASEDIR}/bsddd.rd ${RELEASEDIR}/${BSDDD_FS}
.endif

.PHONY: clean-bsddd clean cleandir
clean-bsddd: unconfig-bsddd
	rm -f bsddd.rd bsddd.gz bsddd.strip ${BSDDD_FS} \
	    ${BSDDD_KERNEL} ${BSDDD_BOOT} ${BSDDD_OBJCHECK}
	rm -rf ${BSDDD_BUILDOBJDIR} ${BSDDD_RDOBJDIR}
	-rmdir ${BSDDD_MOUNT_POINT}

clean cleandir: clean-bsddd

.PHONY: prepare-unpatch-bsddd
prepare-unpatch-bsddd: clean-bsddd
	@if [ -L ${.CURDIR}/obj ]; then \
		_obj=`readlink ${.CURDIR}/obj`; \
		echo "empty private object directory may be removed: $$_obj"; \
		rm -f ${.CURDIR}/obj; \
	fi

.include <bsd.obj.mk>
