165 lines
5.7 KiB
Bash
Executable File
165 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
IFS=$'\n\t'
|
|
|
|
readonly SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
|
readonly PROJECT_USERPATCHES="${SCRIPT_DIR}/userpatches"
|
|
readonly SOURCE_LOCK="${PROJECT_USERPATCHES}/source-lock.env"
|
|
readonly FRAMEWORK_OVERRIDES="${SCRIPT_DIR}/framework-overrides"
|
|
|
|
die() {
|
|
echo "build-image.sh: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: build-image.sh --ssh-public-key PATH [OPTIONS]
|
|
|
|
Build the source-locked Armbian Debian Trixie image for Turing RK1.
|
|
|
|
Options:
|
|
--ssh-public-key PATH Required OpenSSH public-key/authorized_keys file.
|
|
--work-dir PATH Managed framework/cache directory (default: .work).
|
|
--prepare-only Clone/stage inputs, but do not invoke Armbian.
|
|
--config-dump Stage inputs and run Armbian's non-building config dump.
|
|
-h, --help Show this help.
|
|
|
|
The default action performs the full image build. It may ask for sudo through
|
|
Armbian's normal native-build launcher. No image is flashed by this command.
|
|
EOF
|
|
}
|
|
|
|
validate_public_keys() {
|
|
local key_file="${1}"
|
|
[[ -f "${key_file}" ]] || die "public-key file does not exist: ${key_file}"
|
|
[[ -s "${key_file}" ]] || die "public-key file is empty: ${key_file}"
|
|
command -v ssh-keygen >/dev/null || die "ssh-keygen is required to validate the public key"
|
|
|
|
awk '
|
|
/^[[:space:]]*($|#)/ { next }
|
|
$1 !~ /^(ssh-ed25519|ssh-rsa|ecdsa-sha2-nistp(256|384|521)|[email protected]|[email protected])$/ { exit 1 }
|
|
{ count++ }
|
|
END { if (count < 1) exit 1 }
|
|
' "${key_file}" || die "use plain OpenSSH public keys without authorized_keys options"
|
|
ssh-keygen -l -f "${key_file}" >/dev/null || die "ssh-keygen rejected the supplied public-key file"
|
|
}
|
|
|
|
prepare_framework() {
|
|
local work_root="${1}"
|
|
local framework_dir="${work_root}/armbian-build"
|
|
local origin
|
|
|
|
install -d -m 0755 "${work_root}"
|
|
work_root="$(cd -- "${work_root}" && pwd -P)"
|
|
framework_dir="${work_root}/armbian-build"
|
|
[[ "${work_root}" != "/" ]] || die "refusing to use / as the work directory"
|
|
|
|
if [[ ! -e "${framework_dir}" ]]; then
|
|
git init "${framework_dir}" >/dev/null
|
|
git -C "${framework_dir}" remote add origin "${RK1_MEDIA_ARMBIAN_BUILD_URL}"
|
|
install -m 0600 /dev/null "${framework_dir}/.rk1-media-build-root"
|
|
fi
|
|
|
|
[[ -d "${framework_dir}/.git" ]] || die "work path is not a Git checkout: ${framework_dir}"
|
|
[[ -f "${framework_dir}/.rk1-media-build-root" ]] || die "work checkout is not managed by this script: ${framework_dir}"
|
|
origin="$(git -C "${framework_dir}" remote get-url origin)"
|
|
[[ "${origin}" == "${RK1_MEDIA_ARMBIAN_BUILD_URL}" ]] || die "unexpected Armbian origin: ${origin}"
|
|
|
|
if git -C "${framework_dir}" rev-parse --verify HEAD >/dev/null 2>&1; then
|
|
git -C "${framework_dir}" diff --quiet || die "tracked modifications exist in ${framework_dir}"
|
|
git -C "${framework_dir}" diff --cached --quiet || die "staged modifications exist in ${framework_dir}"
|
|
fi
|
|
|
|
if ! git -C "${framework_dir}" cat-file -e "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}^{commit}" 2>/dev/null; then
|
|
git -C "${framework_dir}" fetch --depth=1 origin "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}"
|
|
fi
|
|
git -C "${framework_dir}" checkout --detach "${RK1_MEDIA_ARMBIAN_BUILD_COMMIT}" >/dev/null
|
|
|
|
printf '%s\n' "${framework_dir}"
|
|
}
|
|
|
|
stage_userpatches() {
|
|
local framework_dir="${1}"
|
|
local public_key="${2}"
|
|
local destination="${framework_dir}/userpatches"
|
|
|
|
[[ -f "${framework_dir}/.rk1-media-build-root" ]] || die "refusing to stage into an unmanaged checkout"
|
|
[[ "${destination}" == "${framework_dir}/userpatches" ]] || die "internal userpatch path check failed"
|
|
[[ ! -L "${destination}" ]] || die "refusing to replace a symlinked userpatches directory"
|
|
if [[ -e "${destination}" ]]; then
|
|
[[ -f "${destination}/.rk1-media-managed" ]] || die "existing userpatches are not managed by this script"
|
|
rm -rf -- "${destination}"
|
|
fi
|
|
|
|
install -d -m 0755 "${destination}"
|
|
cp -a "${PROJECT_USERPATCHES}/." "${destination}/"
|
|
install -m 0600 /dev/null "${destination}/.rk1-media-managed"
|
|
install -d -m 0700 "${destination}/overlay/build-input"
|
|
install -m 0600 "${public_key}" "${destination}/overlay/build-input/authorized_keys"
|
|
install -m 0644 "${SOURCE_LOCK}" "${destination}/overlay/build-input/source-lock.env"
|
|
|
|
# Armbian supports immutable resolutions for otherwise moving branch inputs
|
|
# through config/sources/git_sources.json. This pins its firmware artifact.
|
|
cp -a "${FRAMEWORK_OVERRIDES}/." "${framework_dir}/"
|
|
}
|
|
|
|
main() {
|
|
local public_key=""
|
|
local work_dir="${SCRIPT_DIR}/.work"
|
|
local mode="build"
|
|
local framework_dir
|
|
|
|
while (($#)); do
|
|
case "${1}" in
|
|
--ssh-public-key)
|
|
(($# >= 2)) || die "--ssh-public-key requires a path"
|
|
public_key="${2}"
|
|
shift 2
|
|
;;
|
|
--work-dir)
|
|
(($# >= 2)) || die "--work-dir requires a path"
|
|
work_dir="${2}"
|
|
shift 2
|
|
;;
|
|
--prepare-only)
|
|
mode="prepare"
|
|
shift
|
|
;;
|
|
--config-dump)
|
|
mode="config-dump"
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*) die "unknown option: ${1}" ;;
|
|
esac
|
|
done
|
|
|
|
[[ -n "${public_key}" ]] || die "--ssh-public-key is required; the image never enables password login"
|
|
[[ -r "${SOURCE_LOCK}" ]] || die "source lock is missing: ${SOURCE_LOCK}"
|
|
# shellcheck source=userpatches/source-lock.env
|
|
source "${SOURCE_LOCK}"
|
|
validate_public_keys "${public_key}"
|
|
framework_dir="$(prepare_framework "${work_dir}")"
|
|
stage_userpatches "${framework_dir}" "${public_key}"
|
|
|
|
echo "Prepared Armbian ${RK1_MEDIA_ARMBIAN_BUILD_COMMIT} in ${framework_dir}"
|
|
case "${mode}" in
|
|
prepare)
|
|
echo "Configuration staged; no build was started."
|
|
;;
|
|
config-dump)
|
|
(cd "${framework_dir}" && CONFIG_DEFS_ONLY=yes ./compile.sh rk1-media config-dump)
|
|
;;
|
|
build)
|
|
(cd "${framework_dir}" && ./compile.sh rk1-media build)
|
|
echo "Images and checksums: ${framework_dir}/output/images"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
main "$@"
|