Files
2023-12-09 14:57:06 +05:00

337 lines
11 KiB
Bash
Executable File

#!/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 <<EOF
Usage: $(basename ${0##*/}) [OPTION..]
Download OpenWRT image builder and build image from configuration given
in a simple config file, optionally with additional packages and/or files.
The easiest way to use this builder is to copy and modify one of the config
files in the configs directory and then launch the script with:
$(basename ${0##*/}) -c NAME
where NAME is the name of the config file you made
Action options:
-b Build the image
-i Run 'make info' instead of building
-d Only download/fetch image builder from ${openwrt_url}
-w Print command for writing image to SD card
-n Dry run (only show commands, don't execute them)
Config options:
-c NAME Use configuration from file in configs/NAME
This is a more convenient way than supplying every option
as listed below. This option should come *before* any of the
advanced options below (if you need overriding of config file)
-h Print this help
Advanced Config options:
-r REL Build specific version
-t TARGET Download image builder for TARGET
Examples: ath79/generic, bcm27xx/bcm2711
-p NAME What profile to build (if multiple exist). Some targets
such as ath79/generic has multiple profiles while the RPi4 target,
bcm27xx/bcm2711 only has one.
Examples: tplink_archer-c7-v2 (with target th79/generic)
Without any options, info is shown for the last image built.
EOF
}
actions=""
dryrun=""
while [ -n "$1" ]; do
case $1 in
-c) config_name=$2; shift ;;
-r) RELEASE=$2; shift ;;
-t) TARGET=$2; shift ;;
-p) PROFILE=$2; shift ;;
-d) actions+="fetch ";;
-b) actions+="fetch build " ;;
-i) actions+="fetch info " ;;
-w) actions+="write " ;;
-n) dryrun=yes ;;
-h) usage; exit 0 ;;
*)
usage
die "Unknown option '$1'"
;;
esac
shift
done
load_config common
load_config ${config_name}
init_vars
echo_ok "actions = ${actions}"
todo_action fetch &&
fetch_image_builder
if [ -z "${actions}" ] && [ ! -d ${imagebuilder_dir} ]; then
die "No action supplied"
fi
echo_run_nodry "cd ${imagebuilder_dir}"
todo_action build &&
image_build
if todo_action write; then
if [ -d bin/targets/${TARGET} ]; then
image_write_to_sdcard
else
error "bin/targets/${TARGET} not found; You have probably not built yet?"
fi
fi
todo_action info && image_builder_make_info
echo_run_nodry "cd .."
show_output_info