From f38d9923173d36600aac1045e1fa8fb58389acf7 Mon Sep 17 00:00:00 2001 From: oxmc7769 Date: Tue, 22 Apr 2025 22:36:38 -0700 Subject: [PATCH] Add back build.sh (whoops) --- build.sh | 468 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..1643d5f --- /dev/null +++ b/build.sh @@ -0,0 +1,468 @@ +#!/bin/bash -e + +# shellcheck disable=SC2119 +run_sub_stage() +{ + log "Begin ${SUB_STAGE_DIR}" + pushd "${SUB_STAGE_DIR}" > /dev/null + for i in {00..99}; do + if [ -f "${i}-debconf-${ARCH}" ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-debconf-${ARCH}" + on_chroot << EOF +debconf-set-selections < /dev/null + if [ "${CLEAN}" = "1" ]; then + rm -rf .pc + rm -rf ./*-pc + fi + QUILT_PATCHES="${SUB_STAGE_DIR}/${i}-patches-${ARCH}" + SUB_STAGE_QUILT_PATCH_DIR="$(basename "$SUB_STAGE_DIR")-pc" + mkdir -p "$SUB_STAGE_QUILT_PATCH_DIR" + ln -snf "$SUB_STAGE_QUILT_PATCH_DIR" .pc + quilt upgrade + if [ -e "${SUB_STAGE_DIR}/${i}-patches-${ARCH}/EDIT" ]; then + echo "Dropping into bash to edit patches..." + bash + fi + RC=0 + quilt push -a || RC=$? + case "$RC" in + 0|2) + ;; + *) + false + ;; + esac + popd > /dev/null + log "End ${SUB_STAGE_DIR}/${i}-patches-${ARCH}" + elif [ -d "${i}-patches-arm-only" ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-patches-arm-only" + pushd "${STAGE_WORK_DIR}" > /dev/null + if [ "${CLEAN}" = "1" ]; then + rm -rf .pc + rm -rf ./*-pc + fi + QUILT_PATCHES="${SUB_STAGE_DIR}/${i}-patches-arm-only" + SUB_STAGE_QUILT_PATCH_DIR="$(basename "$SUB_STAGE_DIR")-pc" + mkdir -p "$SUB_STAGE_QUILT_PATCH_DIR" + ln -snf "$SUB_STAGE_QUILT_PATCH_DIR" .pc + quilt upgrade + if [ -e "${SUB_STAGE_DIR}/${i}-patches-arm-only/EDIT" ]; then + echo "Dropping into bash to edit patches..." + bash + fi + RC=0 + quilt push -a || RC=$? + case "$RC" in + 0|2) + ;; + *) + false + ;; + esac + popd > /dev/null + log "End ${SUB_STAGE_DIR}/${i}-patches-arm-only" + elif [ -d "${i}-patches" ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-patches" + pushd "${STAGE_WORK_DIR}" > /dev/null + if [ "${CLEAN}" = "1" ]; then + rm -rf .pc + rm -rf ./*-pc + fi + QUILT_PATCHES="${SUB_STAGE_DIR}/${i}-patches" + SUB_STAGE_QUILT_PATCH_DIR="$(basename "$SUB_STAGE_DIR")-pc" + mkdir -p "$SUB_STAGE_QUILT_PATCH_DIR" + ln -snf "$SUB_STAGE_QUILT_PATCH_DIR" .pc + quilt upgrade + if [ -e "${SUB_STAGE_DIR}/${i}-patches/EDIT" ]; then + echo "Dropping into bash to edit patches..." + bash + fi + RC=0 + quilt push -a || RC=$? + case "$RC" in + 0|2) + ;; + *) + false + ;; + esac + popd > /dev/null + log "End ${SUB_STAGE_DIR}/${i}-patches" + fi + if [ -x ${i}-run-${ARCH}.sh ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run-${ARCH}.sh" + ./${i}-run-${ARCH}.sh + log "End ${SUB_STAGE_DIR}/${i}-run-${ARCH}.sh" + elif [ -x "${i}-run-arm-only.sh" ] && [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run-arm-only.sh" + ./${i}-run-arm-only.sh + log "End ${SUB_STAGE_DIR}/${i}-run-arm-only.sh" + elif [ -x ${i}-run.sh ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run.sh" + ./${i}-run.sh + log "End ${SUB_STAGE_DIR}/${i}-run.sh" + fi + if [ -f ${i}-run-chroot-${ARCH}.sh ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run-chroot-${ARCH}.sh" + on_chroot < ${i}-run-chroot-${ARCH}.sh + log "End ${SUB_STAGE_DIR}/${i}-run-chroot-${ARCH}.sh" + elif [ -f "${i}-run-chroot-arm-only.sh" ] && [[ "${ARCH}" == "arm64" || "${ARCH}" == "armhf" ]]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run-chroot-arm-only.sh" + on_chroot < ${i}-run-chroot-arm-only.sh + log "End ${SUB_STAGE_DIR}/${i}-run-chroot-arm-only.sh" + elif [ -f ${i}-run-chroot.sh ]; then + log "Begin ${SUB_STAGE_DIR}/${i}-run-chroot.sh" + on_chroot < ${i}-run-chroot.sh + log "End ${SUB_STAGE_DIR}/${i}-run-chroot.sh" + fi + done + popd > /dev/null + log "End ${SUB_STAGE_DIR}" +} + + +run_stage(){ + log "Begin ${STAGE_DIR}" + STAGE="$(basename "${STAGE_DIR}")" + + pushd "${STAGE_DIR}" > /dev/null + + STAGE_WORK_DIR="${WORK_DIR}/${STAGE}" + ROOTFS_DIR="${STAGE_WORK_DIR}"/rootfs + + unmount "${WORK_DIR}/${STAGE}" + + if [ ! -f SKIP_IMAGES ]; then + if [ -f "${STAGE_DIR}/EXPORT_IMAGE" ]; then + EXPORT_DIRS="${EXPORT_DIRS} ${STAGE_DIR}" + fi + fi + if [ ! -f SKIP ]; then + if [ "${CLEAN}" = "1" ]; then + if [ -d "${ROOTFS_DIR}" ]; then + rm -rf "${ROOTFS_DIR}" + fi + fi + if [ -x prerun.sh ]; then + log "Begin ${STAGE_DIR}/prerun.sh" + ./prerun.sh + log "End ${STAGE_DIR}/prerun.sh" + fi + for SUB_STAGE_DIR in "${STAGE_DIR}"/*; do + if [ -d "${SUB_STAGE_DIR}" ]; then + if [ ! -f "${SUB_STAGE_DIR}/SKIP" ] && [ ! -f "${SUB_STAGE_DIR}/SKIP_${ARCH}" ]; then + run_sub_stage + fi + fi + done + fi + + unmount "${WORK_DIR}/${STAGE}" + + PREV_STAGE="${STAGE}" + PREV_STAGE_DIR="${STAGE_DIR}" + PREV_ROOTFS_DIR="${ROOTFS_DIR}" + popd > /dev/null + log "End ${STAGE_DIR}" +} + +term() { + if [ "$?" -ne 0 ]; then + log "Build failed" + else + log "Build finished" + fi + unmount "${STAGE_WORK_DIR}" + if [ "$STAGE" = "export-image" ]; then + for img in "${STAGE_WORK_DIR}/"*.img; do + unmount_image "$img" + done + fi +} + +if [ "$(id -u)" != "0" ]; then + echo "Please run as root" 1>&2 + exit 1 +fi + +BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +if [[ $BASE_DIR = *" "* ]]; then + echo "There is a space in the base path of pi-gen" + echo "This is not a valid setup supported by debootstrap." + echo "Please remove the spaces, or move pi-gen directory to a base path without spaces" 1>&2 + exit 1 +fi + +export BASE_DIR + +if [ -f config ]; then + # shellcheck disable=SC1091 + source config +fi + +while getopts "c:" flag +do + case "$flag" in + c) + EXTRA_CONFIG="$OPTARG" + # shellcheck disable=SC1090 + source "$EXTRA_CONFIG" + ;; + *) + ;; + esac +done + +export PI_GEN=${PI_GEN:-pi-gen} +export PI_GEN_REPO=${PI_GEN_REPO:-https://github.com/RPi-Distro/pi-gen} +export PI_GEN_RELEASE=${PI_GEN_RELEASE:-Raspberry Pi reference} + +export ARCH="${ARCH:-arm64}" +export RELEASE=${RELEASE:-bookworm} +export IMG_NAME="${IMG_NAME:-chillcraftos-$RELEASE-$ARCH}" + +export USE_QEMU="${USE_QEMU:-0}" +export IMG_DATE="${IMG_DATE:-"$(date +%Y-%m-%d)"}" +export IMG_FILENAME="${IMG_FILENAME:-"${IMG_DATE}-${IMG_NAME}"}" +export ARCHIVE_FILENAME="${ARCHIVE_FILENAME:-"image_${IMG_DATE}-${IMG_NAME}"}" + +export SCRIPT_DIR="${BASE_DIR}/scripts" +export WORK_DIR="${WORK_DIR:-"${BASE_DIR}/work/${IMG_NAME}"}" +export DEPLOY_DIR=${DEPLOY_DIR:-"${BASE_DIR}/deploy"} + +export DEPLOY_COMPRESSION=${DEPLOY_COMPRESSION:-xz} +export COMPRESSION_LEVEL=${COMPRESSION_LEVEL:-6} +export LOG_FILE="${WORK_DIR}/build.log" + +export TARGET_HOSTNAME=${TARGET_HOSTNAME:-chillcraftos} +export FIRST_USER_NAME=${FIRST_USER_NAME:-system} +export FIRST_USER_PASS +export DISABLE_FIRST_BOOT_USER_RENAME=${DISABLE_FIRST_BOOT_USER_RENAME:-0} +export FIRST_USER_ISSYSTEM=${FIRST_USER_ISSYSTEM:-true} +export WPA_COUNTRY +export ENABLE_SSH="${ENABLE_SSH:-0}" +export PUBKEY_ONLY_SSH="${PUBKEY_ONLY_SSH:-0}" + +export LOCALE_DEFAULT="${LOCALE_DEFAULT:-en_US.UTF-8}" + +export KEYBOARD_KEYMAP="${KEYBOARD_KEYMAP:-us}" +export KEYBOARD_LAYOUT="${KEYBOARD_LAYOUT:-English (US)}" + +export TIMEZONE_DEFAULT="${TIMEZONE_DEFAULT:-Americas/Los_Angeles}" + +export GIT_HASH=${GIT_HASH:-"$(git rev-parse HEAD)"} + +export PUBKEY_SSH_FIRST_USER + +export CLEAN +export APT_PROXY + +export STAGE +export STAGE_DIR +export STAGE_WORK_DIR +export PREV_STAGE +export PREV_STAGE_DIR +export ROOTFS_DIR +export PREV_ROOTFS_DIR +export IMG_SUFFIX +export NOOBS_NAME +export NOOBS_DESCRIPTION +export EXPORT_DIR +export EXPORT_ROOTFS_DIR + +export QUILT_PATCHES +export QUILT_NO_DIFF_INDEX=1 +export QUILT_NO_DIFF_TIMESTAMPS=1 +export QUILT_REFRESH_ARGS="-p ab" + +# shellcheck source=scripts/common +source "${SCRIPT_DIR}/common" +# shellcheck source=scripts/dependencies_check +source "${SCRIPT_DIR}/dependencies_check" + +if [ "$SETFCAP" != "1" ]; then + export CAPSH_ARG="--drop=cap_setfcap" +fi + +mkdir -p "${WORK_DIR}" +trap term EXIT INT TERM + +dependencies_check "${BASE_DIR}/depends" + + +PAGESIZE=$(getconf PAGESIZE) +if [ "$ARCH" == "armhf" ] && [ "$PAGESIZE" != "4096" ]; then + echo + echo "ERROR: Building an $ARCH image requires a kernel with a 4k page size (current: $PAGESIZE)" + echo "On Raspberry Pi OS (64-bit), you can switch to a suitable kernel by adding the following to /boot/firmware/config.txt and rebooting:" + echo + echo "kernel=kernel8.img" + echo "initramfs initramfs8 followkernel" + echo + exit 1 +fi + +echo "Checking native $ARCH executable support..." +if ! arch-test -n "$ARCH"; then + echo "WARNING: Only a native build environment is supported. Checking emulated support..." + if ! arch-test "$ARCH"; then + echo "No fallback mechanism found. Ensure your OS has binfmt_misc support enabled and configured." + exit 1 + fi +fi + +#check username is valid +if [[ ! "$FIRST_USER_NAME" =~ ^[a-z][-a-z0-9_]*$ ]]; then + echo "Invalid FIRST_USER_NAME: $FIRST_USER_NAME" + exit 1 +fi + +if [[ "$DISABLE_FIRST_BOOT_USER_RENAME" == "1" ]] && [ -z "${FIRST_USER_PASS}" ]; then + echo "To disable user rename on first boot, FIRST_USER_PASS needs to be set" + echo "Not setting FIRST_USER_PASS makes your system vulnerable and open to cyberattacks" + exit 1 +fi + +if [[ "$DISABLE_FIRST_BOOT_USER_RENAME" == "1" ]]; then + echo "User rename on the first boot is disabled" + echo "Be advised of the security risks linked to shipping a device with default username/password set." +fi + +if [[ -n "${APT_PROXY}" ]] && ! curl --silent "${APT_PROXY}" >/dev/null ; then + echo "Could not reach APT_PROXY server: ${APT_PROXY}" + exit 1 +fi + +if [[ -n "${WPA_PASSWORD}" && ${#WPA_PASSWORD} -lt 8 || ${#WPA_PASSWORD} -gt 63 ]] ; then + echo "WPA_PASSWORD" must be between 8 and 63 characters + exit 1 +fi + +if [[ "${PUBKEY_ONLY_SSH}" = "1" && -z "${PUBKEY_SSH_FIRST_USER}" ]]; then + echo "Must set 'PUBKEY_SSH_FIRST_USER' to a valid SSH public key if using PUBKEY_ONLY_SSH" + exit 1 +fi + +log "Begin ${BASE_DIR}" + +STAGE_LIST=${STAGE_LIST:-${BASE_DIR}/stage*} +export STAGE_LIST + +EXPORT_CONFIG_DIR=$(realpath "${EXPORT_CONFIG_DIR:-"${BASE_DIR}/export-image"}") +if [ ! -d "${EXPORT_CONFIG_DIR}" ]; then + echo "EXPORT_CONFIG_DIR invalid: ${EXPORT_CONFIG_DIR} does not exist" + exit 1 +fi +export EXPORT_CONFIG_DIR + +for STAGE_DIR in $STAGE_LIST; do + STAGE_DIR=$(realpath "${STAGE_DIR}") + run_stage +done + +CLEAN=1 +for EXPORT_DIR in ${EXPORT_DIRS}; do + STAGE_DIR=${EXPORT_CONFIG_DIR} + # shellcheck source=/dev/null + source "${EXPORT_DIR}/EXPORT_IMAGE" + EXPORT_ROOTFS_DIR=${WORK_DIR}/$(basename "${EXPORT_DIR}")/rootfs + run_stage + if [ "${USE_QEMU}" != "1" ]; then + if [ -e "${EXPORT_DIR}/EXPORT_NOOBS" ]; then + # shellcheck source=/dev/null + source "${EXPORT_DIR}/EXPORT_NOOBS" + STAGE_DIR="${BASE_DIR}/export-noobs" + run_stage + fi + fi +done + +if [ -x "${BASE_DIR}/postrun.sh" ]; then + log "Begin postrun.sh" + cd "${BASE_DIR}" + ./postrun.sh + log "End postrun.sh" +fi + +log "End ${BASE_DIR}"