diff --git a/build_complete.sh b/build_complete.sh new file mode 100755 index 0000000..990ec98 --- /dev/null +++ b/build_complete.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +set -e +if [ "$DEBUG" ]; then + set -x + export DEBUG=1 +fi + +. ./common.sh + +if [ "$EUID" -ne 0 ]; then + echo "This script must be run as root." + exit 1 +fi + +if [ -z "$1" ]; then + echo "Usage: ./build_complete.sh board_name" + echo "Valid named arguments (specify with 'key=value'):" + echo " compress_img - Compress the final disk image into a zip file. Set this to any value to enable this option." + exit 1 +fi + +cleanup_path="" +sigint_handler() { + if [ $cleanup_path ]; then + rm -rf $cleanup_path + fi + exit 1 +} +trap sigint_handler SIGINT + +base_dir="$(realpath $(dirname "$0"))" +board="$1" +shim_url="https://dl.osu.bio/api/raw/?path=/SH1mmer/$board.zip" +boards_url="https://chromiumdash.appspot.com/cros/fetch_serving_builds?deviceCategory=ChromeOS" + +echo "downloading list of recovery images" +reco_url="$(wget -qO- --show-progress $boards_url | python3 -c ' +import json, sys + +all_builds = json.load(sys.stdin) +board = all_builds["builds"][sys.argv[1]] +if "models" in board: + board = next(iter(board["models"].values())) + +reco_url = list(board["pushRecoveries"].values())[-1] +print(reco_url) +' $board)" +echo "found url: $reco_url" + +shim_bin="$base_dir/data/shim_$board.bin" +shim_zip="$base_dir/data/shim_$board.zip" +reco_bin="$base_dir/data/reco_$board.bin" +reco_zip="$base_dir/data/reco_$board.zip" +mkdir -p "$base_dir/data" + +download_and_unzip() { + local url="$1" + local zip_path="$2" + local bin_path="$3" + if [ ! -f "$bin_path" ]; then + wget -q --show-progress $url -O $zip_path -c + fi + if [ ! -f "$bin_path" ]; then + cleanup_path="$bin_path" + echo "extracting $zip_path" + local total_bytes="$(unzip -lq $zip_path | tail -1 | xargs | cut -d' ' -f1)" + unzip -p $zip_path | pv -s $total_bytes > $bin_path + rm -rf $zip_path + cleanup_path="" + fi +} + +echo "downloading recovery image" +download_and_unzip $reco_url $reco_zip $reco_bin + +echo "downloading shim image" +download_and_unzip $shim_url $shim_zip $shim_bin + +rootfs_dir="$(realpath data/rootfs_$board)" +rm -rf $rootfs_dir +mkdir -p $rootfs_dir + +echo "building debian rootfs" +./build_rootfs.sh $rootfs_dir bookworm \ + hostname=shimboot-$board \ + root_passwd=root \ + username=user \ + user_passwd=user + +echo "patching debian rootfs" +./patch_rootfs.sh $shim_bin $reco_bin $rootfs_dir + +echo "building final disk image" +final_image="$base_dir/data/shimboot_$board.bin" +./build.sh $final_image $shim_bin data/rootfs +echo "build complete! the final disk image is located at $final_image" + +if [ "${args['compress_img']}" ]; then + image_zip="$base_dir/data/shimboot_$board.zip" + echo "compressing disk image into a zip file" + zip -j $image_zip $final_image + echo "finished compressing the disk file" + echo "the finished zip file can be found at $image_zip" +fi \ No newline at end of file diff --git a/build_rootfs.sh b/build_rootfs.sh index d1dc2b6..30e8af9 100755 --- a/build_rootfs.sh +++ b/build_rootfs.sh @@ -7,55 +7,56 @@ if [ "$DEBUG" ]; then set -x fi -print_help() { - echo "Usage: ./build_rootfs.sh rootfs_path release_name [custom_packages]" -} - -check_deps() { - local needed_commands="realpath debootstrap" - for command in $needed_commands; do - if ! command -v $command &> /dev/null; then - echo $command - fi - done -} +. ./common.sh if [ "$EUID" -ne 0 ]; then - echo "this needs to be run as root." + echo "This script must be run as root." exit 1 fi if [ -z "$2" ]; then - print_help + echo "Usage: ./build_rootfs.sh rootfs_path release_name" + echo "Valid named arguments (specify with 'key=value'):" + echo " custom_packages - The packages that will be installed in place of task-xfce-desktop." + echo " hostname - The hostname for the new rootfs." + echo " root_passwd - The root password." + echo " username - The unprivileged user name for the new rootfs." + echo " user_passwd - The password for the unprivileged user." + echo "If you do not specify the hostname and credentials, you will be prompted for them later." exit 1 fi -missing_commands=$(check_deps) -if [ "${missing_commands}" ]; then - echo "You are missing dependencies needed for this script." - echo "Commands needed:" - echo "${missing_commands}" - exit 1 -fi +assert_deps "realpath debootstrap" +parse_args "$@" rootfs_dir=$(realpath "${1}") release_name="${2}" -packages="${3-'task-xfce-desktop'}" +packages="${args['custom_packages']-'task-xfce-desktop'}" +chroot_mounts="proc sys dev run" + +unmount_all() { + for mountpoint in $chroot_mounts; do + umount -l "$rootfs_dir/$mountpoint" + done +} debootstrap --arch amd64 $release_name $rootfs_dir http://deb.debian.org/debian/ cp -ar rootfs/* $rootfs_dir cp /etc/resolv.conf $rootfs_dir/etc/resolv.conf -chroot_mounts="proc sys dev run" +trap unmount_all EXIT for mountpoint in $chroot_mounts; do mount --make-rslave --rbind "/${mountpoint}" "${rootfs_dir}/$mountpoint" done -chroot_command="/opt/setup_rootfs.sh '$DEBUG' '$release_name' '$packages'" -chroot $rootfs_dir /bin/bash -c "${chroot_command}" +hostname="${args['hostname']}" +root_passwd="${args['root_passwd']}" +username="${args['username']}" +user_passwd="${args['user_passwd']}" -for mountpoint in $chroot_mounts; do - umount -l "${rootfs_dir}/$mountpoint" -done +chroot_command="/opt/setup_rootfs.sh '$DEBUG' '$release_name' '$packages' '$hostname' '$root_passwd' '$username' '$user_passwd'" +chroot $rootfs_dir /bin/bash -c "${chroot_command}" +trap - EXIT +unmount_all echo "rootfs has been created" \ No newline at end of file diff --git a/common.sh b/common.sh new file mode 100755 index 0000000..ae71d56 --- /dev/null +++ b/common.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +check_deps() { + local needed_commands="$1" + for command in $needed_commands; do + if ! command -v $command &> /dev/null; then + echo $command + fi + done +} + +assert_deps() { + local needed_commands="$1" + local missing_commands=$(check_deps "$needed_commands") + if [ "${missing_commands}" ]; then + echo "You are missing dependencies needed for this script." + echo "Commands needed:" + echo "${missing_commands}" + exit 1 + fi +} + +parse_args() { + declare -g -A args + for argument in "$@"; do + local key=$(echo $argument | cut -f1 -d=) + local key_length=${#key} + local value="${argument:$key_length+1}" + args["$key"]="$value" + done +} \ No newline at end of file diff --git a/rootfs/opt/setup_rootfs.sh b/rootfs/opt/setup_rootfs.sh index a28df18..f2c6279 100755 --- a/rootfs/opt/setup_rootfs.sh +++ b/rootfs/opt/setup_rootfs.sh @@ -3,19 +3,26 @@ #setup the debian rootfs #this is meant to be run within the chroot created by debootstrap -DEBUG="$1" -release_name="$2" -packages="$3" - set -e if [ "$DEBUG" ]; then set -x fi +DEBUG="$1" +release_name="$2" +packages="$3" + +hostname="$4" +root_passwd="$5" +username="$6" +user_passwd="$7" + custom_repo="https://shimboot.ading.dev/debian" custom_repo_domain="shimboot.ading.dev" sources_entry="deb [trusted=yes arch=amd64] ${custom_repo} ${release_name} main" +export DEBIAN_FRONTEND=noninteractive + #add shimboot repos echo -e "${sources_entry}\n$(cat /etc/apt/sources.list)" > /etc/apt/sources.list tee -a /etc/apt/preferences << END @@ -43,7 +50,9 @@ PERCENT=50 END #set up hostname and username -read -p "Enter the hostname for the system: " hostname +if [ ! "$hostname" ]; then + read -p "Enter the hostname for the system: " hostname +fi echo "${hostname}" > /etc/hostname tee -a /etc/hosts << END 127.0.0.1 localhost @@ -56,16 +65,27 @@ ff02::2 ip6-allrouters END echo "Enter a root password:" -while ! passwd root; do - echo "Failed to set password, please try again." -done +if [ ! "$root_passwd" ]; then + while ! passwd root; do + echo "Failed to set password, please try again." + done +else + yes "$root_passwd" | passwd root +fi -read -p "Enter the username for the user account: " username +if [ ! $username ]; then + read -p "Enter the username for the user account: " username +fi useradd -m -s /bin/bash -G sudo $username -echo "Enter the password for ${username}:" -while ! passwd $username; do - echo "Failed to set password, please try again." -done + +if [ ! "$user_passwd" ]; then + echo "Enter the password for ${username}:" + while ! passwd $username; do + echo "Failed to set password, please try again." + done +else + yes "$user_passwd" | passwd $username +fi #clean apt caches apt-get clean \ No newline at end of file