openwrtbuilder 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. #!/usr/bin/env bash
  2. #
  3. # Copyright 2022-23 Bryan C. Roessler
  4. #
  5. # Build and deploy OpenWRT images
  6. #
  7. # Apache 2.0 License
  8. #
  9. # See README.md and ./profiles
  10. #
  11. # Set default release
  12. : "${RELEASE:="22.03.3"}"
  13. printHelp() {
  14. debug "${FUNCNAME[0]}"
  15. cat <<-'EOF'
  16. Build and deploy OpenWRT images
  17. USAGE:
  18. openwrtbuilder [OPTION [VALUE]]... -p PROFILE [-p PROFILE]...
  19. OPTIONS
  20. --profile,-p PROFILE
  21. --release,-r,--version,-v RELEASE ("snapshot", "22.03.3")
  22. --buildroot,-b PATH
  23. Default: location of openwrtbuilder script
  24. --source
  25. Build image from source, not from Image Builder
  26. --ssh-upgrade HOST
  27. Example: root@192.168.1.1
  28. --ssh-backup SSH_PATH
  29. Enabled by default for --ssh-upgrade
  30. --flash,-f DEVICE
  31. Example: /dev/sdX
  32. --reset
  33. Cleanup all source and output files
  34. --debug,-d
  35. --help,-h
  36. EXAMPLES
  37. ./openwrtbuilder -p r4s -r snapshot --debug
  38. ./openwrtbuilder -p ax6000_stock -r 23.03.3 --source --debug
  39. ./openwrtbuilder -p rpi4 -r 23.03.3 --flash /dev/sdX
  40. ./openwrtbuilder -p linksys -r snapshot --ssh-upgrade root@192.168.1.1
  41. EOF
  42. }
  43. init() {
  44. debug "${FUNCNAME[0]}"
  45. declare -g ID RPM_MGR SCRIPTDIR DL_TOOL
  46. debug || echo "To enable debugging output, use --debug or -d"
  47. # Save the script directory
  48. # https://stackoverflow.com/a/4774063
  49. SCRIPTDIR="$(cd -- "$(dirname "$0")" >/dev/null 2>&1 || exit $? ; pwd -P)"
  50. if [[ -e "/etc/os-release" ]]; then
  51. source "/etc/os-release"
  52. else
  53. err "/etc/os-release not found"
  54. err "Your OS is unsupported"
  55. printHelp
  56. exit 1
  57. fi
  58. debug "Detected host platform: $ID"
  59. # normalize distro ID
  60. case "$ID" in
  61. debian|arch)
  62. ;;
  63. centos|fedora)
  64. if hash dnf &>/dev/null; then
  65. RPM_MGR="dnf"
  66. elif hash yum &>/dev/null; then
  67. RPM_MGR="yum"
  68. fi
  69. ;;
  70. rhel)
  71. ID="centos"
  72. ;;
  73. linuxmint|neon|*ubuntu*)
  74. ID="ubuntu"
  75. ;;
  76. *suse*)
  77. ID="suse"
  78. ;;
  79. raspbian)
  80. ID="debian"
  81. ;;
  82. *)
  83. echo "Autodetecting distro, this may be unreliable"
  84. if hash dnf &>/dev/null; then
  85. ID="fedora"
  86. RPM_MGR="dnf"
  87. elif hash yum &>/dev/null; then
  88. ID="centos"
  89. RPM_MGR="yum"
  90. elif hash apt &>/dev/null; then
  91. ID="ubuntu"
  92. elif hash pacman &>/dev/null; then
  93. ID="arch"
  94. else
  95. return 1
  96. fi
  97. ;;
  98. esac
  99. debug "Using host platform: $ID"
  100. # Set distro-specific functions
  101. case "$ID" in
  102. fedora|centos)
  103. pkg_install(){ sudo "$RPM_MGR" install -y "$@"; }
  104. ;;
  105. debian|ubuntu)
  106. pkg_install(){ sudo apt-get install -y -q0 "$@"; }
  107. ;;
  108. suse)
  109. pkg_install(){ sudo zypper --non-interactive -q install --force --no-confirm "$@"; }
  110. ;;
  111. arch)
  112. pkg_install(){ sudo pacman -S --noconfirm --needed "$@"; }
  113. ;;
  114. esac
  115. if hash axel &>/dev/null; then
  116. DL_TOOL="axel"
  117. elif hash curl &>/dev/null; then
  118. DL_TOOL="curl"
  119. else
  120. echo "Downloading the Image Builder requires axel or curl!"
  121. return 1
  122. fi
  123. }
  124. readInput() {
  125. debug "${FUNCNAME[0]}"
  126. unset RESET
  127. declare -ga PROFILES
  128. declare long_opts='release:,version:,profile:,buildroot:,source,'
  129. long_opts+='ssh-upgrade:,ssh-backup:,flash:,reset,debug,help'
  130. if _input=$(getopt -o +r:v:p:b:sf:dh -l $long_opts -- "$@"); then
  131. eval set -- "$_input"
  132. while true; do
  133. case "$1" in
  134. --release|-r|--version|-v)
  135. shift && declare -g USER_RELEASE="$1"
  136. ;;
  137. --profile|-p)
  138. shift && PROFILES+=("$1")
  139. ;;
  140. --buildroot|-b)
  141. shift && BUILDROOT="$1"
  142. ;;
  143. --source|-s)
  144. FROM_SOURCE=1
  145. ;;
  146. --ssh-upgrade)
  147. shift && SSH_UPGRADE_PATH="$1"
  148. ;;
  149. --ssh-backup)
  150. shift && SSH_BACKUP_PATH="$1"
  151. ;;
  152. --flash|-f)
  153. shift && FLASH_DEV="$1"
  154. ;;
  155. --reset)
  156. RESET=1
  157. ;;
  158. --debug|-d)
  159. echo "Debugging on"
  160. DEBUG=1
  161. ;;
  162. --help|-h)
  163. printHelp && exit 0
  164. ;;
  165. --)
  166. shift
  167. break
  168. ;;
  169. esac
  170. shift
  171. done
  172. else
  173. echo "Incorrect options provided"
  174. printHelp && exit 1
  175. fi
  176. }
  177. installDependencies() {
  178. debug "${FUNCNAME[0]}"
  179. declare -a pkg_list
  180. # TODO please contribute your platform here
  181. if (( FROM_SOURCE )); then
  182. # For building from source with make
  183. # https://openwrt.org/docs/guide-developer/toolchain/install-buildsystem
  184. case "$ID" in
  185. fedora|centos)
  186. pkg_list+=(
  187. "bash-completion"
  188. "bzip2"
  189. "gcc"
  190. "gcc-c++"
  191. "git"
  192. "make"
  193. "ncurses-devel"
  194. "patch"
  195. "rsync"
  196. "tar"
  197. "unzip"
  198. "wget"
  199. "which"
  200. "diffutils"
  201. "python2"
  202. "python3"
  203. "perl-base"
  204. "perl-Data-Dumper"
  205. "perl-File-Compare"
  206. "perl-File-Copy"
  207. "perl-FindBin"
  208. "perl-Thread-Queue"
  209. "clang" # for qosify
  210. )
  211. ;;
  212. debian|ubuntu)
  213. pkg_list+=(
  214. "build-essential"
  215. "clang"
  216. "flex"
  217. "g++"
  218. "gawk"
  219. "gcc-multilib"
  220. "gettext"
  221. "git"
  222. "libncurses5-dev"
  223. "libssl-dev"
  224. "python3-distutils"
  225. "rsync"
  226. "unzip"
  227. "zlib1g-dev"
  228. "file"
  229. "wget"
  230. )
  231. ;;
  232. arch)
  233. pkg_list+=(
  234. "base-devel"
  235. "autoconf"
  236. "automake"
  237. "bash"
  238. "binutils"
  239. "bison"
  240. "bzip2"
  241. "clang"
  242. "fakeroot"
  243. "file"
  244. "findutils"
  245. "flex"
  246. "gawk"
  247. "gcc"
  248. "gettext"
  249. "git"
  250. "grep"
  251. "groff"
  252. "gzip"
  253. "libelf"
  254. "libtool"
  255. "libxslt"
  256. "m4"
  257. "make"
  258. "ncurses"
  259. "openssl"
  260. "patch"
  261. "pkgconf"
  262. "python"
  263. "rsync"
  264. "sed"
  265. "texinfo"
  266. "time"
  267. "unzip"
  268. "util-linux"
  269. "wget"
  270. "which"
  271. "zlib"
  272. )
  273. ;;
  274. esac
  275. else
  276. # For Imagebuilder
  277. case "$ID" in
  278. fedora|centos)
  279. pkg_list+=(
  280. "@c-development"
  281. "@development-tools"
  282. "@development-libs"
  283. "perl-FindBin"
  284. "zlib-static"
  285. "elfutils-libelf-devel"
  286. "gawk"
  287. "unzip"
  288. "file"
  289. "wget"
  290. "python3"
  291. "python2"
  292. "axel"
  293. )
  294. ;;
  295. debian|ubuntu)
  296. pkg_list+=(
  297. "build-essential"
  298. "libncurses5-dev"
  299. "libncursesw5-dev"
  300. "zlib1g-dev"
  301. "gawk"
  302. "git"
  303. "gettext"
  304. "libssl-dev"
  305. "xsltproc"
  306. "wget"
  307. "unzip"
  308. "python"
  309. "axel"
  310. )
  311. ;;
  312. esac
  313. fi
  314. pkg_install "${pkg_list[@]}"
  315. }
  316. getImageBuilder() {
  317. debug "${FUNCNAME[0]}"
  318. if [[ -f "$IB_ARCHIVE" ]]; then
  319. if askOK "$IB_ARCHIVE exists. Re-download?"; then
  320. rm -f "$IB_ARCHIVE"
  321. else
  322. return 0
  323. fi
  324. fi
  325. echo "Downloading Image Builder archive using $DL_TOOL"
  326. debug "$DL_TOOL -o $IB_ARCHIVE $IB_URL"
  327. "$DL_TOOL" -o "$IB_ARCHIVE" "$IB_URL"
  328. }
  329. getImageBuilderChecksum() {
  330. debug "${FUNCNAME[0]}"
  331. if [[ -f $IB_SHA256_FILE ]]; then
  332. if askOk "$IB_SHA256_FILE exists. Re-download?"; then
  333. rm -f "$IB_SHA256_FILE"
  334. else
  335. return 0
  336. fi
  337. fi
  338. "$DL_TOOL" -o "$IB_SHA256_FILE" "$IB_SHA256_URL"
  339. }
  340. extractImageBuilder() {
  341. debug "${FUNCNAME[0]}"
  342. echo "Extracting Image Builder archive"
  343. [[ ! -d "$BUILDDIR" ]] && mkdir -p "$BUILDDIR"
  344. debug "tar -xf $IB_ARCHIVE -C $BUILDDIR --strip-components 1"
  345. if ! tar -xf "$IB_ARCHIVE" -C "$BUILDDIR" --strip-components 1; then
  346. echo "Extraction failed"
  347. return 1
  348. fi
  349. }
  350. addRepos() {
  351. debug "${FUNCNAME[0]}"
  352. if [[ -v P_ARR[repo] ]]; then
  353. if ! grep -q "${P_ARR[repo]}" "$BUILDDIR/repositories.conf"; then
  354. echo "${P_ARR[repo]}" >> "$BUILDDIR/repositories.conf"
  355. fi
  356. sed -i '/option check_signature/d' "$BUILDDIR/repositories.conf"
  357. fi
  358. }
  359. sshBackup() {
  360. debug "${FUNCNAME[0]}"
  361. local _date _hostname _backup_fname
  362. [[ -d "$FILESDIR" ]] || mkdir -p "$FILESDIR"
  363. printf -v _date '%(%Y-%m-%d-%H-%M-%S)T'
  364. _hostname=$(ssh -qt "$SSH_BACKUP_PATH" echo -n \$HOSTNAME)
  365. _backup_fname="backup-$_hostname-$_date.tar.gz"
  366. # Make backup archive on remote
  367. debug "ssh -t $SSH_BACKUP_PATH sysupgrade -b /tmp/$_backup_fname"
  368. if ! ssh -t "$SSH_BACKUP_PATH" "sysupgrade -b /tmp/$_backup_fname"; then
  369. echo "SSH backup failed"
  370. exit 1
  371. fi
  372. # Move backup archive locally
  373. debug "rsync -avz --remove-source-files $SSH_BACKUP_PATH:/tmp/$_backup_fname $BUILDDIR/"
  374. if ! rsync -avz --remove-source-files \
  375. "$SSH_BACKUP_PATH":"/tmp/$_backup_fname" "$BUILDDIR/"; then
  376. echo "Could not copy SSH backup"
  377. exit 1
  378. fi
  379. # Extract backup archive
  380. debug "tar -C $FILESDIR -xzf $BUILDDIR/$_backup_fname"
  381. if ! tar -C "$FILESDIR" -xzf "$BUILDDIR/$_backup_fname"; then
  382. echo "Could not extract SSH backup"
  383. exit 1
  384. fi
  385. rm "$BUILDDIR/$_backup_fname"
  386. }
  387. makeImages() {
  388. debug "${FUNCNAME[0]}"
  389. # Reuse the existing output
  390. if [[ -d "$THIS_BINDIR" ]]; then
  391. if askOk "$THIS_BINDIR exists. Rebuild?"; then
  392. rm -rf "$THIS_BINDIR"
  393. else
  394. return 0
  395. fi
  396. fi
  397. [[ -d "$BUILDDIR" ]] || mkdir -p "$BUILDDIR"
  398. make image \
  399. BIN_DIR="$THIS_BINDIR" \
  400. PROFILE="${P_ARR[profile]}" \
  401. PACKAGES="${P_ARR[packages]:+"${P_ARR[packages]}"}" \
  402. FILES="${FILESDIR}" \
  403. --directory="$BUILDDIR" \
  404. --jobs="$(nproc)" \
  405. > "$BUILDDIR/make.log"
  406. }
  407. verifyImages() {
  408. debug "${FUNCNAME[0]}"
  409. declare outfile
  410. for outfile in "$THIS_BINDIR"/*.img.gz; do
  411. verify "$outfile" "$IB_OUT_SHA256_FILE" || return 1
  412. done
  413. }
  414. flashImage() {
  415. debug "${FUNCNAME[0]}"
  416. declare img img_gz partitions
  417. if [[ ! -e "$FLASH_DEV" ]]; then
  418. echo "The device specified by --flash could not be found"
  419. exit 1
  420. fi
  421. # TODO Roughly choose the correct image
  422. if (( FROM_SOURCE )); then
  423. if [[ -f $SOURCEFACTORYIMGGZ &&
  424. -f $SOURCESYSUPGRADEIMGGZ ]]; then
  425. local _response
  426. echo "$SOURCEFACTORYIMGGZ and $SOURCESYSUPGRADEIMGGZ both exist"
  427. read -r -p "Flash factory or sysupgrade image? [(f)actory/(s)ysupgrade]" _response
  428. _response=${_response,,}
  429. if [[ "$_response" =~ ^(f|factory)$ ]]; then
  430. img_gz="$SOURCEFACTORYIMGGZ"
  431. img="$SOURCEFACTORYIMG"
  432. elif [[ "$_response" =~ ^(s|sysupgrade)$ ]]; then
  433. img_gz="$SOURCESYSUPGRADEIMGGZ"
  434. img="$SOURCESYSUPGRADEIMG"
  435. else
  436. echo "Invalid input, you must enter f or s"
  437. fi
  438. elif [[ -f $SOURCEFACTORYIMGGZ ]]; then
  439. img_gz="$SOURCEFACTORYIMGGZ"
  440. img="$SOURCEFACTORYIMG"
  441. elif [[ -f $SOURCESYSUPGRADEIMGGZ ]]; then
  442. img_gz="$SOURCESYSUPGRADEIMGGZ"
  443. img="$SOURCESYSUPGRADEIMG"
  444. else
  445. echo "No files found at $SOURCEFACTORYIMGGZ or $SOURCESYSUPGRADEIMGGZ"
  446. echo "Check your build output"
  447. return 1
  448. fi
  449. else
  450. if [[ -f $FACTORYIMGGZ &&
  451. -f $SYSUPGRADEIMGGZ ]]; then
  452. local _response
  453. echo "$FACTORYIMGGZ and $SYSUPGRADEIMGGZ both exist"
  454. read -r -p "Flash factory or sysupgrade image? [(f)actory/(s)ysupgrade]" _response
  455. _response=${_response,,}
  456. if [[ "$_response" =~ ^(f|factory)$ ]]; then
  457. img_gz="$FACTORYIMGGZ"
  458. img="$FACTORYIMG"
  459. elif [[ "$_response" =~ ^(s|sysupgrade)$ ]]; then
  460. img_gz="$SYSUPGRADEIMGGZ"
  461. img="$SYSUPGRADEIMG"
  462. else
  463. echo "Invalid input, you must enter f or s"
  464. fi
  465. elif [[ -f $FACTORYIMGGZ ]]; then
  466. img_gz="$FACTORYIMGGZ"
  467. img="$FACTORYIMG"
  468. elif [[ -f $SYSUPGRADEIMGGZ ]]; then
  469. img_gz="$SYSUPGRADEIMGGZ"
  470. img="$SYSUPGRADEIMG"
  471. else
  472. echo "No files found at $FACTORYIMGGZ or $SYSUPGRADEIMGGZ"
  473. echo "Check your build output"
  474. return 1
  475. fi
  476. fi
  477. debug "$img_gz $img"
  478. debug "gunzip -qfk $img_gz"
  479. gunzip -qfk "$img_gz"
  480. echo "Unmounting target device $FLASH_DEV partitions"
  481. partitions=( "$FLASH_DEV"?* )
  482. debug "umount ${partitions[*]}"
  483. sudo umount "${partitions[@]}"
  484. debug "sudo dd if=$img of=$FLASH_DEV bs=2M conv=fsync"
  485. if sudo dd if="$img" of="$FLASH_DEV" bs=2M conv=fsync; then
  486. sync
  487. echo "Image flashed sucessfully!"
  488. else
  489. echo "dd failed!"
  490. exit 1
  491. fi
  492. }
  493. sshUpgrade() {
  494. debug "${FUNCNAME[0]}"
  495. declare img_gz img_fname
  496. if (( FROM_SOURCE )); then
  497. if [[ -f $SOURCESYSUPGRADEIMGGZ ]]; then
  498. img_gz="$SOURCESYSUPGRADEIMGGZ"
  499. img_fname="$SOURCESYSUPGRADEIMGGZFNAME"
  500. fi
  501. elif [[ -f $SYSUPGRADEIMGGZ ]]; then
  502. img_gz="$SYSUPGRADEIMGGZ"
  503. img_fname="$SYSUPGRADEIMGGZFNAME"
  504. fi
  505. if [[ ! -f $img_gz ]]; then
  506. echo "$img_gz is missing, check build output"
  507. return 1
  508. fi
  509. echo "Copying '$img_gz' to $SSH_UPGRADE_PATH/tmp/$img_fname"
  510. debug "scp $img_gz $SSH_UPGRADE_PATH:/tmp/$img_fname"
  511. if ! scp "$img_gz" "$SSH_UPGRADE_PATH":"/tmp/$img_fname"; then
  512. echo "Could not copy $img_gz to $SSH_UPGRADE_PATH:/tmp/$img_fname"
  513. return 1
  514. fi
  515. echo "Executing remote sysupgrade"
  516. debug "ssh $SSH_UPGRADE_PATH sysupgrade -F /tmp/$img_fname"
  517. # shellcheck disable=SC2029
  518. # execute remotely
  519. # this will probably be a weird exit code from closed connection
  520. ssh "$SSH_UPGRADE_PATH" "sysupgrade -F /tmp/$img_fname"
  521. }
  522. fromSource() {
  523. debug "${FUNCNAME[0]}"
  524. declare src_url="https://github.com/openwrt/openwrt.git"
  525. declare pkg kopt opt
  526. declare -a make_opts config_opts
  527. declare -g SEED_FILE="$GITWORKTREEDIR/.config"
  528. echo "Building from source is under development"
  529. # Update source code
  530. if [[ ! -d "$GITSRCDIR" ]]; then
  531. mkdir -p "$GITSRCDIR"
  532. git clone "$src_url" "$GITSRCDIR"
  533. fi
  534. git -C "$GITSRCDIR" pull
  535. if [[ $RELEASE == "snapshot" ]]; then
  536. git -C "$GITSRCDIR" worktree add -d "$GITWORKTREEDIR" master
  537. else
  538. git -C "$GITSRCDIR" worktree add -d "$GITWORKTREEDIR" "v$RELEASE"
  539. fi
  540. pushd "$GITWORKTREEDIR" &>/dev/null || return 1
  541. # make clean # compiled output
  542. # make targetclean # compiled output, toolchain
  543. # make dirclean # compiled output, toolchain, build tools
  544. make distclean # compiled output, toolchain, build tools, .config, feeds, .ccache
  545. # Grab the release seed config
  546. if ! curl -so "$SEED_FILE" "$SEED_URL"; then
  547. echo "Could not obtain $SEED_FILE from $SEED_URL"
  548. return 1
  549. fi
  550. # Set compilation output dir
  551. config_opts+=("CONFIG_BINARY_FOLDER=\"$THIS_BINDIR\"")
  552. # Add custom packages
  553. for pkg in ${P_ARR[packages]}; do
  554. if [[ $pkg == -* ]]; then
  555. debug "Removing package ${pkg#-}"
  556. config_opts+=("CONFIG_PACKAGE_${pkg#-}=n") # remove package
  557. else
  558. debug "Adding package $pkg"
  559. config_opts+=("CONFIG_PACKAGE_$pkg=y") # add package
  560. fi
  561. done
  562. # Add kopts from profile
  563. for kopt in ${P_ARR[kopts]}; do
  564. config_opts+=("$kopt")
  565. done
  566. # Only compile selected fs
  567. sed -i '/CONFIG_TARGET_ROOTFS_/d' "$SEED_FILE"
  568. if [[ $FILESYSTEM == "squashfs" ]]; then
  569. config_opts+=("CONFIG_TARGET_ROOTFS_SQUASHFS=y")
  570. elif [[ $FILESYSTEM == "ext4" ]]; then
  571. config_opts+=("CONFIG_TARGET_ROOTFS_EXT4FS=y")
  572. fi
  573. # Only compile selected target
  574. sed -i '/CONFIG_TARGET_DEVICE_/d' "$SEED_FILE"
  575. # config_opts+=("CONFIG_TARGET_PER_DEVICE_ROOTFS=n")
  576. config_opts+=("CONFIG_TARGET_MULTI_PROFILE=n")
  577. # config_opts+=("CONFIG_TARGET_ALL_PROFILES=n")
  578. config_opts+=("CONFIG_TARGET_PROFILE=DEVICE_${P_ARR[profile]}")
  579. config_opts+=("CONFIG_TARGET_${P_ARR[target]//\//_}_DEVICE_${P_ARR[profile]}=y")
  580. # config_opts+=("CONFIG_TARGET_DEVICE_${P_ARR[target]//\//_}_DEVICE_${P_ARR[profile]}=y")
  581. config_opts+=("CONFIG_SDK=n")
  582. config_opts+=("CONFIG_SDK_LLVM_BPF=n")
  583. config_opts+=("CONFIG_IB=n")
  584. config_opts+=("CONFIG_MAKE_TOOLCHAIN=n")
  585. # Write options to config seed file
  586. for opt in "${config_opts[@]}"; do
  587. debug "Writing $opt to $SEED_FILE"
  588. echo "$opt" >> "$SEED_FILE"
  589. done
  590. # Update package feed
  591. # ./scripts/feeds install will run make defconfig for us
  592. # to normalize and expand .config
  593. ./scripts/feeds update -a &&
  594. ./scripts/feeds install -a
  595. # TODO for now symlink clang for qosify
  596. [[ -d "$GITSRCDIR/staging_dir/host/llvm-bpf/bin" ]] || mkdir -p "$GITSRCDIR/staging_dir/host/llvm-bpf/bin"
  597. ln -fs "$(which clang)" "$GITSRCDIR/staging_dir/host/llvm-bpf/bin/clang"
  598. (( DEBUG )) && make_opts+=("V=s")
  599. debug "make ${make_opts[*]} download"
  600. make "${make_opts[@]}" download
  601. debug "make ${make_opts[*]} -j$(nproc) world"
  602. make "${make_opts[@]}" -j"$(nproc)" world
  603. popd &>/dev/null || return 1
  604. exit # TODO exit here for fromSource() testing
  605. }
  606. debug() { (( DEBUG )) && echo "Debug: $*"; }
  607. askOk() {
  608. local _response
  609. read -r -p "$* [y/N]" _response
  610. _response=${_response,,}
  611. [[ "$_response" =~ ^(yes|y)$ ]]
  612. }
  613. resetAll() {
  614. debug "${FUNCNAME[0]}"
  615. askOk "Remove $SRCDIR and $BINDIR?" || exit $?
  616. debug "rm -rf $SRCDIR $BINDIR"
  617. rm -rf "$SRCDIR" "$BINDIR"
  618. }
  619. resetProfile() {
  620. debug "${FUNCNAME[0]}"
  621. askOk "Remove $BUILDDIR and $THIS_BINDIR?" || exit $?
  622. debug "rm -rf $BUILDDIR $THIS_BINDIR"
  623. rm -rf "$BUILDDIR" "$THIS_BINDIR"
  624. }
  625. loadProfiles() {
  626. debug "${FUNCNAME[0]}"
  627. declare -g PFILE
  628. PFILE="$SCRIPTDIR/profiles"
  629. # shellcheck source=./profiles
  630. ! source "$PFILE" && echo "profiles file missing!" && return 1
  631. }
  632. verify() {
  633. debug "${FUNCNAME[0]}"
  634. declare file_to_check="$1"
  635. declare sumfile="$2"
  636. declare checksum
  637. hash sha256sum &>/dev/null || return 1
  638. [[ -f $sumfile && -f $file_to_check ]] || return 1
  639. checksum=$(grep "${file_to_check##*/}" "$sumfile" | cut -f1 -d' ')
  640. echo -n "$checksum $file_to_check" | sha256sum --check --status
  641. }
  642. main() {
  643. debug "${FUNCNAME[0]}"
  644. init
  645. loadProfiles
  646. readInput "$@"
  647. # Fallback to SCRIPTDIR if BUILDROOT has not been set
  648. declare -g BUILDROOT="${BUILDROOT:=$SCRIPTDIR}"
  649. [[ $BUILDROOT == "/" ]] && echo "Invalid --buildroot" && exit 1
  650. declare -g FILESDIR="${FILESDIR:=$BUILDROOT/src/files}"
  651. declare -g SRCDIR="$BUILDROOT/src" # input/build
  652. declare -g BINDIR="$BUILDROOT/bin" # output
  653. declare -g GITSRCDIR="$SRCDIR/openwrt"
  654. for dir in "$SRCDIR" "$BINDIR"; do
  655. [[ -d "$dir" ]] || mkdir -p "$dir"
  656. done
  657. # Allow --reset without a profile
  658. if [[ ${#PROFILES} -lt 1 ]]; then
  659. if (( RESET )); then
  660. resetAll
  661. exit
  662. else
  663. echo "No profile supplied" && return 1
  664. fi
  665. fi
  666. installDependencies
  667. for profile in "${PROFILES[@]}"; do
  668. debug "Starting profile: $profile"
  669. if [[ ! ${!profile@a} = A ]]; then
  670. echo "Profile '$profile' does not exist"
  671. return 1
  672. fi
  673. # Store profile settings in P_ARR
  674. declare -gn P_ARR="$profile"
  675. # release precedence: user input>profile>env>hardcode
  676. declare -g RELEASE="${USER_RELEASE:=${P_ARR[release]:=$RELEASE}}"
  677. declare -g BUILDDIR="$SRCDIR/$profile/${P_ARR[profile]}-$RELEASE"
  678. declare -g FILESYSTEM="${P_ARR[filesystem]:="squashfs"}"
  679. declare -g THIS_BINDIR="$BINDIR/$profile/${P_ARR[profile]}-$RELEASE"
  680. if [[ "$RELEASE" == "snapshot" ]]; then
  681. declare url_prefix="https://downloads.openwrt.org/snapshots/targets/${P_ARR[target]}"
  682. declare url_filename="openwrt-imagebuilder-${P_ARR[target]//\//-}.Linux-x86_64.tar.xz"
  683. declare img_fname="openwrt-${P_ARR[target]//\//-}-${P_ARR[profile]}-$FILESYSTEM"
  684. else
  685. declare url_prefix="https://downloads.openwrt.org/releases/$RELEASE/targets/${P_ARR[target]}"
  686. declare url_filename="openwrt-imagebuilder-$RELEASE-${P_ARR[target]//\//-}.Linux-x86_64.tar.xz"
  687. declare img_fname="openwrt-$RELEASE-${P_ARR[target]//\//-}-${P_ARR[profile]}-$FILESYSTEM"
  688. fi
  689. declare -g IB_URL="$url_prefix/$url_filename"
  690. declare -g IB_ARCHIVE="$SRCDIR/$url_filename"
  691. declare -g IB_SHA256_URL="$url_prefix/sha256sums"
  692. declare -g IB_SHA256_FILE="$BUILDDIR/sha256sums"
  693. declare -g IB_OUT_SHA256_FILE="$THIS_BINDIR/sha256sums"
  694. declare -g FACTORYIMG="$BUILDDIR/$img_fname-factory.img"
  695. declare -g FACTORYIMGGZ="$BUILDDIR/$img_fname-factory.img.gz"
  696. declare -g FACTORYIMGGZFNAME="${FACTORYIMGGZ##*/}"
  697. declare -g SYSUPGRADEIMG="$BUILDDIR/$img_fname-sysupgrade.img"
  698. declare -g SYSUPGRADEIMGGZ="$BUILDDIR/$img_fname-sysupgrade.img.gz"
  699. declare -g SYSUPGRADEIMGGZFNAME="${SYSUPGRADEIMGGZ##*/}"
  700. declare -g SOURCEFACTORYIMG="$THIS_BINDIR/$img_fname-factory.img"
  701. declare -g SOURCEFACTORYIMGGZ="$THIS_BINDIR/$img_fname-factory.img.gz"
  702. declare -g SOURCESYSUPGRADEIMG="$THIS_BINDIR/targets/$img_fname-sysupgrade.img"
  703. declare -g SOURCESYSUPGRADEIMGGZ="$THIS_BINDIR/targets/$img_fname-sysupgrade.img.gz"
  704. declare -g SOURCESYSUPGRADEIMGGZFNAME="${SOURCESYSUPGRADEIMGGZ##*/}"
  705. declare -g GITWORKTREEDIR="$SRCDIR/$profile/$RELEASE"
  706. declare -g SEED_URL="$url_prefix/config.buildinfo"
  707. declare -g SEED_FILE="$GITWORKTREEDIR/.config"
  708. if (( DEBUG )); then
  709. echo "Profile settings:"
  710. for x in "${!P_ARR[@]}"; do printf "%s=%s\n" "$x" "${P_ARR[$x]}"; done
  711. echo "Build settings:"
  712. cat <<- EOF
  713. ALIAS=$profile
  714. BUILDROOT=$BUILDROOT
  715. BUILDDIR=$BUILDDIR
  716. SRCDIR=$SRCDIR
  717. BINDIR=$BINDIR
  718. GITSRCDIR=$GITSRCDIR
  719. THIS_BINDIR=$THIS_BINDIR
  720. TARGET=${P_ARR[target]}
  721. PROFILE=${P_ARR[profile]}
  722. RELEASE=$RELEASE
  723. FILESYSTEM=$FILESYSTEM
  724. IB_URL=$IB_URL
  725. IB_ARCHIVE=$IB_ARCHIVE
  726. SEED_URL=$SEED_URL
  727. SEED_FILE=$SEED_FILE
  728. IB_SHA256_URL=$IB_SHA256_URL
  729. IB_SHA256_FILE=$IB_SHA256_FILE
  730. IB_OUT_SHA256_FILE=$IB_OUT_SHA256_FILE
  731. FACTORYIMGGZ: $FACTORYIMGGZ
  732. FACTORYIMGGZFNAME: $FACTORYIMGGZFNAME
  733. SYSUPGRADEIMGGZ: $SYSUPGRADEIMGGZ
  734. SYSUPGRADEIMGGZFNAME: $SYSUPGRADEIMGGZFNAME
  735. EOF
  736. fi
  737. (( RESET )) && resetProfile
  738. (( FROM_SOURCE )) && fromSource
  739. # Acquire and verify Image Builder
  740. getImageBuilder &&
  741. getImageBuilderChecksum &&
  742. verify "$IB_ARCHIVE" "$IB_SHA256_FILE" ||
  743. return $?
  744. extractImageBuilder || return $?
  745. addRepos
  746. #copyFiles
  747. [[ -v SSH_BACKUP_PATH ]] && sshBackup
  748. if makeImages && verifyImages; then
  749. [[ -v SSH_UPGRADE_PATH ]] && sshUpgrade
  750. [[ -v FLASH_DEV ]] && flashImage
  751. fi
  752. done
  753. }
  754. main "$@"
  755. exit
  756. # VM setup (for testing)
  757. # sudo sgdisk -N 0 /dev/vda &&
  758. # sudo mkfs.ext4 /dev/vda1
  759. # mkdir ~/mnt
  760. # sudo mount /dev/vda1 ~/mnt
  761. # sudo chown liveuser:liveuser -R ~/mnt