#!/usr/bin/env bash # Script to download and run OpenWRT image builder with some config file ############################################################################### # OpenWRT target image config defaults ############################################################################### # Default configuration (file) to use config_name="archer-c6-v3" # Release to fetch and build (can be "snapshot") RELEASE="" # Which target CPU architecture to build image for. # See targets here: https://downloads.openwrt.org/snapshots/targets TARGET="" # What profile (platform/device) to build for this TARGET PROFILE="" FILES="" DISABLED_SERVICES="" # See https://openwrt.org/packages/ for list of all packages #PACKAGES=" #luci luci-app-uhttpd #luci-theme-bootstrap luci-theme-openwrt luci-theme-openwrt-2020 #luci-app-wireguard kmod-wireguard wireguard-tools #zoneinfo-europe #kmod-usb-net-rtl8150 kmod-usb-net-rtl8152 #" # glob to use for searching for USB SD-card reader device dev_usb_sdcard_glob=/dev/disk/by-id/usb-Generic-*-0:0 ############################################################################### # console colors ############################################################################### if [ -t 1 ]; then c_red="\e[31m"; c_green="\e[32m"; c_yellow="\e[33m"; c_mag="\e[35m" c_cyan="\e[36m"; c_white="\e[37m"; c_ired="\e[91m"; c_igreen="\e[92m" c_iyellow="\e[93m"; c_imag="\e[95m"; c_icyan="\e[96m"; c_iwhite="\e[97m" c_igrey="\e[90m"; c_reset="\e[0m"; c_bold="\e[1m"; c_inv="\e[7m" fi echo_run() { echo -e "\$ ${c_green}$*${c_reset}"; if [ -z "${dryrun}" ]; then eval "$*"; else true; fi; } echo_run_nodry() { echo -e "\$ ${c_green}$*${c_reset}"; eval "$*"; } echo_ok() { echo -e "${c_imag}$*${c_reset}"; } echo_note() { echo -e "${c_iyellow}$*${c_reset}"; } echo_bold() { echo -e "${c_icyan}$*${c_reset}"; } echo_inv() { echo -e "${c_inv}$*${c_reset}"; } warn() { echo >&2 -e "${c_iyellow}WARNING: $*${c_reset}"; } error() { echo >&2 -e "${c_ired}ERROR: $*${c_reset}"; } die() { error "$*"; exit 1; } verb() { [ -n "${VERBOSE}" ] && echo "$*"; } ############################################################################### # ############################################################################### openwrt_url=https://downloads.openwrt.org load_config() { local name=$1 . configs/common || die "FAILED to load config from ${f}" for f in configs/${name} configs/${name}.sh; do if [ -f ${f} ]; then . "${f}" || die "FAILED to load config from ${f}" echo "Loaded config ${f}" return 0 fi done die "configuration file ${name} not found in configs" } # setup file and directory names of image builder and final image: # target_with_dash # imagebuilder_dir # image_file_base # image_tarball init_vars() { echo "Current config:" for v in RELEASE TARGET PROFILE; do printf " %-10s = %s\n" "${v}" "${!v}" [ -n "${!v}" ] || die "Config variable ${v} has no value" done target_with_dash=$(echo "${TARGET}" | tr '/' '-') if [ "${RELEASE}" = "snapshot" ]; then tarball=openwrt-imagebuilder-${target_with_dash}.Linux-x86_64.tar.xz url_path="snapshots/targets/${TARGET}/${tarball}" else tarball=openwrt-imagebuilder-${RELEASE}-${target_with_dash}.Linux-x86_64.tar.xz url_path="releases/${RELEASE}/targets/${TARGET}/${tarball}" fi imagebuilder_dir=${tarball%%.tar*} } todo_action() { echo "${actions}" | grep -q "$1" } fetch_image_builder() { echo_note "Downloading ${RELEASE} build from: ${openwrt_url}/${url_path}" if [ -f "${tarball}" ]; then echo_ok "${tarball} already exists, skipping fetch" else echo_run "wget ${openwrt_url}/${url_path}" || die "wget FAILED" fi if [ -d ${imagebuilder_dir} ]; then echo_ok "${imagebuilder_dir} already exists, skipping unpack" else echo_run "tar xf ${tarball}" || die "tar xf FAILED" fi } locate_files_dir() { for d in ../configs .. .; do local path=${d}/${FILES} if [ -d ${path} ]; then echo_note "Using FILES = ${path}" FILES=${path} return 0 fi done die "FAILED to locate FILES directory: ${FILES}" } image_build() { echo_inv "make image" locate_files_dir if [ -n "${CONFIG_TARGET_ROOTFS_PARTSIZE}" ]; then local configfile="${imagebuilder_dir}/.config" echo_note "Configuring CONFIG_TARGET_ROOTFS_PARTSIZE=${CONFIG_TARGET_ROOTFS_PARTSIZE}" echo_note " by appending to ${configfile}" echo "CONFIG_TARGET_ROOTFS_PARTSIZE=${CONFIG_TARGET_ROOTFS_PARTSIZE}" \ >> .config fi PACKAGES=$(echo "${PACKAGES}" | tr '\n' ' ') echo_run "make image PROFILE='${PROFILE}' FILES='${FILES}' PACKAGES='${PACKAGES}' DISABLED_SERVICES='${DISABLED_SERVICES}'" || die "image build FAILED" } image_builder_make_info() { echo_inv "make info" echo_run "make info" || die "image build FAILED" local file=bin/targets/${TARGET}/${image_tarball} [ -f ${file} ] && echo_run "gunzip -f ${file}" } image_write_to_sdcard() { echo_inv "Determining SD card write command" # find the USB device that holds the SD-Card: if echo_run "ls -lh ${dev_usb_sdcard_glob}"; then realdev=$(readlink -f ${dev_usb_sdcard_glob}) echo_note "Using device ${realdev}" else echo_note "No USB storage device detected:" echo_note "You will have to insert correct USB_STORAGE device in the command below" realdev="USB_STORAGE" fi image_names_gz=$(find bin/targets/${TARGET} -name '*factory.img.gz') [ -n "${image_names_gz}" ] && echo "Unzipping images" for f in ${image_names_gz}; do echo_run "gunzip -f ${f}" done echo "Finding factory images for SD card writing:" echo_run "(cd bin/targets/${TARGET} && ls -1 *factory.img)" image_names=$(find bin/targets/${TARGET} -name '*factory.img') image_tarball=$(echo "${image_names}" | head -n1) echo_note "Here are the commands for SD card write. Verify before running:" if mount | grep "${realdev}" >/dev/null; then echo_bold "sudo umount ${realdev}?" fi echo_bold "sudo dd if=${imagebuilder_dir}/${image_tarball} \\ of=${realdev} \\ bs=1M status=progress && sync" [ "${realdev}" = "USB_STORAGE" ] && \ echo "where USB_STORAGE is the USB storage device" } show_output_info() { echo_inv "Final output info" manifest="$(ls ${imagebuilder_dir}/bin/targets/${TARGET}/*.manifest)" if ls ${imagebuilder_dir}/build_dir/target-*/root* >/dev/null; then echo_note "Image manifest is here:" echo " ${manifest}" fi if ls ${imagebuilder_dir}/build_dir/target-*/root* >/dev/null; then echo_note "Original and modified rootfs is here:" echo_run "ls -d1 ${imagebuilder_dir}/build_dir/target-*/root*" fi if [ -d ${imagebuilder_dir}/bin/targets/${TARGET} ]; then echo_note "Final images are in ${imagebuilder_dir}/bin/targets/${TARGET}" echo_run "(cd ${imagebuilder_dir}/bin/targets/${TARGET} && find . -name '*.bin' -o -name '*.img*' |xargs ls -lh)" echo_note "sysupgrade images:" echo_run "ls -1 ${imagebuilder_dir}/bin/targets/${TARGET}/*-sysupgrade.{bin,img.gz}* 2>/dev/null" # determine most likely sysupgrade file (squashfs) and its suffix file_sysupgrade_squashfs="$(find ${imagebuilder_dir}/bin/targets/${TARGET} -name '*-squashfs-sysupgrade.bin' -o -name '*-squashfs-sysupgrade.img.gz')" file_suffix=$(echo ${file_sysupgrade_squashfs} | sed -r "s/.*-sysupgrade.(.*)/\1/") echo_note "Run following commands to perform a system upgrade:" cat << EOF scp FILE.img.gz HOST:/tmp ssh HOST '/sbin/sysupgrade -v /tmp/*.img.gz' EOF echo_note "For example (for current config, ${config_name}):" cat << EOF scp ${file_sysupgrade_squashfs} 192.168.1.1:/tmp ssh 192.168.1.1 '/sbin/sysupgrade -v /tmp/*.${file_suffix}' EOF else echo_bold "directory not found: ${imagebuilder_dir}/bin/targets/${TARGET}" echo_bold "which means we built nothing!?" fi } ############################################################################### # ############################################################################### usage() { cat <