openwrtBuild 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #!/usr/bin/env bash
  2. source ./functions.sh
  3. #####################
  4. ##### DEFAULTS ######
  5. #####################
  6. setDefaults() {
  7. debug "${FUNCNAME[0]}"
  8. [[ -z $_debug ]] && _debug="true" # Set to true to enable debugging by default
  9. [[ -z $_builddir ]] && _builddir="$PWD"
  10. [[ -z $_filesroot ]] && _filesroot="$_builddir/files/"
  11. # Global default packages for all profiles
  12. declare -ag _packages=("luci" "nano" "htop" "tcpdump" "diffutils")
  13. # If no profile is specified, use the TP-Link Archer C7 v2
  14. [[ -z $_profile ]] && _profile="tplink_archer-c7-v2"
  15. # Custom profiles
  16. # TP-Link Archer C7 v2 dumb AP
  17. if [[ -z $_target ]]; then
  18. if [[ "$_profile" == "tplink_archer-c7-v2" ]]; then
  19. [[ -z $_version ]] && _version="19.07.2"
  20. [[ -z $_target ]] && _target="ath79/generic"
  21. _packages+=("-dnsmasq" "-odhcpd")
  22. # Raspberry Pi 4B router with USB->Ethernet dongle
  23. elif [[ "$_profile" == "rpi-4" ]]; then
  24. [[ -z $_version ]] && _version="snapshot"
  25. [[ -z $_target ]] && _target="bcm27xx/bcm2711"
  26. _packages+=("kmod-usb-net-asix-ax88179" "luci-app-upnp" "luci-app-wireguard" \
  27. "luci-app-vpn-policy-routing" "-dnsmasq" "dnsmasq-full" "luci-app-ddns")
  28. fi
  29. fi
  30. }
  31. #####################
  32. ##### FUNCTIONS #####
  33. #####################
  34. printHelpAndExit() {
  35. debug "${FUNCNAME[0]}"
  36. cat <<-'EOF'
  37. USAGE:
  38. openwrtBuild [[OPTION] [VALUE]]...
  39. If PROFILE is set and TARGET is not, buildOpenwrt can use a custom profile specified in DEFAULTS
  40. OPTIONS
  41. --version, -v OPENWRT_VERSION
  42. --target, -t TARGET
  43. --profile, -p PROFILE
  44. --builddir, -b PATH
  45. --ssh-upgrade SSH_PATH
  46. Example: root@192.168.1.1
  47. --flash, -f DEVICE
  48. Example: /dev/sdX
  49. --debug, -d
  50. --help, -h
  51. EOF
  52. # Exit using passed exit code
  53. [[ -z $1 ]] && exit 0 || exit "$1"
  54. }
  55. parseInput() {
  56. debug "${FUNCNAME[0]}"
  57. if _input=$(getopt -o +v:t:p:b:f:dh -l version:,target:,profile:,builddir:,ssh-upgrade:,flash:,debug,help -- "$@"); then
  58. eval set -- "$_input"
  59. while true; do
  60. case "$1" in
  61. --version|-v)
  62. shift && _version="$1"
  63. ;;
  64. --target|-t)
  65. shift && _target="$1"
  66. ;;
  67. --profile|-p)
  68. shift && _profile="$1"
  69. ;;
  70. --builddir|-b)
  71. shift && _builddir="$1"
  72. ;;
  73. --ssh-upgrade)
  74. shift && _ssh_upgrade_path="$1"
  75. ;;
  76. --flash|-f)
  77. shift && _flash_dev="$1"
  78. ;;
  79. --debug|-d)
  80. echo "Debugging on"
  81. _debug="true"
  82. ;;
  83. --help|-h)
  84. _printHelpAndExit 0
  85. ;;
  86. --)
  87. shift
  88. break
  89. ;;
  90. esac
  91. shift
  92. done
  93. else
  94. echo "Incorrect options provided"
  95. printHelpAndExit 1
  96. fi
  97. }
  98. debug () { [[ "$_debug" == "true" ]] && echo "Running: " "$@" ; }
  99. setVars() {
  100. debug "${FUNCNAME[0]}"
  101. getOS () {
  102. debug "${FUNCNAME[0]}"
  103. if [[ -f /etc/os-release ]]; then
  104. source /etc/os-release
  105. export ID="$ID"
  106. echo "Detected platform: $ID"
  107. else
  108. echo "Cannot detect OS!"
  109. exit 1
  110. fi
  111. }
  112. getOS
  113. export _source_archive="$_builddir/sources/$_profile-$_version.tar.xz"
  114. export _source_dir="${_source_archive%.tar.xz}"
  115. export _out_bin_dir="$_builddir/bin/$_profile-$_version/"
  116. export _out_bin_gz="$_out_bin_dir/openwrt-${_target//\//-}-$_profile-ext4-factory.img.gz"
  117. export _out_bin="${_out_bin_gz%.gz}"
  118. }
  119. installPrerequisites() {
  120. debug "${FUNCNAME[0]}"
  121. local -a _pkg_list
  122. local _pkg_cmd
  123. if [[ "$ID" == "fedora" ]]; then
  124. _pkg_list=("@c-development" "@development-tools" "@development-libs" "zlib-static" "elfutils-libelf-devel" "gawk" "unzip" "file" "wget" "python3" "python2" "axel")
  125. _pkg_cmd="dnf"
  126. elif [[ "$ID" =~ ^(debian|ubuntu)$ ]]; then
  127. _pkg_list=("build-essential" "libncurses5-dev" "libncursesw5-dev" "zlib1g-dev" "gawk" "git" "gettext" "libssl-dev" "xsltproc" "wget" "unzip" "python" "axel")
  128. _pkg_cmd="apt-get"
  129. fi
  130. echo "Installing dependencies"
  131. debug "sudo $_pkg_cmd -y install ${_pkg_list[*]}"
  132. if ! sudo "$_pkg_cmd" -y install "${_pkg_list[@]}" > /dev/null 2>&1; then
  133. echo "Warning: Problem installing prerequisites"
  134. return 1
  135. fi
  136. }
  137. acquireImageBuilder() {
  138. debug "${FUNCNAME[0]}"
  139. local _url _filename
  140. if [[ "$_version" == "snapshot" ]]; then
  141. _filename="openwrt-imagebuilder-${_target//\//-}.Linux-x86_64.tar.xz"
  142. _url="https://downloads.openwrt.org/snapshots/targets/$_target/$_filename"
  143. else
  144. _filename="openwrt-imagebuilder-$_version-${_target//\//-}.Linux-x86_64.tar.xz"
  145. _url="https://downloads.openwrt.org/releases/$_version/targets/$_target/$_filename"
  146. fi
  147. # Make sources directory if it does not exist
  148. [[ ! -d "$_builddir/sources" ]] && mkdir -p "$_builddir/sources"
  149. # Remove existing ImageBuilder archives
  150. [[ -f "$_source_archive" ]] && rm "$_source_archive"
  151. echo "Downloading image archive"
  152. debug "axel -o $_source_archive $_url"
  153. if ! axel -o "$_source_archive" "$_url" > /dev/null 2>&1; then
  154. echo "Could not download Image Builder"
  155. exit 1
  156. fi
  157. }
  158. extractImageBuilder() {
  159. debug "${FUNCNAME[0]}"
  160. [[ ! -d "$_source_dir" ]] && mkdir -p "$_source_dir"
  161. if [[ ! -f "$_source_archive" ]]; then
  162. echo "Archive missing"
  163. exit 1
  164. fi
  165. echo "Extracting image archive"
  166. debug "tar -xf $_source_archive -C $_source_dir --strip-components 1"
  167. if ! tar -xf "$_source_archive" -C "$_source_dir" --strip-components 1; then
  168. echo "Extraction failed"
  169. exit 1
  170. fi
  171. }
  172. makeImage() {
  173. debug "${FUNCNAME[0]}"
  174. # move to extracted source directory
  175. if ! pushd "$_source_dir" > /dev/null 2>&1; then
  176. exit 1
  177. fi
  178. # Make bin dir
  179. [[ ! -d "$_out_bin_dir" ]] && mkdir -p "$_out_bin_dir"
  180. # build image
  181. echo "Running make -j4 image BIN_DIR=$_out_bin_dir PROFILE=$_profile PACKAGES=${_packages[*]} FILES=$_filesroot"
  182. debug "make -j4 image BIN_DIR=$_out_bin_dir PROFILE=$_profile PACKAGES=${_packages[*]} FILES=$_filesroot > make.log"
  183. if ! make -j4 image BIN_DIR="$_out_bin_dir" PROFILE="$_profile" \
  184. PACKAGES="${_packages[*]}" FILES="$_filesroot" > make.log; then
  185. echo "Make image failed!"
  186. exit 1
  187. fi
  188. if ! popd > /dev/null 2>&1; then
  189. exit 1
  190. fi
  191. }
  192. flashImage() {
  193. debug "${FUNCNAME[0]}"
  194. extractImage "$_out_bin_gz"
  195. if [[ ! -d "$_flash_dev" ]]; then
  196. echo "The device specified by --flash could not be found"
  197. exit 1
  198. fi
  199. echo "Unmounting target device $_flash_dev partitions"
  200. debug "umount $_flash_dev?*"
  201. sudo umount "$_flash_dev?*"
  202. debug "sudo dd if=\"$_out_bin\" of=\"$_flash_dev\" bs=2M conv=fsync"
  203. if sudo dd if="$_out_bin" of="$_flash_dev" bs=2M conv=fsync; then
  204. sync
  205. echo "Image flashed sucessfully!"
  206. else
  207. echo "dd failed!"
  208. exit 1
  209. fi
  210. }
  211. sshUpgrade() {
  212. debug "${FUNCNAME[0]}"
  213. local _out_bin_gz_name="${_out_bin_gz##*/}"
  214. echo "Copying upgrade image to $_ssh_upgrade_path"
  215. debug "scp \"$_out_bin_gz\" \"$_ssh_upgrade_path:/tmp/$_out_bin_gz_name\""
  216. # shellcheck disable=SC2140
  217. if ! scp "$_out_bin_gz" "$_ssh_upgrade_path":"/tmp/$_out_bin_gz_name"; then
  218. echo "Could not access the --ssh-upgrade PATH"
  219. exit 1
  220. fi
  221. echo "Executing remote sysupgrade"
  222. debug "ssh \"$_ssh_upgrade_path\" \"sysupgrade -F /tmp/$_out_bin_gz_name\""
  223. # shellcheck disable=SC2029
  224. ssh "$_ssh_upgrade_path" "sysupgrade -F /tmp/$_out_bin_gz_name"
  225. }
  226. __main() {
  227. parseInput "$@"
  228. setDefaults
  229. setVars
  230. installPrerequisites
  231. acquireImageBuilder
  232. extractImageBuilder
  233. makeImage
  234. [[ -n $_ssh_upgrade_path ]] && sshUpgrade
  235. [[ -n $_flash_dev ]] && flashImage
  236. }
  237. __main "$@"
  238. exit $?