0017-base-files-always-use-staged-sysupgrade.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. From: Matthias Schiffer <mschiffer@universe-factory.net>
  2. Date: Sat, 22 Apr 2017 00:54:50 +0200
  3. Subject: base-files: always use staged sysupgrade
  4. Support for the -d and -p options is dropped; it may be added again at some
  5. point by adding these flags to the ubus sysupgrade call.
  6. A downside of this is that we get a lot less information about the progress
  7. of the upgrade: as soon as the actual upgrade starts, all shell sessions
  8. are killed to allow unmounting the root filesystem.
  9. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
  10. diff --git a/package/base-files/files/lib/upgrade/common.sh b/package/base-files/files/lib/upgrade/common.sh
  11. index e3519ca2cb496ff0835a9ef87da7faf217a07964..17248c2b1decd6f92558fb89601238b55fd0f0d6 100644
  12. --- a/package/base-files/files/lib/upgrade/common.sh
  13. +++ b/package/base-files/files/lib/upgrade/common.sh
  14. @@ -56,7 +56,6 @@ run_ramfs() { # <command> [...]
  15. /bin/rm /usr/bin/basename /bin/kill /bin/chmod /usr/bin/find \
  16. /bin/mknod
  17. - install_bin /bin/uclient-fetch /bin/wget
  18. install_bin /sbin/mtd
  19. install_bin /sbin/mount_root
  20. install_bin /sbin/snapshot
  21. @@ -96,51 +95,37 @@ run_ramfs() { # <command> [...]
  22. exec /bin/busybox ash -c "$*"
  23. }
  24. -kill_remaining() { # [ <signal> ]
  25. +kill_remaining() { # [ <signal> [ <loop> ] ]
  26. local sig="${1:-TERM}"
  27. + local loop="${2:-0}"
  28. + local run=true
  29. + local stat
  30. +
  31. echo -n "Sending $sig to remaining processes ... "
  32. - local my_pid=$$
  33. - local my_ppid=$(cut -d' ' -f4 /proc/$my_pid/stat)
  34. - local my_ppisupgraded=
  35. - grep -q upgraded /proc/$my_ppid/cmdline >/dev/null && {
  36. - local my_ppisupgraded=1
  37. - }
  38. -
  39. - local stat
  40. - for stat in /proc/[0-9]*/stat; do
  41. - [ -f "$stat" ] || continue
  42. -
  43. - local pid name state ppid rest
  44. - read pid name state ppid rest < $stat
  45. - name="${name#(}"; name="${name%)}"
  46. -
  47. - local cmdline
  48. - read cmdline < /proc/$pid/cmdline
  49. -
  50. - # Skip kernel threads
  51. - [ -n "$cmdline" ] || continue
  52. -
  53. - if [ $$ -eq 1 ] || [ $my_ppid -eq 1 ] && [ -n "$my_ppisupgraded" ]; then
  54. - # Running as init process, kill everything except me
  55. - if [ $pid -ne $$ ] && [ $pid -ne $my_ppid ]; then
  56. - echo -n "$name "
  57. - kill -$sig $pid 2>/dev/null
  58. - fi
  59. - else
  60. - case "$name" in
  61. - # Skip essential services
  62. - *procd*|*ash*|*init*|*watchdog*|*ssh*|*dropbear*|*telnet*|*login*|*hostapd*|*wpa_supplicant*|*nas*|*relayd*) : ;;
  63. -
  64. - # Killable process
  65. - *)
  66. - if [ $pid -ne $$ ] && [ $ppid -ne $$ ]; then
  67. - echo -n "$name "
  68. - kill -$sig $pid 2>/dev/null
  69. - fi
  70. - ;;
  71. - esac
  72. - fi
  73. + while $run; do
  74. + run=false
  75. + for stat in /proc/[0-9]*/stat; do
  76. + [ -f "$stat" ] || continue
  77. +
  78. + local pid name state ppid rest
  79. + read pid name state ppid rest < $stat
  80. + name="${name#(}"; name="${name%)}"
  81. +
  82. + # Skip PID1, ourself and our children
  83. + [ $pid -ne 1 -a $pid -ne $$ -a $ppid -ne $$ ] || continue
  84. +
  85. + local cmdline
  86. + read cmdline < /proc/$pid/cmdline
  87. +
  88. + # Skip kernel threads
  89. + [ -n "$cmdline" ] || continue
  90. +
  91. + echo -n "$name "
  92. + kill -$sig $pid 2>/dev/null
  93. +
  94. + [ $loop -eq 1 ] && run=true
  95. + done
  96. done
  97. echo ""
  98. }
  99. @@ -175,28 +160,31 @@ v() {
  100. [ "$VERBOSE" -ge 1 ] && echo "$@"
  101. }
  102. +json_string() {
  103. + local v="$1"
  104. + v="${v//\\/\\\\}"
  105. + v="${v//\"/\\\"}"
  106. + echo "\"$v\""
  107. +}
  108. +
  109. rootfs_type() {
  110. /bin/mount | awk '($3 ~ /^\/$/) && ($5 !~ /rootfs/) { print $5 }'
  111. }
  112. get_image() { # <source> [ <command> ]
  113. local from="$1"
  114. - local conc="$2"
  115. - local cmd
  116. -
  117. - case "$from" in
  118. - http://*|ftp://*) cmd="wget -O- -q";;
  119. - *) cmd="cat";;
  120. - esac
  121. - if [ -z "$conc" ]; then
  122. - local magic="$(eval $cmd \"$from\" 2>/dev/null | dd bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
  123. + local cat="$2"
  124. +
  125. + if [ -z "$cat" ]; then
  126. + local magic="$(dd if="$from" bs=2 count=1 2>/dev/null | hexdump -n 2 -e '1/1 "%02x"')"
  127. case "$magic" in
  128. - 1f8b) conc="zcat";;
  129. - 425a) conc="bzcat";;
  130. + 1f8b) cat="zcat";;
  131. + 425a) cat="bzcat";;
  132. + *) cat="cat";;
  133. esac
  134. fi
  135. - eval "$cmd \"$from\" 2>/dev/null ${conc:+| $conc}"
  136. + $cat "$from" 2>/dev/null
  137. }
  138. get_magic_word() {
  139. @@ -320,12 +308,14 @@ default_do_upgrade() {
  140. fi
  141. }
  142. -do_upgrade() {
  143. +do_upgrade_stage2() {
  144. v "Performing system upgrade..."
  145. - if type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
  146. - platform_do_upgrade "$ARGV"
  147. + if [ -n "$do_upgrade" ]; then
  148. + $do_upgrade "$IMAGE"
  149. + elif type 'platform_do_upgrade' >/dev/null 2>/dev/null; then
  150. + platform_do_upgrade "$IMAGE"
  151. else
  152. - default_do_upgrade "$ARGV"
  153. + default_do_upgrade "$IMAGE"
  154. fi
  155. if [ "$SAVE_CONFIG" -eq 1 ] && type 'platform_copy_config' >/dev/null 2>/dev/null; then
  156. @@ -333,12 +323,11 @@ do_upgrade() {
  157. fi
  158. v "Upgrade completed"
  159. - [ -n "$DELAY" ] && sleep "$DELAY"
  160. - ask_bool 1 "Reboot" && {
  161. - v "Rebooting system..."
  162. - umount -a
  163. - reboot -f
  164. - sleep 5
  165. - echo b 2>/dev/null >/proc/sysrq-trigger
  166. - }
  167. + sleep 1
  168. +
  169. + v "Rebooting system..."
  170. + umount -a
  171. + reboot -f
  172. + sleep 5
  173. + echo b 2>/dev/null >/proc/sysrq-trigger
  174. }
  175. diff --git a/package/base-files/files/lib/upgrade/nand.sh b/package/base-files/files/lib/upgrade/nand.sh
  176. index 6bd2005344c081df20e5a330a69e49e37225c39f..1e69c8f9657b39adf2a2c33bd9bac9303bcbc3d7 100644
  177. --- a/package/base-files/files/lib/upgrade/nand.sh
  178. +++ b/package/base-files/files/lib/upgrade/nand.sh
  179. @@ -283,7 +283,16 @@ nand_upgrade_tar() {
  180. }
  181. # Recognize type of passed file and start the upgrade process
  182. -nand_do_upgrade_stage2() {
  183. +nand_do_upgrade() {
  184. + if [ -n "$IS_PRE_UPGRADE" ]; then
  185. + # Previously, nand_do_upgrade was called from the platform_pre_upgrade
  186. + # hook; this piece of code handles scripts that haven't been
  187. + # updated. All scripts should gradually move to call nand_do_upgrade
  188. + # from platform_do_upgrade instead.
  189. + export do_upgrade=nand_do_upgrade
  190. + return
  191. + fi
  192. +
  193. local file_type=$(identify $1)
  194. if type 'platform_nand_pre_upgrade' >/dev/null 2>/dev/null; then
  195. @@ -299,45 +308,6 @@ nand_do_upgrade_stage2() {
  196. esac
  197. }
  198. -nand_upgrade_stage2() {
  199. - [ $1 = "nand" ] && {
  200. - [ -f "$2" ] && {
  201. - touch /tmp/sysupgrade
  202. -
  203. - killall -9 telnetd
  204. - killall -9 dropbear
  205. - killall -9 ash
  206. -
  207. - kill_remaining TERM
  208. - sleep 3
  209. - kill_remaining KILL
  210. -
  211. - sleep 1
  212. -
  213. - if [ -n "$(rootfs_type)" ]; then
  214. - v "Switching to ramdisk..."
  215. - run_ramfs ". /lib/functions.sh; include /lib/upgrade; nand_do_upgrade_stage2 $2"
  216. - else
  217. - nand_do_upgrade_stage2 $2
  218. - fi
  219. - return 0
  220. - }
  221. - echo "Nand upgrade failed"
  222. - exit 1
  223. - }
  224. -}
  225. -
  226. -nand_upgrade_stage1() {
  227. - [ -f /tmp/sysupgrade-nand-path ] && {
  228. - path="$(cat /tmp/sysupgrade-nand-path)"
  229. - [ "$SAVE_CONFIG" != 1 -a -f "$CONF_TAR" ] &&
  230. - rm $CONF_TAR
  231. -
  232. - ubus call system nandupgrade "{\"prefix\": \"$RAM_ROOT\", \"path\": \"$path\" }"
  233. - exit 0
  234. - }
  235. -}
  236. -
  237. # Check if passed file is a valid one for NAND sysupgrade. Currently it accepts
  238. # 3 types of files:
  239. # 1) UBI - should contain an ubinized image, header is checked for the proper
  240. @@ -364,13 +334,3 @@ nand_do_platform_check() {
  241. return 0
  242. }
  243. -
  244. -# Start NAND upgrade process
  245. -#
  246. -# $(1): file to be used for upgrade
  247. -nand_do_upgrade() {
  248. - echo -n $1 > /tmp/sysupgrade-nand-path
  249. - install_bin /sbin/upgraded
  250. - ln -s "$RAM_ROOT"/sbin/upgraded /tmp/upgraded
  251. - nand_upgrade_stage1
  252. -}
  253. diff --git a/package/base-files/files/lib/upgrade/stage2 b/package/base-files/files/lib/upgrade/stage2
  254. new file mode 100755
  255. index 0000000000000000000000000000000000000000..4e2aa3a23c3bab07a795762a30a4d4f701081934
  256. --- /dev/null
  257. +++ b/package/base-files/files/lib/upgrade/stage2
  258. @@ -0,0 +1,50 @@
  259. +#!/bin/sh
  260. +
  261. +. /lib/functions.sh
  262. +. /lib/functions/system.sh
  263. +
  264. +export IMAGE="$1"
  265. +COMMAND="$2"
  266. +
  267. +export ARGV="$IMAGE"
  268. +export ARGC=1
  269. +
  270. +export SAVE_CONFIG=1
  271. +export SAVE_PARTITIONS=1
  272. +
  273. +export INTERACTIVE=0
  274. +export VERBOSE=1
  275. +export CONFFILES=/tmp/sysupgrade.conffiles
  276. +export CONF_TAR=/tmp/sysupgrade.tgz
  277. +
  278. +
  279. +[ -f "$CONF_TAR" ] || export SAVE_CONFIG=0
  280. +[ -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap ] && export SAVE_PARTITIONS=0
  281. +
  282. +include /lib/upgrade
  283. +
  284. +
  285. +killall -9 telnetd
  286. +killall -9 dropbear
  287. +killall -9 ash
  288. +
  289. +kill_remaining TERM
  290. +sleep 3
  291. +kill_remaining KILL 1
  292. +
  293. +sleep 1
  294. +
  295. +
  296. +if [ -n "$IMAGE" ] && type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
  297. + IS_PRE_UPGRADE=1 platform_pre_upgrade "$IMAGE"
  298. +
  299. + # Needs to be unset again because of busybox weirdness ...
  300. + IS_PRE_UPGRADE=
  301. +fi
  302. +
  303. +if [ -n "$(rootfs_type)" ]; then
  304. + echo "Switching to ramdisk..."
  305. + run_ramfs "$COMMAND"
  306. +else
  307. + exec /bin/busybox ash -c "$COMMAND"
  308. +fi
  309. diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade
  310. index c095ca81c50c71021af2dc04a561ac22f6b7442b..2d67371ef74b4b970076a069e97f4fd6a1e0bc95 100755
  311. --- a/package/base-files/files/sbin/sysupgrade
  312. +++ b/package/base-files/files/sbin/sysupgrade
  313. @@ -1,4 +1,7 @@
  314. #!/bin/sh
  315. +
  316. +[ "$1" = "nand" ] && exec /lib/upgrade/stage2 "$2" "$3"
  317. +
  318. . /lib/functions.sh
  319. . /lib/functions/system.sh
  320. @@ -11,7 +14,6 @@ export VERBOSE=1
  321. export SAVE_CONFIG=1
  322. export SAVE_OVERLAY=0
  323. export SAVE_PARTITIONS=1
  324. -export DELAY=
  325. export CONF_IMAGE=
  326. export CONF_BACKUP_LIST=0
  327. export CONF_BACKUP=
  328. @@ -25,7 +27,6 @@ export TEST=0
  329. while [ -n "$1" ]; do
  330. case "$1" in
  331. -i) export INTERACTIVE=1;;
  332. - -d) export DELAY="$2"; shift;;
  333. -v) export VERBOSE="$(($VERBOSE + 1))";;
  334. -q) export VERBOSE="$(($VERBOSE - 1))";;
  335. -n) export SAVE_CONFIG=0;;
  336. @@ -50,10 +51,9 @@ done
  337. export CONFFILES=/tmp/sysupgrade.conffiles
  338. export CONF_TAR=/tmp/sysupgrade.tgz
  339. -export ARGV="$*"
  340. -export ARGC="$#"
  341. +IMAGE="$1"
  342. -[ -z "$ARGV" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && {
  343. +[ -z "$IMAGE" -a -z "$NEED_IMAGE" -o $HELP -gt 0 ] && {
  344. cat <<EOF
  345. Usage: $0 [<upgrade-option>...] <image file or URL>
  346. $0 [-q] [-i] <backup-command> <file>
  347. @@ -90,7 +90,7 @@ EOF
  348. exit 1
  349. }
  350. -[ -n "$ARGV" -a -n "$NEED_IMAGE" ] && {
  351. +[ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && {
  352. cat <<-EOF
  353. -b|--create-backup and -r|--restore-backup do not perform a firmware upgrade.
  354. Do not specify both -b|-r and a firmware image.
  355. @@ -136,14 +136,13 @@ sysupgrade_pre_upgrade="fwtool_pre_upgrade"
  356. include /lib/upgrade
  357. -[ "$1" = "nand" ] && nand_upgrade_stage2 $@
  358. -
  359. do_save_conffiles() {
  360. local conf_tar="${1:-$CONF_TAR}"
  361. [ -z "$(rootfs_type)" ] && {
  362. echo "Cannot save config while running from ramdisk."
  363. ask_bool 0 "Abort" && exit
  364. + rm -f "$conf_tar"
  365. return 0
  366. }
  367. run_hooks "$CONFFILES" $sysupgrade_init_conffiles
  368. @@ -184,8 +183,33 @@ type platform_check_image >/dev/null 2>/dev/null || {
  369. exit 1
  370. }
  371. +case "$IMAGE" in
  372. + http://*)
  373. + wget -O/tmp/sysupgrade.img "$IMAGE"
  374. + IMAGE=/tmp/sysupgrade.img
  375. + ;;
  376. +esac
  377. +
  378. +IMAGE="$(readlink -f "$IMAGE")"
  379. +
  380. +case "$IMAGE" in
  381. + '')
  382. + echo "Image file not found."
  383. + exit 1
  384. + ;;
  385. + /tmp/*) ;;
  386. + *)
  387. + v "Image not in /tmp, copying..."
  388. + cp -f "$IMAGE" /tmp/sysupgrade.img
  389. + IMAGE=/tmp/sysupgrade.img
  390. + ;;
  391. +esac
  392. +
  393. +export ARGV="$IMAGE"
  394. +export ARGC=1
  395. +
  396. for check in $sysupgrade_image_check; do
  397. - ( eval "$check \"\$ARGV\"" ) || {
  398. + ( $check "$IMAGE" ) || {
  399. if [ $FORCE -eq 1 ]; then
  400. echo "Image check '$check' failed but --force given - will update anyway!"
  401. break
  402. @@ -211,6 +235,7 @@ elif ask_bool $SAVE_CONFIG "Keep config files over reflash"; then
  403. [ $TEST -eq 1 ] || do_save_conffiles
  404. export SAVE_CONFIG=1
  405. else
  406. + [ $TEST -eq 1 ] || rm -f "$CONF_TAR"
  407. export SAVE_CONFIG=0
  408. fi
  409. @@ -218,28 +243,18 @@ if [ $TEST -eq 1 ]; then
  410. exit 0
  411. fi
  412. -run_hooks "" $sysupgrade_pre_upgrade
  413. -
  414. -# Some platforms/devices may want different sysupgrade process, e.g. without
  415. -# killing processes yet or calling ubus system upgrade method.
  416. -# This is needed e.g. on NAND devices where we just want to trigger stage1 at
  417. -# this point.
  418. -if type 'platform_pre_upgrade' >/dev/null 2>/dev/null; then
  419. - platform_pre_upgrade "$ARGV"
  420. +if [ $SAVE_PARTITIONS -eq 0 ]; then
  421. + touch /tmp/sysupgrade.always.overwrite.bootdisk.partmap
  422. +else
  423. + rm -f /tmp/sysupgrade.always.overwrite.bootdisk.partmap
  424. fi
  425. -ubus call system upgrade
  426. -touch /tmp/sysupgrade
  427. -
  428. -if [ ! -f /tmp/failsafe ] ; then
  429. - kill_remaining TERM
  430. - sleep 3
  431. - kill_remaining KILL
  432. -fi
  433. +run_hooks "" $sysupgrade_pre_upgrade
  434. -if [ -n "$(rootfs_type)" ]; then
  435. - v "Switching to ramdisk..."
  436. - run_ramfs '. /lib/functions.sh; include /lib/upgrade; do_upgrade'
  437. -else
  438. - do_upgrade
  439. -fi
  440. +install_bin /sbin/upgraded
  441. +v "Commencing upgrade. All shell sessions will be closed now."
  442. +ubus call system sysupgrade "{
  443. + \"prefix\": \"$RAM_ROOT\",
  444. + \"path\": $(json_string "$IMAGE"),
  445. + \"command\": \". /lib/functions.sh; include /lib/upgrade; do_upgrade_stage2\"
  446. +}"