Add support for DFU over TFTP to ARM host image
This adds support for firmware upgrades over TFTP.
The device will broadcast BOOTP messages on the
network to find the TFTP server. If one is running,
it attempts to download the manifest in the expected
format. The manifest has a SHA field that describes
the contents of the update. If this is different
than the current version, the device will run through
the rest of the manifest and request those image files
from the TFTP server. Gzipped files are supported.
BUG: 142283345
Test: local build and run on rock pi 4b
Signed-off-by: Tristan Muntsinger <muntsinger@google.com>
Change-Id: I3e9756a03ad30aff33df6f6329e0e41a893cfa4d
diff --git a/tools/create_base_image_arm.sh b/tools/create_base_image_arm.sh
index e2e2c89..8302c85 100755
--- a/tools/create_base_image_arm.sh
+++ b/tools/create_base_image_arm.sh
@@ -193,6 +193,68 @@
-C none -A arm -T script -d ${mntdir}/boot/init.cmd ${mntdir}/boot/init.scr
cat > ${mntdir}/boot/boot.cmd << "EOF"
+setenv bootcmd_dhcp '
+mw.b ${scriptaddr} 0 0x8000
+mmc dev 0 0
+mmc read ${scriptaddr} 0x1fc0 0x40
+env import -b ${scriptaddr} 0x8000
+mw.b ${scriptaddr} 0 0x8000
+if dhcp ${scriptaddr} manifest.txt; then
+ setenv OldSha ${Sha}
+ setenv Sha
+ env import -t ${scriptaddr} 0x8000 ManifestVersion
+ if test "$ManifestVersion" = "1"; then
+ run manifest1
+ else
+ run manifestX
+ fi
+fi'
+setenv manifestX 'echo "***** ERROR: Unknown manifest version! *****";'
+setenv manifest1 '
+echo "Manifest version 1";
+env import -t ${scriptaddr} 0x8000
+if test "$Sha" != "$OldSha"; then
+ setenv serverip ${TftpServer}
+ setenv loadaddr 0x00200000
+ mmc dev 0 0;
+ file=$TplSplImg; offset=0x40; size=0x1f80; run tftpget1; setenv TplSplImg
+ file=$UbootItb; offset=0x4000; size=0x2000; run tftpget1; setenv UbootItb
+ file=$TrustImg; offset=0x6000; size=0x2000; run tftpget1; setenv TrustImg
+ file=$RootfsImg; offset=0x8000; size=0; run tftpget1; setenv RootfsImg
+ file=$UbootEnv; offset=0x1fc0; size=0x40; run tftpget1; setenv UbootEnv
+ mw.b ${scriptaddr} 0 0x8000
+ env export -b ${scriptaddr} 0x8000
+ mmc write ${scriptaddr} 0x1fc0 0x40
+else
+ echo "Already have ${Sha}. Booting..."
+fi'
+setenv tftpget1 "
+mw.b ${loadaddr} 0 0x400000
+&& tftp ${file}
+&& isGz=0 && setexpr isGz sub .*\\.gz\$ 1 ${file}
+&& if test $isGz = 1; then
+ setexpr boffset ${offset} * 0x200
+ && gzwrite mmc 0 ${loadaddr} 0x${filesize} 100000 ${boffset}
+ && echo Updated: ${bootfile}
+elif test ${file} = boot.env; then
+ env import -b ${loadaddr}
+ && echo Updated: boot.env
+else
+ && if test $size = 0; then
+ setexpr x $filesize - 1
+ && setexpr x $x / 0x1000
+ && setexpr x $x + 1
+ && setexpr x $x * 0x1000
+ && setexpr x $x / 0x200
+ && size=0x${x}
+ fi
+ && mmc write ${loadaddr} ${offset} ${size}
+ && echo Updated: ${bootfile}
+fi
+|| echo ** UPDATE FAILED: ${bootfile} **"
+if mmc dev 1 0; then; else
+ run bootcmd_dhcp;
+fi
load mmc ${devnum}:${distro_bootpart} 0x02080000 /boot/Image
load mmc ${devnum}:${distro_bootpart} 0x04000000 /boot/uInitrd
load mmc ${devnum}:${distro_bootpart} 0x01f00000 /boot/dtb/rockchip/rk3399-rock-pi-4.dtb
diff --git a/tools/make_manifest.sh b/tools/make_manifest.sh
new file mode 100755
index 0000000..a66c1e6
--- /dev/null
+++ b/tools/make_manifest.sh
@@ -0,0 +1,111 @@
+#!/bin/bash
+
+# Copyright 2019 Google Inc. All rights reserved.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+source "${ANDROID_BUILD_TOP}/external/shflags/src/shflags"
+
+DEFINE_string loader1 \
+ "" "Path to loader1 image (partition 1)" "l"
+DEFINE_string env \
+ "" "Path to env image (partition 2)" "e"
+DEFINE_string loader2 \
+ "" "Path to loader2 image (partition 3)" "u"
+DEFINE_string trust \
+ "" "Path to trust image (partition 4)" "t"
+DEFINE_string rootfs \
+ "" "Path to rootfs image (partition 5)" "r"
+DEFINE_string tftp \
+ "192.168.0.1" "TFTP server address" "f"
+DEFINE_string tftpdir \
+ "/tftpboot" "TFTP server directory" "d"
+
+FLAGS_HELP="USAGE: $0 [flags]"
+
+FLAGS "$@" || exit $?
+eval set -- "${FLAGS_ARGV}"
+
+for arg in "$@" ; do
+ flags_help
+ exit 1
+done
+
+confirm() {
+ read -r -p "${1:-Are you sure you want to continue? [y/N]} " response
+ case "$response" in
+ [yY][eE][sS]|[yY])
+ true
+ ;;
+ *)
+ false
+ ;;
+ esac
+}
+
+createManifest() {
+if [ ! -e manifest.txt ]; then
+ cat > manifest.txt << EOF
+ManifestVersion=1
+TftpServer=${tftp}
+EOF
+fi
+}
+
+makeSHA() {
+ key="SHA"
+ cd "${ANDROID_BUILD_TOP}/device/google/cuttlefish_common"
+ SHA=`git rev-parse HEAD`
+ cd -
+ cd "${ANDROID_BUILD_TOP}/external/u-boot"
+ SHA="$SHA,`git rev-parse HEAD`"
+ cd -
+ cd "${ANDROID_BUILD_TOP}/external/arm-trusted-firmware"
+ SHA="$SHA,`git rev-parse HEAD`"
+ cd -
+ grep -q "^${key}=" manifest.txt && \
+ sed -i "s/^${key}=.*/${key}=${SHA}/" manifest.txt || \
+ echo "${key}=${SHA}" >> manifest.txt
+}
+
+addToManifest() {
+ key=$1
+ path=$2
+
+ if [ "${path}" != "" ]; then
+ filename=$(basename $path)
+
+ if [ $key == "UbootEnv" ] && [ ${file: -3} == ".gz" ]; then
+ echo "error: gzip not supported for env images"
+ fi
+ if [ $key != "UbootEnv" ] && [ ${file: -3} != ".gz" ]; then
+ echo "warning: gzip recommended for all non-env images"
+ confirm || exit 1
+ fi
+ if [ ! "${path}" -ef "${tftpdir}/${filename}" ]; then
+ cp "${path}" "${tftpdir}/"
+ fi
+ else
+ unset filename
+ fi
+ grep -q "^${key}=" manifest.txt && \
+ sed -i "s/^${key}=.*/${key}=${filename}/" manifest.txt || \
+ echo "${key}=${filename}" >> manifest.txt
+}
+
+createManifest
+addToManifest RootfsImg ${rootfs}
+addToManifest UbootEnv ${env}
+addToManifest TplSplImg ${loader1}
+addToManifest UbootItb ${loader2}
+makeSHA