aboutsummaryrefslogtreecommitdiff
path: root/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'bootstrap')
-rwxr-xr-xbootstrap399
1 files changed, 307 insertions, 92 deletions
diff --git a/bootstrap b/bootstrap
index 45a122c..95c988e 100755
--- a/bootstrap
+++ b/bootstrap
@@ -4,12 +4,16 @@
#
# Assumptions/expectations:
#
-# - host debootstrap/debian-archive-keyring matching release
+# - Bootstrapping for the host CPU (currently x86_64 or aarch64).
+#
+# - Host debootstrap/debian-archive-keyring matching release.
#
# - /btrfs/<user> is a btrfs directory where the current user can create
-# snapshots
+# snapshots.
+#
+# - sudo is passwordless (used to run debootstrap, systemd-nspawn, etc).
#
-# - sudo is passwordless (used to run debootstrap, systemd-nspawn, etc)
+# - This script is executed from the buildos/ source directory.
#
# Options:
#
@@ -19,19 +23,48 @@
#
# 1 - bootstrap phase 1
# 2 - bootstrap phase 2
-# 3 - kernel build
+# 3 - kernel build (and package patching, if necessary)
# 4 - setup
# 5 - create footfs
# 6 - create kernel image and initrd
#
+# --arch-variant
+# Architecture variant, for example, m1 for aarch64-m1.
+#
+# --kernel-source
+# Pre-configured Linux kernel source .tar.* archive. If unspecified, Debian
+# source/configuration will be used.
+#
+# --firmware
+# Firmware .tar.* archive to be unpackged into /lib/firmware/.
+#
usage="usage: $0"
-macaddr="de:ad:be:ef:b8:da" # @@ TMP mac address for testing.
+owd="$(pwd)"
+trap "{ cd '$owd'; exit 1; }" ERR
+set -o errtrace # Trap in functions.
+
+function info () { echo "$*" 1>&2; }
+function error () { info "$*"; exit 1; }
id="$(id -un)"
btrfs=/btrfs
root="$btrfs/$id/buildos"
+arch="$(uname -m)"
+
+case "$arch" in
+ x86_64)
+ debian_arch=amd64
+ ;;
+ aarch64)
+ debian_arch=arm64
+ ;;
+ *)
+ error "unsupported architecture: $arch"
+ ;;
+esac
+
# Source distribution and packages. Base packages are installed on stage 1 via
# debootstrap. Extra packages are added on stage 4 via apt-get install. The
# idea is to be able to add extra packages without upgrading the base system.
@@ -41,45 +74,63 @@ root="$btrfs/$id/buildos"
#
# - some packages (such as CPU microcode updates) are in non-free.
# - systemd-container seems to be required by host systemd-nspawn.
-# - not installing linux-image-amd64 since building custom below
+# - must explicitly select between dbus and dbus-broker
+# - not installing linux-image-* since building custom below
#
release="testing"
components="main,contrib,non-free"
-mirror="http://deb.debian.org/debian/"
-#mirror="https://deb.debian.org/debian/"
+mirror="http://http.us.debian.org/debian/"
+#mirror="https://http.us.debian.org/debian/"
-base_pkgs="locales,klibc-utils,sudo,systemd-container,udev"
+base_pkgs="locales,klibc-utils,sudo"
+base_pkgs+=",udev,dbus,systemd-timesyncd,systemd-container"
base_pkgs+=",kmod,linux-base,firmware-linux-free,irqbalance"
-base_pkgs+=",intel-microcode,amd64-microcode"
-base_pkgs+=",pciutils,usbutils,dmidecode,cpuid"
+base_pkgs+=",pciutils,usbutils,dmidecode"
base_pkgs+=",hdparm,btrfs-progs"
-base_pkgs+=",lm-sensors,smartmontools"
+base_pkgs+=",lm-sensors,smartmontools,linux-cpupower"
base_pkgs+=",psmisc"
base_pkgs+=",net-tools,iproute2,iptables,isc-dhcp-client"
-base_pkgs+=",ifupdown,bridge-utils,dnsmasq,ntp,postfix"
+base_pkgs+=",ifupdown,bridge-utils,dnsmasq,postfix"
base_pkgs+=",iputils-ping,wget,curl,ca-certificates"
base_pkgs+=",openssh-client,openssh-server"
base_pkgs+=",tftp-hpa,tftpd-hpa"
-base_pkgs+=",bzip2,xz-utils"
+base_pkgs+=",zstd,xz-utils"
base_pkgs+=",less,nano,time"
-
-base_pkgs+=",qemu-kvm,qemu-utils,socat"
-
-base_pkgs+=",g++,make,pkg-config"
-
-extra_pkgs=""
-
-owd="$(pwd)"
-trap "{ cd '$owd'; exit 1; }" ERR
-set -o errtrace # Trap in functions.
-
-function info () { echo "$*" 1>&2; }
-function error () { info "$*"; exit 1; }
-
-stage="1"
-stage_max="6"
+base_pkgs+=",g++,make"
+
+base_pkgs+=",qemu-utils,socat"
+
+case "$arch" in
+ x86_64)
+ base_pkgs+=",cpuid"
+ base_pkgs+=",intel-microcode" #,amd64-microcode
+ base_pkgs+=",qemu-system-x86"
+ ;;
+ aarch64)
+ base_pkgs+=",qemu-system-arm"
+ ;;
+esac
+
+extra_pkgs="ethtool"
+
+case "$arch" in
+ x86_64)
+ #extra_pkgs+=""
+ ;;
+ aarch64)
+ extra_pkgs+=",ipxe-qemu"
+ ;;
+esac
+
+# Options.
+#
+stage=1
+stage_max=6
+arch_variant=
+kernel_source=
+firmware=
while [ "$#" -gt 0 ]; do
case "$1" in
@@ -88,6 +139,21 @@ while [ "$#" -gt 0 ]; do
stage="$1"
shift
;;
+ --arch-variant)
+ shift
+ arch_variant="$1"
+ shift
+ ;;
+ --kernel-source)
+ shift
+ kernel_source="$1"
+ shift
+ ;;
+ --firmware)
+ shift
+ firmware="$1"
+ shift
+ ;;
-*)
error "unknown option: $1"
;;
@@ -101,6 +167,11 @@ if [ "$stage" -lt "1" -o "$stage" -gt "$stage_max" ]; then
error "invalid stage number $stage"
fi
+arch_with_variant="$arch"
+if [ -n "$arch_variant" ]; then
+ arch_with_variant="$arch_with_variant-$arch_variant"
+fi
+
# Extract version.
#
version="$(sed -n -re 's/^version: ([0-9]+\.[0-9]+\.[0-9]+).*$/\1/p' ./manifest)"
@@ -154,14 +225,28 @@ function nspawn () # <root> <systemd-nspawn-args>
local r="$1"
shift
+ # systemd-nspawn appears to carry over the root directory owner into the
+ # container which then causes other issues (Debian bug#950684).
+ #
+ # @@ Looking around didn't reveal any way (e.g., an option) to fix this.
+ # Perhaps newer systemd-nspawn does the right thing automatically?
+ #
+ ug="$(stat --format="%G:%U" "$r")"
+ sudo chown root:root "$r"
+
sudo systemd-nspawn --register=no -D "$r" "$@"
- # systemd-nspawn may create the /var/lib/machines subvolume which prevents
- # the deletion of the containing submodule. So we clean it up.
+ sudo chown "$ug" "$r"
+
+ # systemd-nspawn may create the /var/lib/{machines,portables} subvolumes
+ # which prevents the deletion of the containing submodule. So we clean'em
+ # up.
#
- if sudo btrfs subvol show "$r/var/lib/machines" 1>/dev/null 2>&1; then
- sudo btrfs subvol delete "$r/var/lib/machines"
- fi
+ for s in /var/lib/machines /var/lib/portables; do
+ if sudo btrfs subvol show "$r$s" 1>/dev/null 2>&1; then
+ sudo btrfs subvol delete "$r$s"
+ fi
+ done
}
# (Over)write or append to a file in the installation root, for example:
@@ -196,7 +281,7 @@ if [ "$stage" -eq "1" ]; then
sudo debootstrap \
--foreign \
- --arch=amd64 \
+ --arch="$debian_arch" \
--merged-usr \
--variant=minbase \
--components="$components" \
@@ -234,15 +319,24 @@ trap "exit 1" ERR
set -x
# Hack around systemd bug#79306 (changes /etc/localtime) by removing it now
-# and making readonly below.
+# and making readonly below. @@ See --timezone systemd-nspawn option?
#
rm /etc/localtime
# Both nspawn and debootstrap try to mount /proc /sys (Debian bug#840372).
#
-mkdir /tmp/proc /tmp/sys
-mount --move /proc /tmp/proc
-mount --move /sys /tmp/sys
+# @@ TMP this now causes issues with newer systemd.
+#
+#mkdir /tmp/proc /tmp/sys
+#mount --move /proc /tmp/proc
+#mount --move /sys /tmp/sys
+
+# systemd-nspawn "helpfully" creates a /lib64 symlink that then trips
+# up is-usr-merged package (Debain bug #1019575).
+#
+if [ $arch = aarch64 ]; then
+ rm /lib64
+fi
# Run second stage of debootstrap.
#
@@ -354,47 +448,162 @@ EOF
# Create the kernel build snapshot, write the script that does the build
# from within the installation and boot it up via systemd-nspawn --boot.
#
- # Add this line before shutdown if need to debug/check things.
- #
- # setsid /bin/bash -c "exec /bin/bash -i <>/dev/console 1>&0 2>&1"
+ # Add `bash` before shutdown if need to debug/check things. But note that it
+ # does not work well with `... | tee bootstrap.log`!
#
subvol_delete "$root-3-kernel"
subvol_snapshot "$root" "$root-3-kernel"
+ # Copy custom kernel source.
+ #
+ if [ -n "$kernel_source" ]; then
+ sudo cp "$kernel_source" "$root-3-kernel/usr/src/"
+ fi
+
+ # Copy patches.
+ #
+ #sudo cp ./patches/tftp-hpa-partial-upload.patch "$root-3-kernel/bootstrap/"
+
write <<EOF /bootstrap/setup "$root-3-kernel"
#!/bin/bash
trap "exit 1" ERR
set -x
+# Add deb-src to each deb entry in /etc/apt/sources.list.
+#
+sed -ri -e 's/^deb (.+)/deb \1\ndeb-src \1/' /etc/apt/sources.list
+
+apt-get update
+apt-get install -y build-essential devscripts
+
+# Build custom/patched packages.
+#
+cd /usr/src
+
+if false; then
+mkdir tftpd-hpa
+cd tftpd-hpa
+apt-get install -y libwrap0-dev
+apt-get source tftpd-hpa
+cd tftp-hpa-*/
+patch -p1 </bootstrap/tftp-hpa-partial-upload.patch
+dch -n "Apply patches."
+cd ../tftp-hpa-*/ # May get renamed.
+dpkg-buildpackage -us -uc
+cd ../..
+fi
+
+# Build kernel.
+#
# This seems to be the simplest method of building the standard Debian
# kernel with adjusted configuration. Taken from the Debian Kernel Handbook.
#
apt-get update
-apt-get install -y build-essential linux-source
+apt-get install -y bc
apt-get install -y bison flex
apt-get install -y libelf-dev
apt-get install -y libssl-dev
+apt-get install -y cpio rsync
+apt-get install -y dwarves
+apt-get install -y device-tree-compiler
+
cd /usr/src
-tar xf linux-source-*
-mv linux-source-*/ linux
-xzcat linux-config-*/config.amd64_none_amd64.xz >linux/.config
+
+if [ -z "$kernel_source" ]; then
+ apt-get install -y linux-source
+ tar xf linux-source-*
+ mv linux-source-*/ linux
+ xzcat linux-config-*/config.${debian_arch}_none_${debian_arch}.xz >linux/.config
+else
+ kernel_source=\$(basename $kernel_source)
+ tar xf \$kernel_source
+ mv \$(sed -re 's/(.+)\.tar\..+/\1/' <<<\$kernel_source) linux
+fi
+
cd linux
# Adjust configuration.
#
-echo 'CONFIG_SYSTEM_TRUSTED_KEYS=""' >>.config
-echo 'CONFIG_BUILD_SALT=""' >>.config
-echo 'CONFIG_MODULE_SIG=n' >>.config
+# Note that we do some of these even for the pre-configured kernel.
+#
+# Note that SECURITY_LOCKDOWN_LSM forces MODULE_SIG ('select' in Kconfig).
+#
+# Generally, if you disable an option but it still appears enabled after
+# the kernel build, search for 'select XXX' in Kconfig* and also disable
+# any found symbols.
+#
+scripts/config --disable KCSAN
+scripts/config --disable SECURITY_LOCKDOWN_LSM
+scripts/config --disable MODULE_SIG
+scripts/config --set-str BUILD_SALT ''
+scripts/config --set-str SYSTEM_TRUSTED_KEYS ''
+
+scripts/config --enable INIT_STACK_NONE
+scripts/config --disable INIT_STACK_ALL_PATTERN
+scripts/config --disable INIT_STACK_ALL_ZERO
+
+scripts/config --enable DEBUG_INFO_NONE
+scripts/config --disable DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
+
+# aarch64/5.19 additions:
+#
+scripts/config --disable KCOV
+scripts/config --disable SHADOW_CALL_STACK
+scripts/config --disable ZERO_CALL_USED_REGS
+scripts/config --disable VIDEO_ADV7511
+
+if [ -z "$kernel_source" ]; then
+
+ # Disable sound subsystem/drivers.
+ #
+ sed -i -re '/^CONFIG_SND_.+/d' .config
+ sed -i -re '/^CONFIG_SOUND_.+/d' .config
+ scripts/config --disable CONFIG_SOUND
+ scripts/config --disable CONFIG_SND
+
+ # Disable GPU subsystem/drivers.
+ #
+ # NOTE: this seems to have killed the high-resolution console.
+ #
+ sed -i -re '/^CONFIG_DRM_.+/d' .config
+ scripts/config --disable CONFIG_DRM
+
+ # Disable wireless network drivers.
+ #
+ scripts/config --disable CONFIG_WLAN
+
+fi
# Adjust kernel command line size limit.
#
-sed -i -re 's/^(#define COMMAND_LINE_SIZE ).+\$/\1 4096/' arch/x86/include/asm/setup.h
+sed -i -re 's/^(#define COMMAND_LINE_SIZE).+\$/\1 4096/' arch/x86/include/asm/setup.h
+sed -i -re 's/^(#define COMMAND_LINE_SIZE).+\$/\1 4096/' arch/arm64/include/uapi/asm/setup.h
+
+# Change certain network diagnostics from pr_info() to pr_debug() (otherwise
+# to drowns out any useful diagnostics).
+#
+patch net/core/dev.c <<EOP
+@@ -0 +0 @@
+- pr_info("device %s %s promiscuous mode\n",
++ pr_debug("device %s %s promiscuous mode\n",
+EOP
+patch net/bridge/br_stp.c <<EOP
+@@ -0 +0 @@
+- br_info(p->br, "port %u(%s) entered %s state\n",
++ br_debug(p->br, "port %u(%s) entered %s state\n",
+EOP
+patch net/ipv6/addrconf.c <<EOP
+@@ -0 +0 @@
+- pr_info("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready\n",
++ pr_debug("ADDRCONF(NETDEV_CHANGE): %s: link becomes ready\n",
+EOP
+
+#bash
make oldconfig
-scripts/config --disable DEBUG_INFO
make clean
-make deb-pkg LOCALVERSION=-buildos KDEB_PKGVERSION=1 -j 8
+make deb-pkg LOCALVERSION=-buildos KDEB_PKGVERSION=1-1 -j 8
# Clean up and shutdown.
#
@@ -406,8 +615,9 @@ EOF
nspawn "$root-3-kernel" --boot
- # Copy the kernel over and install it.
+ # Copy the kernel and packages over and install them.
#
+ #sudo cp "$root-3-kernel/usr/src/tftpd-hpa/tftpd-hpa_"*.deb "$root/usr/src/"
sudo cp "$root-3-kernel/usr/src/linux-image-"*.deb "$root/usr/src/"
write <<EOF /bootstrap/setup
@@ -416,7 +626,9 @@ EOF
trap "exit 1" ERR
set -x
+#dpkg -i /usr/src/tftpd-hpa_*.deb
dpkg -i /usr/src/linux-image-*.deb
+
rm -rf /usr/src/*
cd /
ln -s boot/vmlinuz-* /vmlinuz
@@ -438,6 +650,12 @@ fi
#
if [ "$stage" -le "4" ]; then
+ # Copy custom firmware.
+ #
+ if [ -n "$firmware" ]; then
+ sudo cp "$firmware" "$root/usr/src/"
+ fi
+
# Write the setup script that will finish the setup (the service is already
# there from stage 3).
#
@@ -454,6 +672,17 @@ for p in \$(sed -e 's/,/ /g' <<<"$extra_pkgs"); do
apt-get install -y --no-install-recommends "\$p"
done
+# Install custom firmware.
+#
+if [ -n "$firmware" ]; then
+ firmware=\$(basename $firmware)
+ tar -C /lib/firmware -xf /usr/src/\$firmware
+fi
+
+# Final /usr/src cleanup.
+#
+rm -rf /usr/src/*
+
# We want the utility (smartctl) but not the daemon.
#
systemctl disable smartd
@@ -464,15 +693,21 @@ systemctl disable smartd
# consistent across builds.
#
addgroup --gid 2000 build
-adduser --uid 2000 --gid 2000 --home /build --gecos "" --disabled-password build
+adduser --uid 2000 --ingroup build --home /build --gecos "" --disabled-password build
adduser build kvm
echo "build ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/build
echo "Defaults:build !syslog" >>/etc/sudoers.d/build
chmod 0440 /etc/sudoers.d/build
-# Clean up package cache.
+# Clean up package cache and fetched repository information.
#
apt-get clean
+rm -rf /var/lib/apt/lists
+
+# Strip GCC executables (Debian bug #998841). Fixed but let's keep the command
+# around in case it pops up again.
+#
+#strip \$(find /usr/lib/gcc -type f -executable)
# Clean up /bootstrap.
#
@@ -502,15 +737,18 @@ if [ "$stage" -le "5" ]; then
# Quite a few files/directories are only accessible by root (e.g., /root) so
# we run under sudo.
#
+ # Note also that without --check=crc32 the kernel will not be able to
+ # decompress things.
+ #
root_dirs="build dev etc mnt root usr var"
root_links="bin sbin lib lib32 lib64"
- info "generating buildos-rootfs.cpio.gz..."
+ info "generating buildos-rootfs.cpio.xz..."
cd "$root"
sudo find $root_dirs $root_links -print0 | \
sudo cpio --null -o -H newc | \
- gzip -9 > "$owd/buildos-rootfs.cpio.gz"
+ xz -9 --check=crc32 >"$owd/buildos-rootfs.cpio.xz"
cd "$owd"
subvol_snapshot -r "$root" "$root-5"
@@ -537,11 +775,16 @@ if [ "$stage" -le "6" ]; then
sudo ln -sf "$root/usr/lib/systemd/system/buildos.service" \
"$root/etc/systemd/system/multi-user.target.wants/buildos.service"
- info "generating buildos-init.cpio.gz..."
+ # Patch in the arch variant.
+ #
+ sudo sed -i -e "s/^arch_variant=.*/arch_variant=$arch_variant/" \
+ "$root/usr/sbin/buildos"
+
+ info "generating buildos-init.cpio.xz..."
cd "$root"
sudo cpio -o -H newc <<EOF | \
- gzip -9 > "$owd/buildos-init.cpio.gz"
+ xz -9 --check=crc32 >"$owd/buildos-init.cpio.xz"
usr/lib/os-release
init
usr/sbin/buildos
@@ -550,41 +793,13 @@ etc/systemd/system/multi-user.target.wants/buildos.service
EOF
cd "$owd"
- cat buildos-rootfs.cpio.gz buildos-init.cpio.gz >buildos-initrd
+ cat buildos-rootfs.cpio.xz \
+ buildos-init.cpio.xz >"buildos-initrd-$arch_with_variant"
# Copy the kernel image next to the initramfs for convenience.
#
- cp "$root/vmlinuz" buildos-image
- echo "$buildid" >buildos-buildid
+ cp "$root/vmlinuz" "buildos-image-$arch_with_variant"
+ echo "$buildid" >"buildos-buildid-$arch_with_variant"
subvol_snapshot -r "$root" "$root-6"
fi
-
-exit 0
-
-# Test.
-#
-if [ ! -e /tmp/buildos-state ]; then
- qemu-img create -f raw /tmp/buildos-state 20M
-fi
-
-if [ ! -e /tmp/buildos-machines ]; then
- qemu-img create -f raw /tmp/buildos-machines 100M
-fi
-
-# To test PXE boot, replace -kernel/-initrd/-append with '-boot n'.
-#
-sudo kvm \
- -m 16G \
- -cpu host -smp "sockets=1,cores=4,threads=2" \
- -device "e1000,netdev=net0,mac=$macaddr" \
- -netdev "tap,id=net0,script=./qemu-ifup" \
- -device "virtio-scsi-pci,id=scsi" \
- -device "scsi-hd,drive=disk1" \
- -drive "if=none,id=disk1,file=/tmp/buildos-state,format=raw" \
- -device "scsi-hd,drive=disk2" \
- -drive "if=none,id=disk2,file=/tmp/buildos-machines,format=raw" \
- -boot n
-
-# -kernel buildos-image -initrd buildos-initrd \
-# -append "buildos.smtp_relay=build2.org buildos.admin_email=admin@build2.org"