| #!/bin/sh |
| # Emergency Recovery Mode. |
| # |
| # The recovery image will be streamed using ginstall from a Google property |
| # over HTTPS. If the 'emergency' boot flag is set then we will immediately break |
| # out of emergency mode and allow the device to fully boot into the emergency |
| # recovery image. |
| |
| . /etc/utils.sh |
| |
| # The URL where our recovery GI images are hosted. |
| DOMAIN="https://storage.googleapis.com/gfiber-emergency-images/current" |
| |
| # The number of times we will retry an operation before giving up and rebooting. |
| MAX_RETRIES="3" |
| |
| # Host to ping to verify we have external reachability. |
| PING_HOST="8.8.8.8" |
| |
| log() { |
| echo "$(basename $0):" "$@" >&2 |
| } |
| |
| is_emergency_debug() { |
| # If boot flag is set, allow the box to boot fully. |
| if grep -Fq "emergency_debug=1" /proc/cmdline; then |
| return 0 |
| fi |
| return 1 |
| } |
| |
| do_reboot() { |
| # Ensure we don't reboot when we are supposed to allow a complete boot up. |
| if ! is_emergency_debug; then |
| log "Rebooting..." |
| reboot || log "Failed to reboot!" |
| fi |
| } |
| |
| on_exit() { |
| do_reboot |
| } |
| # We can't trap ERR because it's a POSIX extension that dash does not implement. |
| trap on_exit EXIT |
| |
| image_file() { |
| local model=$(cat /etc/platform) |
| log "model: ${model}" |
| # TODO(cgibson): Add support for more platforms. |
| # TODO(cgibson): Pass model name in URL and let the server decide what |
| # image we get. |
| case "${model}" in |
| GFRG2*0) |
| echo "gfrg200.gi" |
| ;; |
| GFHD200) |
| echo "gftv200.gi" |
| ;; |
| *) |
| log "Unsupported platform: ${model}" |
| ;; |
| esac |
| } |
| |
| log "Starting emergency recovery mode!" |
| if is_emergency_debug; then |
| log "emergency boot flag is set, allowing device to fully boot." |
| exit 0 |
| fi |
| |
| log "Checking platform support for emergency recovery image..." |
| GINSTALL_IMAGE_FILE=$(image_file) |
| if [ -z ${GINSTALL_IMAGE_FILE} ]; then |
| log "Failed to identify a recovery image for this platform!" |
| exit 1 |
| fi |
| |
| # We may not have a publically routable IP address yet, so wait for a while |
| # until we can ping the outside world. |
| log "Waiting for external connectivity..." |
| i="0" |
| while [ ${i} -lt ${MAX_RETRIES} ]; do |
| i=$((i+1)) |
| if ping -c5 ${PING_HOST}; then |
| log " ...success!" |
| break |
| fi |
| if [ ${i} -ge ${MAX_RETRIES} ]; then |
| log " ...timed out waiting to ping ${PING_HOST}" |
| do_reboot |
| fi |
| sleep 3 |
| done |
| |
| DOWNLOAD_URL="${DOMAIN}/${GINSTALL_IMAGE_FILE}" |
| log "New emergency recovery image will be downloaded from: ${DOWNLOAD_URL}" |
| i="0" |
| while [ ${i} -lt ${MAX_RETRIES} ]; do |
| i=$((i+1)) |
| if ginstall -t "${DOWNLOAD_URL}"; then |
| log " ...ginstall was successful!" |
| break |
| else |
| if [ ${i} -ge ${MAX_RETRIES} ]; then |
| log " ...ginstall failed to fetch requested image; giving up." |
| exit 1 |
| else |
| log " ...ginstall failed, retrying..." |
| fi |
| fi |
| done |