xref: /freebsd/release/tools/rc.amibuilder (revision 58426589030308cd632477d328b9536b1634c54d)
1#!/bin/sh
2#
3# Copyright (c) 2025 Colin Percival
4#
5# SPDX-License-Identifier: BSD-2-Clause
6#
7# rc.amibuilder: Juggle disks to reroot into a memory disk and install a clean
8# copy of FreeBSD onto the root disk.
9#
10
11# Do nothing if init(8) is in the middle of rerooting
12if ps -p 1 -o command | grep -q reroot; then
13	exit 0
14fi
15
16# Figure out which partition we boot from
17BOOTPART=$(sysctl -n kern.geom.conftxt |
18    grep -E 'PART|gpt/rootfs' |
19    grep -B 1 gpt/rootfs |
20    awk '{ print $3 }' |
21    head -1)
22BOOTDISK=${BOOTPART%%p*}
23BOOTPARTNUM=${BOOTPART##*p}
24
25# First pass: Copy ourselves into a memory disk and reroot into it
26if ! [ -c /dev/md0 ]; then
27	# Create a memory disk of appropriate size and copy the disk
28	echo "Copying FreeBSD into memory disk..."
29	DISKBYTES=$(diskinfo ${BOOTDISK} | awk '{print $3}')
30	mdconfig -a -t swap -s ${DISKBYTES}b -u 0
31	dd if=/dev/${BOOTDISK} of=/dev/md0 bs=1M
32
33	# Reboot into the memory disk we just created
34	echo "Rebooting into memory disk..."
35	kenv vfs.root.mountfrom="ufs:/dev/md0p${BOOTPARTNUM}"
36	reboot -r
37
38	# Lose a race against init
39	sleep 10
40	exit 1
41fi
42
43# Second pass: Extract a clean copy of FreeBSD onto the physical disk
44echo "Installing base FreeBSD image..."
45sysctl kern.geom.debugflags=16
46zstdcat < /image.zst | dd bs=1M of=/dev/${BOOTDISK}
47
48# Mount the clean image
49if gpart show ${BOOTDISK} | grep -q freebsd-ufs; then
50	mount /dev/${BOOTPART} /mnt
51else
52	zpool import -aNR /mnt
53	zfs mount zroot/ROOT/default
54	zfs mount -a
55fi
56
57# Provide instructions for when the user logs in
58mount -w /
59cat >/etc/motd.template <<EOF
60Welcome to the FreeBSD AMI builder!
61
62FreeBSD `uname -r` is now installed onto the disk /dev/${BOOTDISK},
63and mounted at /mnt. Make any further changes you wish, then run
64
65# mkami <AMI name> [<AMI description>]
66
67to create the AMI. Don't forget to shut down this instance when
68you're done!
69
70EOF
71mount -o ro /
72
73# After we exit, the boot proceeds with init spawning /etc/rc normally
74exit 0
75