Skip to content

Instantly share code, notes, and snippets.

@dimme
Last active December 26, 2015 22:29
Show Gist options
  • Save dimme/7223634 to your computer and use it in GitHub Desktop.
Save dimme/7223634 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -o nounset
set -o errexit
REPO_URI=${REPO_URI:-"https://github.com/Hexxeh/rpi-firmware"}
UPDATE_SELF=${UPDATE_SELF:-1}
UPDATE_URI="https://gist.github.com/Dimme/7223634/raw/29c43a079ac472cb4f3f4912bbf13abb8649a85c/gistfile1.txt"
if [[ ${BOOT_PATH:-"unset"} == "unset" && ${ROOT_PATH:-"unset"} != "unset" ]] ||
[[ ${BOOT_PATH:-"unset"} != "unset" && ${ROOT_PATH:-"unset"} == "unset" ]]; then
echo " *** You need to specify both ROOT_PATH and BOOT_PATH, or neither"
exit 1
fi
BRANCH=${BRANCH:-"master"}
ROOT_PATH=${ROOT_PATH:-"/"}
BOOT_PATH=${BOOT_PATH:-"/boot"}
WORK_PATH=${WORK_PATH:-"${ROOT_PATH}/root"}
SKIP_KERNEL=${SKIP_KERNEL:-0}
SKIP_SDK=${SKIP_SDK:-0}
RPI_UPDATE_UNSUPPORTED=${RPI_UPDATE_UNSUPPORTED:-0}
FW_REPO="${REPO_URI}.git"
FW_REPOLOCAL="${WORK_PATH}/.rpi-firmware"
FW_PATH="${BOOT_PATH}"
FW_MODPATH="${ROOT_PATH}/lib/modules"
FW_REV=${1:-""}
FW_REVFILE="${FW_PATH}/.firmware_revision"
[ "${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
function update_self() {
echo " *** Performing self-update"
_tempFileName="$0.tmp"
if ! wget --output-document="${_tempFileName}" "${UPDATE_URI}"; then
echo " !!! Failed to download update for rpi-update!"
echo " !!! Make sure you have ca-certificates installed and that the time is set correctly"
exit 1
fi
OCTAL_MODE=$(stat -c '%a' "$0")
if ! chmod ${OCTAL_MODE} "${_tempFileName}" ; then
echo " !!! Failed: Error while trying to set mode on ${_tempFileName}"
exit 1
fi
cat > "${WORK_PATH}/.updateScript.sh" << EOF
if mv "${_tempFileName}" "$0"; then
rm -- "\$0"
exec env UPDATE_SELF=0 /bin/bash "$0" "${FW_REV}"
else
echo " !!! Failed!"
fi
EOF
echo " *** Relaunching after update"
exec /bin/bash "${WORK_PATH}/.updateScript.sh"
}
function update_modules {
if [[ ${SKIP_KERNEL} -eq 0 ]]; then
echo " *** Updating kernel modules"
cp -vR "${FW_REPOLOCAL}/modules/"* "${FW_MODPATH}/"
find "${FW_REPOLOCAL}/modules" -mindepth 1 -maxdepth 1 -type d | while read DIR; do
BASEDIR=$(basename "${DIR}")
echo " *** depmod ${BASEDIR}"
depmod -b "${ROOT_PATH}" -a "${BASEDIR}"
done
else
echo " *** As requested, not updating kernel modules"
fi
}
function update_vc_libs {
echo " *** Updating VideoCore libraries"
ELFOUTPUT=$(readelf -a "${ROOT_PATH}/bin/bash")
if [ "${ELFOUTPUT}" != "${ELFOUTPUT/VFP_args/}" ]; then
echo " *** Using HardFP libraries"
cp -vR "${FW_REPOLOCAL}/vc/hardfp/"* "${ROOT_PATH}/"
else
echo " *** Using SoftFP libraries"
cp -vR "${FW_REPOLOCAL}/vc/softfp/"* "${ROOT_PATH}/"
fi
}
function update_sdk {
if [[ ${SKIP_SDK} -eq 0 ]]; then
echo " *** Updating SDK"
cp -vR "${FW_REPOLOCAL}/vc/sdk/"* "${ROOT_PATH}/"
else
echo " *** As requested, not updating SDK"
fi
}
function update_firmware {
echo " *** Updating firmware"
rm -rf "${FW_PATH}/"*.elf
rm -rf "${FW_PATH}/"*.bin
cp -v "${FW_REPOLOCAL}/"*.elf "${FW_PATH}/"
cp -v "${FW_REPOLOCAL}/"*.bin "${FW_PATH}/"
cp -v "${FW_REPOLOCAL}/"*.dat "${FW_PATH}/"
if [[ ${SKIP_KERNEL} -eq 0 ]]; then
cp -v "${FW_REPOLOCAL}/"*.img "${FW_PATH}/"
else
echo " *** As requested, not updating kernel"
fi
}
function finalise {
if [[ -f "${FW_PATH}/arm192_start.elf" ]]; then
echo " *** Setting 192M ARM split"
cp -v "${FW_PATH}/arm192_start.elf" "${FW_PATH}/start.elf"
fi
echo " *** Running ldconfig"
ldconfig -r "${ROOT_PATH}"
if [[ "${FW_REV}" == "" ]]; then
echo " *** Storing current firmware revision"
git --git-dir="${FW_REPOLOCAL}/.git" rev-parse "${BRANCH}" > "${FW_REVFILE}"
else
echo "${FW_REV}" > "${FW_REVFILE}"
fi
echo " *** Syncing changes to disk"
sync
}
function download_repo {
echo " *** Setting up firmware (this may take a few minutes)"
mkdir -p "${FW_REPOLOCAL}"
set +e
git clone "${FW_REPO}" "${FW_REPOLOCAL}" --depth=1 --branch "${BRANCH}"
RETVAL=$?
set -e
if [[ ${RETVAL} -ne 0 ]]; then
echo " !!! Failed to download new firmware files"
exit 1
fi
}
function update_repo {
# updating a depth=1 git tree doesn't work, so just kill it and clone a new one
rm -rf "${FW_REPOLOCAL}"
download_repo
}
function do_backup {
echo " *** Backing up files"
rm -rf "${FW_PATH}.bak"
cp -va "${FW_PATH}" "${FW_PATH}.bak"
if [[ ${SKIP_KERNEL} -eq 0 ]]; then
rm -rf "${FW_MODPATH}.bak"
cp -va "${FW_MODPATH}" "${FW_MODPATH}.bak"
fi
}
function do_update {
update_firmware
update_modules
update_vc_libs
update_sdk
finalise
echo " *** If no errors appeared, your firmware was successfully $1"
if [[ "${ROOT_PATH}" == "/" ]]; then
echo " *** A reboot is needed to activate the new firmware"
fi
}
function download_rev {
echo " *** Downloading specific firmware revision (this will take a few minutes)"
mkdir -p "${FW_REPOLOCAL}"
FW_TARBALL="${FW_REPOLOCAL}/${FW_REV}.tar.gz"
echo " *** Decompressing downloaded firmware archive"
wget "${REPO_URI}/tarball/${FW_REV}" -O "${FW_TARBALL}"
tar xzf "${FW_TARBALL}" -C "${FW_REPOLOCAL}" --strip-components=1
rm "${FW_TARBALL}"
}
if [[ ${EUID} -ne 0 ]]; then
echo " !!! This tool must be run as root"
exit 1
fi
echo " *** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS"
if [[ ${UPDATE_SELF} -ne 0 ]]; then
update_self
fi
if [[ ! -d "${FW_PATH}" ]]; then
echo " !!! ${FW_PATH} doesn't exist"
exit 1
fi
if [[ ${SKIP_KERNEL} -eq 0 ]] && [[ ! -d "${FW_MODPATH}" ]]; then
echo " !!! ${FW_MODPATH} doesn't exist"
exit 1
fi
command -v git >/dev/null 2>&1 || {
echo " !!! This tool requires you have Git installed, please install it first"
echo " In Debian, try: sudo apt-get install git-core"
echo " In Arch, try: pacman -S git"
exit 1
}
command -v readelf >/dev/null 2>&1 || {
echo " !!! This tool requires you have readelf installed, please install it first"
echo " In Debian, try: sudo apt-get install binutils"
echo " In Arch, try: pacman -S binutils"
exit 1
}
echo " *** ARM/GPU split is now defined in /boot/config.txt using the gpu_mem option!"
if [[ "${FW_REV}" != "" ]]; then
download_rev
do_update "updated to revision ${FW_REV}"
elif [[ -f "${FW_REPOLOCAL}/bootcode.bin" ]]; then
# ask git server version before spending time cloning
GITREV=$(git ls-remote -h "${REPO_URI}" "refs/heads/${BRANCH}" | awk '{print $1}')
if [[ -f "${FW_REVFILE}" ]] && [[ $(cat "${FW_REVFILE}") == "$GITREV" ]]; then
echo " *** Your firmware is already up to date"
# no changes made, nothing to finalise
# finalise
else
update_repo
do_update "updated"
fi
else
echo " *** We're running for the first time"
if [[ -d "${FW_REPOLOCAL}" ]]; then
# rpi-update must have errored during the first run
rm -rf "${FW_REPOLOCAL}"
fi
download_repo
do_backup
do_update "setup"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment