This will free about 5 to 12 MB of RAM even on lightly used devices yielding plenty of RAM for autoupdate to succeed.
		
			
				
	
	
		
			187 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
#!/bin/sh
 | 
						|
 | 
						|
if test $(uci get autoupdater.settings.enabled) != 1; then
 | 
						|
  echo "autoupdater is disabled"
 | 
						|
  exit 0
 | 
						|
fi
 | 
						|
 | 
						|
BRANCH=$(uci get autoupdater.settings.branch)
 | 
						|
 | 
						|
PROBABILITY=$(uci get autoupdater.${BRANCH}.probability)
 | 
						|
 | 
						|
if test "a$1" != "a-f"; then
 | 
						|
  # get one random byte from /dev/urandom, convert it to decimal and check
 | 
						|
  # against update_probability*255
 | 
						|
  hexdump -n1 -e '/1 "%d"' /dev/urandom | awk "{exit \$1 > $PROBABILITY * 255}"
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "No autoupdate this time. Use -f to override"
 | 
						|
    exit 0
 | 
						|
  fi
 | 
						|
fi
 | 
						|
 | 
						|
BRANCH_NAME=$(uci get autoupdater.${BRANCH}.name)
 | 
						|
MIRRORS=$(for mirror in $(uci get autoupdater.${BRANCH}.mirror); do \
 | 
						|
            hexdump -n1 -e '/1 "%d '"$mirror"'\n"' /dev/urandom; \
 | 
						|
          done | sort -n | cut -d' ' -f2)
 | 
						|
PUBKEYS=$(uci get autoupdater.${BRANCH}.pubkey)
 | 
						|
GOOD_SIGNATURES=$(uci get autoupdater.${BRANCH}.good_signatures)
 | 
						|
 | 
						|
VERSION_FILE=/lib/gluon/release
 | 
						|
 | 
						|
newer_than() {
 | 
						|
  local old="$(printf '%s\n%s\n' "$1" "$2" | sort -n | head -n 1)"
 | 
						|
  test "$1" != "$old"
 | 
						|
}
 | 
						|
 | 
						|
fetch_manifest() {
 | 
						|
  local MIRROR=$1
 | 
						|
  local manifest=$2
 | 
						|
 | 
						|
  wget -O$manifest "$MIRROR"/manifest
 | 
						|
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "Couldn't fetch manifest from $MIRROR" >&2
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
 | 
						|
  return 0
 | 
						|
}
 | 
						|
 | 
						|
verify_manifest() {
 | 
						|
  local manifest=$1
 | 
						|
  local manifest_upper=$2
 | 
						|
  local manifest_lower=$(mktemp)
 | 
						|
  awk "BEGIN    { sep=0 }
 | 
						|
     /^---\$/ { sep=1; next }
 | 
						|
              { if(sep==0) print > \"$manifest_upper\";
 | 
						|
                else       print > \"$manifest_lower\"}" \
 | 
						|
    $manifest
 | 
						|
 | 
						|
  local signatures=""
 | 
						|
  while read sig; do
 | 
						|
    echo "$sig" | grep -q "^[0-9a-f]\{128\}$"
 | 
						|
    if test $? -ne 0; then
 | 
						|
      continue
 | 
						|
    fi
 | 
						|
    signatures="$signatures -s $sig"
 | 
						|
  done < $manifest_lower
 | 
						|
 | 
						|
  local pubkeys=""
 | 
						|
  for key in $PUBKEYS; do
 | 
						|
    pubkeys="$pubkeys -p $key"
 | 
						|
  done
 | 
						|
 | 
						|
  rm -f $manifest_lower
 | 
						|
 | 
						|
  ecdsaverify -n $GOOD_SIGNATURES $pubkeys $signatures $manifest_upper
 | 
						|
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "Not enough valid signatures!" >&2
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
 | 
						|
  return 0
 | 
						|
}
 | 
						|
 | 
						|
analyse_manifest() {
 | 
						|
  local manifest_upper=$1
 | 
						|
 | 
						|
  grep -q "^BRANCH=${BRANCH_NAME}$" $manifest_upper
 | 
						|
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "Wrong branch. We are on ${BRANCH_NAME}" >&2
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
 | 
						|
  local my_firmware
 | 
						|
  my_firmware=$(grep "^${my_model} " $manifest_upper)
 | 
						|
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "No matching firmware found (model ${my_model})" >&2
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
 | 
						|
  fw_version=$(echo "${my_firmware}"|cut -d' ' -f2)
 | 
						|
  fw_checksum=$(echo "${my_firmware}"|cut -d' ' -f3)
 | 
						|
  fw_file=$(echo "${my_firmware}"|cut -d' ' -f4)
 | 
						|
 | 
						|
  return 0
 | 
						|
}
 | 
						|
 | 
						|
fetch_firmware() {
 | 
						|
  local MIRROR=$1
 | 
						|
  local fw_image=$2
 | 
						|
 | 
						|
  wget -O$fw_image "${MIRROR}/${fw_file}"
 | 
						|
 | 
						|
  if test $? -ne 0; then
 | 
						|
    echo "Error downloading image from $MIRROR" >&2
 | 
						|
    return 1
 | 
						|
  fi
 | 
						|
 | 
						|
  return 0
 | 
						|
}
 | 
						|
 | 
						|
autoupdate() {
 | 
						|
  local MIRROR=$1
 | 
						|
 | 
						|
  local manifest=$(mktemp)
 | 
						|
  fetch_manifest $MIRROR $manifest || { rm -f $manifest; return 1; }
 | 
						|
 | 
						|
  local manifest_upper=$(mktemp)
 | 
						|
  verify_manifest $manifest $manifest_upper || { rm -f $manifest $manifest_upper; return 1; }
 | 
						|
  rm -f $manifest
 | 
						|
 | 
						|
  analyse_manifest $manifest_upper || { rm -f $manifest_upper; return 1; }
 | 
						|
  rm -f $manifest_upper
 | 
						|
 | 
						|
  if newer_than "$fw_version" "$my_version"; then
 | 
						|
    echo "New version available"
 | 
						|
 | 
						|
    # drop caches to make room for firmware image
 | 
						|
    sync
 | 
						|
    sysctl -w vm.drop_caches=3
 | 
						|
 | 
						|
    local fw_image=$(mktemp)
 | 
						|
    fetch_firmware $MIRROR $fw_image || { rm -f $fw_image; return 1; }
 | 
						|
 | 
						|
    image_sha512=$(sha512sum "$fw_image" | awk '{print $1}')
 | 
						|
    image_md5=$(md5sum "$fw_image" | awk '{print $1}')
 | 
						|
    if [ "$image_sha512" != "$fw_checksum" -a "$image_md5" != "$fw_checksum" ]; then
 | 
						|
      echo "Invalid image checksum" >&2
 | 
						|
      rm -f $fw_image
 | 
						|
      return 1
 | 
						|
    fi
 | 
						|
    echo "Upgrading firmware."
 | 
						|
 | 
						|
    sysupgrade "${fw_image}"
 | 
						|
  else
 | 
						|
    echo "No new firmware available"
 | 
						|
  fi
 | 
						|
 | 
						|
  return 0
 | 
						|
}
 | 
						|
 | 
						|
trap 'echo Signal ignored.' INT TERM PIPE
 | 
						|
 | 
						|
. /lib/gluon/functions/model.sh
 | 
						|
my_model="$(get_model | tr '[A-Z]' '[a-z]' | sed -r 's/[^a-z0-9]+/-/g;s/-$//')"
 | 
						|
 | 
						|
if [ ! -f "$VERSION_FILE" ]; then
 | 
						|
  echo "Couldn't determine firmware version!" >&2
 | 
						|
  exit 1
 | 
						|
fi
 | 
						|
 | 
						|
my_version="$(cat "$VERSION_FILE")"
 | 
						|
 | 
						|
for mirror in $MIRRORS; do
 | 
						|
 | 
						|
  autoupdate $mirror && exit 0
 | 
						|
 | 
						|
  unset fw_version
 | 
						|
  unset fw_checksum
 | 
						|
  unset fw_file
 | 
						|
 | 
						|
done
 | 
						|
 |