Advertisement
Guest User

patched rpi-update

a guest
Jun 2nd, 2016
1,287
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 10.78 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. set -o nounset
  4. set -o errexit
  5.  
  6. REPO_URI=${REPO_URI:-"https://github.com/Hexxeh/rpi-firmware"}
  7.  
  8. UPDATE_SELF=0
  9. UPDATE_URI="https://raw.githubusercontent.com/Hexxeh/rpi-update/master/rpi-update"
  10.  
  11. if [[ ${BOOT_PATH:-"unset"} == "unset" && ${ROOT_PATH:-"unset"} != "unset" ]] ||
  12. [[ ${BOOT_PATH:-"unset"} != "unset" && ${ROOT_PATH:-"unset"} == "unset" ]]; then
  13.     echo " *** You need to specify both ROOT_PATH and BOOT_PATH, or neither"
  14.     exit 1
  15. fi
  16.  
  17. if [[ ${BOOT_PATH:-"unset"} == "unset" ]]; then
  18.     NOOBS_CHECK=${NOOBS_CHECK:-1}
  19. else
  20.     NOOBS_CHECK=${NOOBS_CHECK:-0}
  21. fi
  22.  
  23. BRANCH=${BRANCH:-"master"}
  24. ROOT_PATH=${ROOT_PATH:-"/"}
  25. BOOT_PATH=${BOOT_PATH:-"/boot"}
  26. WORK_PATH=${WORK_PATH:-"${ROOT_PATH}/root"}
  27. SKIP_KERNEL=${SKIP_KERNEL:-0}
  28. SKIP_SDK=${SKIP_SDK:-0}
  29. SKIP_REPODELETE=${SKIP_REPODELETE:-0}
  30. SKIP_BACKUP=${SKIP_BACKUP:-0}
  31. SKIP_DOWNLOAD=${SKIP_DOWNLOAD:-0}
  32. SKIP_WARNING=${SKIP_WARNING:-0}
  33. WANT_SYMVERS=${WANT_SYMVERS:-0}
  34. PRUNE_MODULES=${PRUNE_MODULES:-0}
  35. RPI_UPDATE_UNSUPPORTED=${RPI_UPDATE_UNSUPPORTED:-0}
  36. JUST_CHECK=${JUST_CHECK:-0}
  37. FW_REPO="${REPO_URI}.git"
  38. FW_REPOLOCAL=${FW_REPOLOCAL:-"${WORK_PATH}/.rpi-firmware"}
  39. FW_PATH="${BOOT_PATH}"
  40. FW_MODPATH="${ROOT_PATH}/lib/modules"
  41. FW_REV=${1:-""}
  42. FW_REVFILE="${FW_PATH}/.firmware_revision"
  43. [ "${RPI_UPDATE_UNSUPPORTED}" -ne 0 ] && echo -e "You appear to be trying to update firmware on an incompatible distribution. To force update, run the following:\nsudo -E RPI_UPDATE_UNSUPPORTED=0 rpi-update" && exit 1
  44.  
  45. function update_self() {
  46.     echo " *** Performing self-update"
  47.     _tempFileName="$0.tmp"
  48.  
  49.     if ! curl -k -Ls --output "${_tempFileName}" "${UPDATE_URI}"; then
  50.         echo " !!! Failed to download update for rpi-update!"
  51.         echo " !!! Make sure you have ca-certificates installed and that the time is set correctly"
  52.         exit 1
  53.     fi
  54.  
  55.     OCTAL_MODE=$(stat -c '%a' "$0")
  56.     if ! chmod ${OCTAL_MODE} "${_tempFileName}" ; then
  57.         echo " !!! Failed: Error while trying to set mode on ${_tempFileName}"
  58.         exit 1
  59.     fi
  60.  
  61.     cat > "${WORK_PATH}/.updateScript.sh" << EOF
  62.     if mv "${_tempFileName}" "$0"; then
  63.         rm -- "\$0"
  64.         exec env UPDATE_SELF=0 /bin/bash "$0" "${FW_REV}"
  65.     else
  66.         echo " !!! Failed!"
  67.     fi
  68. EOF
  69.  
  70.     echo " *** Relaunching after update"
  71.     exec /bin/bash "${WORK_PATH}/.updateScript.sh"
  72. }
  73.  
  74. function update_modules {
  75.     if [[ ${SKIP_KERNEL} -eq 0 ]]; then
  76.         echo " *** Updating kernel modules"
  77.         find "${FW_REPOLOCAL}/modules" -mindepth 1 -maxdepth 1 -type d | while read DIR; do
  78.             BASEDIR=$(basename "${DIR}")
  79.             rm -rf "${FW_MODPATH}/${BASEDIR}/kernel"
  80.         done
  81.  
  82.         if [[ ${PRUNE_MODULES} -ne 0 ]]; then
  83.             find "${FW_MODPATH}" -mindepth 1 -maxdepth 1 -type d | while read DIR; do
  84.                 COUNT=$(find ${DIR} -type f ! \( -name '*.ko' -o -name 'modules.*' \) | wc -l);
  85.                 if [[ ${COUNT} -eq 0 ]]; then
  86.                     echo "Pruning ${DIR}"
  87.                     rm -rf ${DIR}
  88.                 else
  89.                     echo "Keeping ${DIR}"
  90.                 fi
  91.             done
  92.         fi
  93.  
  94.         cp -R "${FW_REPOLOCAL}/modules/"* "${FW_MODPATH}/"
  95.         find "${FW_REPOLOCAL}/modules" -mindepth 1 -maxdepth 1 -type d | while read DIR; do
  96.             BASEDIR=$(basename "${DIR}")
  97.             echo " *** depmod ${BASEDIR}"
  98.             depmod -b "${ROOT_PATH}" -a "${BASEDIR}"
  99.         done
  100.     else
  101.         echo " *** As requested, not updating kernel modules"
  102.     fi
  103. }
  104.  
  105. function update_vc_libs {
  106.     echo " *** Updating VideoCore libraries"
  107.  
  108.     if [[ -e ${ROOT_PATH}/bin/sh ]]; then
  109.         ELFOUTPUT=$(readelf -a "${ROOT_PATH}/bin/sh"; readelf -h "${ROOT_PATH}/bin/sh")
  110.     else
  111.         ELFOUTPUT="VFP_args"
  112.     fi
  113.     if [[ "${ELFOUTPUT}" != "${ELFOUTPUT/VFP_args/}" || \
  114.             "${ELFOUTPUT}" != "${ELFOUTPUT/hard-float/}" ]]; then
  115.         echo " *** Using HardFP libraries"
  116.         cp -R "${FW_REPOLOCAL}/vc/hardfp/"* "${ROOT_PATH}/"
  117.     else
  118.         echo " *** Using SoftFP libraries"
  119.         cp -R "${FW_REPOLOCAL}/vc/softfp/"* "${ROOT_PATH}/"
  120.     fi
  121. }
  122.  
  123. function update_sdk {
  124.     if [[ ${SKIP_SDK} -eq 0 ]]; then
  125.         echo " *** Updating SDK"
  126.         cp -R "${FW_REPOLOCAL}/vc/sdk/"* "${ROOT_PATH}/"
  127.     else
  128.         echo " *** As requested, not updating SDK"
  129.     fi
  130. }
  131.  
  132. function show_notice {
  133.     local NOTICE=`curl -k -Lfs https://raw.githubusercontent.com/hexxeh/rpi-firmware/${FW_REV}/NOTICE.md`
  134.     if [ -z "$NOTICE" ]; then
  135.         return
  136.     fi
  137.     echo "$NOTICE"
  138.     if ! echo "$NOTICE" | grep -q WARNING; then
  139.         return
  140.     fi
  141.     if [[ ${SKIP_WARNING} -ne 0 ]]; then
  142.         return
  143.     fi
  144.     read -p "Would you like to proceed? (y/N)" -n 1 -r -s
  145.     echo ""
  146.     if ! [[ $REPLY =~ ^[Yy]$ ]]; then
  147.         exit 1;
  148.     fi
  149. }
  150.  
  151. function update_firmware {
  152.     echo " *** Updating firmware"
  153.     rm -rf "${FW_PATH}/"*.elf
  154.     rm -rf "${FW_PATH}/"bootcode.bin
  155.     cp "${FW_REPOLOCAL}/"*.elf "${FW_PATH}/"
  156.     cp "${FW_REPOLOCAL}/"*.bin "${FW_PATH}/"
  157.     cp "${FW_REPOLOCAL}/"*.dat "${FW_PATH}/"
  158.     if [[ ${SKIP_KERNEL} -eq 0 ]]; then
  159.         cp "${FW_REPOLOCAL}/"*.img "${FW_PATH}/"
  160.         if [[ -n $(shopt -s nullglob; echo "${FW_REPOLOCAL}/"*.dtb*) ]]; then
  161.             cp "${FW_REPOLOCAL}/"*.dtb* "${FW_PATH}/"
  162.         fi
  163.         if [[ -n $(shopt -s nullglob; echo "${FW_REPOLOCAL}/overlays/"*.dtb*) ]]; then
  164.             mkdir -p "${FW_PATH}/overlays"
  165.             cp "${FW_REPOLOCAL}/overlays/"*.dtb* "${FW_PATH}/overlays/"
  166.             if [[ -f "${FW_REPOLOCAL}/overlays/README" ]]; then
  167.                 cp "${FW_REPOLOCAL}/overlays/README" "${FW_PATH}/overlays/"
  168.             fi
  169.         fi
  170.     else
  171.         echo " *** As requested, not updating kernel"
  172.     fi
  173.     if [[ ${WANT_SYMVERS} -ne 0 ]]; then
  174.         if [[ -f "${FW_REPOLOCAL}/Module.symvers" ]]; then
  175.             cp "${FW_REPOLOCAL}/Module.symvers" "${FW_PATH}/"
  176.         fi
  177.         if [[ -f "${FW_REPOLOCAL}/git_hash" ]]; then
  178.             cp "${FW_REPOLOCAL}/git_hash" "${FW_PATH}/"
  179.         fi
  180.     fi
  181. }
  182.  
  183. function finalise {
  184.     if [[ -f "${FW_PATH}/arm192_start.elf" ]]; then
  185.         echo " *** Setting 192M ARM split"
  186.         cp "${FW_PATH}/arm192_start.elf" "${FW_PATH}/start.elf"
  187.     fi
  188.     if [[ -e ${ROOT_PATH}/etc ]]; then
  189.         echo " *** Running ldconfig"
  190.         ldconfig -r "${ROOT_PATH}"
  191.     fi
  192.     echo " *** Storing current firmware revision"
  193.     echo "${FW_REV}" > "${FW_REVFILE}"
  194. }
  195.  
  196. function do_backup {
  197.     if [[ ${SKIP_BACKUP} -eq 0 ]]; then
  198.         echo " *** Backing up files (this will take a few minutes)"
  199.         if [[ -d "${FW_PATH}.bak" ]]; then
  200.             echo " *** Remove old firmware backup"
  201.             rm -rf "${FW_PATH}.bak"
  202.         fi
  203.         echo " *** Backing up firmware"
  204.         cp -a "${FW_PATH}" "${FW_PATH}.bak"
  205.         if [[ ${SKIP_KERNEL} -eq 0 ]]; then
  206.             if [[ -d "${FW_MODPATH}.bak" ]]; then
  207.                 echo " *** Remove old modules backup"
  208.                 rm -rf "${FW_MODPATH}.bak"
  209.             fi
  210.             echo " *** Backing up modules $(uname -r)"
  211.             if [[ -d "${FW_MODPATH}/$(uname -r)" ]]; then
  212.                 mkdir -p "${FW_MODPATH}.bak" && cp -a "${FW_MODPATH}/$(uname -r)" "${FW_MODPATH}.bak"
  213.             fi
  214.         fi
  215.     fi
  216. }
  217.  
  218. function do_update {
  219.     show_notice
  220.     download_rev
  221.     if [[ -f "${FW_REPOLOCAL}/pre-install" ]]; then
  222.         echo " *** Running pre-install script"
  223.         source "${FW_REPOLOCAL}/pre-install"
  224.     fi
  225.     update_firmware
  226.     update_modules
  227.     update_vc_libs
  228.     update_sdk
  229.     finalise
  230.     if [[ -f "${FW_REPOLOCAL}/post-install" ]]; then
  231.         echo " *** Running post-install script"
  232.         source "${FW_REPOLOCAL}/post-install"
  233.     fi
  234.     remove_rev
  235.     echo " *** Syncing changes to disk"
  236.     sync
  237.     echo " *** If no errors appeared, your firmware was successfully updated to ${FW_REV}"
  238.     if [[ "${ROOT_PATH}" == "/" ]]; then
  239.         echo " *** A reboot is needed to activate the new firmware"
  240.     fi
  241. }
  242.  
  243. function download_rev {
  244.     if [[ ${SKIP_DOWNLOAD} -eq 0 ]]; then
  245.         echo " *** Downloading specific firmware revision (this will take a few minutes)"
  246.         rm -rf "${FW_REPOLOCAL}"
  247.         mkdir -p "${FW_REPOLOCAL}"
  248.         curl -k -L "${REPO_URI}/tarball/${FW_REV}" | tar xzf - -C "${FW_REPOLOCAL}" --strip-components=1
  249.     fi
  250. }
  251.  
  252. function remove_rev {
  253.     echo " *** Deleting downloaded files"
  254.     if [[ ${SKIP_REPODELETE} -eq 0 ]]; then
  255.         rm -rf "${FW_REPOLOCAL}"
  256.     fi
  257. }
  258.  
  259. function noobs_fix {
  260.     echo " !!! $BOOT_PATH appears to contain NOOBS files"
  261.     echo "     This may occur if fstab contains incorrect entries."
  262.     echo "     rpi-update will attempt to correct fstab."
  263.     read -p "Would you like to proceed? (y/N)" -n 1 -r -s
  264.     echo
  265.     if ! [[ $REPLY =~ ^[Yy]$ ]]; then
  266.         exit 1;
  267.     fi
  268.  
  269.     if ! grep -qE "/dev/mmcblk0p1\s+/boot" ${ROOT_PATH}/etc/fstab; then
  270.         echo "Unexpected fstab entry"
  271.         exit 1
  272.     fi
  273.  
  274.     local ROOTNUM=`cat /proc/cmdline | sed -n 's|.*root=/dev/mmcblk0p\([0-9]*\).*|\1|p'`
  275.     if [ ! "$ROOTNUM" ];then
  276.         echo "Could not determine root partition."
  277.         exit 1
  278.     fi
  279.     local BOOT_DEV="/dev/mmcblk0p$((ROOTNUM-1))"
  280.     local ROOT_DEV="/dev/mmcblk0p${ROOTNUM}"
  281.     sed ${ROOT_PATH}/etc/fstab -e "s|^.*[^#].* / |${ROOT_DEV}  / |;s|^.*[^#].* /boot |${BOOT_DEV}  /boot |"
  282.     read -p "Does this look correct?  (y/N)" -n 1 -r -s
  283.     echo
  284.     if ! [[ $REPLY =~ ^[Yy]$ ]]; then
  285.         exit 1;
  286.     fi
  287.     sed ${ROOT_PATH}/etc/fstab -i -e "s|^.*[^#].* / |${ROOT_DEV}  / |;s|^.*[^#].* /boot |${BOOT_DEV}  /boot |"
  288.  
  289.     umount /boot
  290.     if [ $? -ne 0 ]; then
  291.         echo "Failed to umount /boot. Remount manually and try again."
  292.         exit 1
  293.     else
  294.         mount /boot
  295.     fi
  296.  
  297. }
  298.  
  299. if [[ ${EUID} -ne 0 ]]; then
  300.     echo " !!! This tool must be run as root"
  301.     exit 1
  302. fi
  303.  
  304. echo " *** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS and Dom"
  305.  
  306. if [[ ! -d ${WORK_PATH} ]]; then
  307.     echo " !!! ${WORK_PATH} doesn't exist - creating"
  308.     mkdir -p ${WORK_PATH}
  309. fi
  310.  
  311. if [[ ${UPDATE_SELF} -ne 0 ]]; then
  312.     update_self
  313. fi
  314.  
  315. if [[ ! -d "${FW_PATH}" ]]; then
  316.     echo " !!! ${FW_PATH} doesn't exist - creating"
  317.     mkdir -p ${FW_PATH}
  318. fi
  319.  
  320. if [[ ${SKIP_KERNEL} -eq 0 ]] && [[ ! -d "${FW_MODPATH}" ]]; then
  321.     echo " !!! ${FW_MODPATH} doesn't exist - creating"
  322.     mkdir -p ${FW_MODPATH}
  323. fi
  324.  
  325. if [[ ${NOOBS_CHECK} -eq 1 ]] && [[ -f ${BOOT_PATH}/recovery.elf ]]; then
  326.     noobs_fix
  327. fi
  328.  
  329. command -v readelf >/dev/null 2>&1 || {
  330.     echo " !!! This tool requires you have readelf installed, please install it first"
  331.     echo "     In Debian, try: sudo apt-get install binutils"
  332.     echo "     In Arch, try: pacman -S binutils"
  333.     exit 1
  334. }
  335.  
  336. # ask github for latest version hash
  337. REPO_API=${REPO_URI/github.com/api.github.com\/repos}/git/refs/heads/${BRANCH}
  338. GITREV=$(curl -k -s ${REPO_API} | awk '{ if ($1 == "\"sha\":") { print substr($2, 2, 40) } }')
  339. FW_REV=${FW_REV:-${GITREV}}
  340.  
  341. if [[ "${FW_REV}" == "" ]]; then
  342.     echo " *** No hash received from github: ${REPO_API}"
  343.     # run again with errors not suppressed
  344.     curl -k ${REPO_API}
  345.     exit 1
  346. fi
  347.  
  348. if [[ ! -f "${FW_REVFILE}" ]]; then
  349.     echo " *** We're running for the first time"
  350.     if [[ ${JUST_CHECK} -ne 0 ]]; then
  351.         exit 2
  352.     fi
  353.     do_backup
  354. else
  355.     if [[ $(cat "${FW_REVFILE}") == "${FW_REV}" ]]; then
  356.         echo " *** Your firmware is already up to date"
  357.         exit 0
  358.     fi
  359.     if [[ ${JUST_CHECK} -ne 0 ]]; then
  360.         echo " *** Firmware update required. New commits available:"
  361.         DIFF_API=${REPO_URI/github.com/api.github.com\/repos}/compare/$(cat "${FW_REVFILE}")...${BRANCH}
  362.         SEPARATOR="======================================================"
  363.         curl -k -Ls ${DIFF_API} | awk -v SEPARATOR="${SEPARATOR}" -F\" ' { if ($2 == "commits") {commits=1} if (commits && $2 == "message") {print SEPARATOR "\nCommit: " $4} }' | sed 's/\\n\\n/\nCommit:\ /g'
  364.         exit 2
  365.     fi
  366. fi
  367.  
  368. do_update
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement