1 IMG_VERIFIER="/usr/sbin/img-verifier"
2 STATUS_DIR="/opt/data/update"
3 HAL_UPGRADE_CFG_DIR="/hal/etc/upgrade/"
4 HAL_PART_MAP_FILE="label_map.list"
5 HAL_PART_LIST_FILE="background_copy.list"
6 CONFIG_FILE="update.cfg"
7 SET_UPGRADE_STATUS="/usr/bin/device_board_set_upgrade_status"
8 DO_RW_UPDATE_FILE="$FOTA_UPDATE_PREFIX/opt/.do_rw_update"
12 #------------------------------------------------
13 # critical_log msg [file]
14 #------------------------------------------------
16 # log format: [script_name][tag]actual_log
17 LOG="[${SCRIPT_NAME}]$1"
19 if [ "$2" != "" ]; then
28 critical_log "$1" "$LOG_FILE"
31 #------------------------------------------------
33 #------------------------------------------------
35 # log format: [script_name][tag]actual_log
36 LOG="[${SCRIPT_NAME}]$1"
37 if [ "$2" != "" ]; then
54 trap 'echo "Aborting due to errexit on ${0##*/}:$LINENO. Exit code: $?" >&2' ERR
59 FILE_PATH="$FOTA_DIR/$FILE_NAME"
60 VALID_CHECKSUM=$(awk "\$2 ~ /^$FILE_NAME\$/ {print \$1}" "$FOTA_DIR/checksum.SHA1")
61 if [ "$VALID_CHECKSUM" == "" ]; then
62 echo "[Error] No $FILE_NAME in checksum.SHA1"
66 if ! echo "$VALID_CHECKSUM $FILE_PATH" | sha1sum --check --status; then
67 echo "[Error] Checksum for file $FILE_NAME is invalid"
71 echo "[Info] Checksum of $FILE_NAME is OK"
78 tar xpf "${ARCHIVE_NAME}" -C "${FOTA_DIR}" "${FILE_NAME}" 2> /dev/null
79 if [ ! -e "${FOTA_DIR}/${FILE_NAME}" ]; then
80 flog "[Error] There is no ${FILE_NAME}"
83 if ! verify_file "$FILE_NAME"; then
90 if [ -e "$IMG_VERIFIER" ]; then
91 log "[Info] Package verifier is found. Verify $DELTA_FILE" "$LOG_FILE"
92 if ! "$IMG_VERIFIER" -i "$DELTA_FILE" -l "/opt/var/log/last_iv.log"; then
93 log "[Error] Update package verification FAILED..." "$LOG_FILE"
94 echo 5 > "$STATUS_DIR"/result
97 log "[Info] Update package verification PASSED!" "$LOG_FILE"
102 check_ab_partition_scheme() {
103 CURRENT_AB="$(/bin/sed -E 's|.*(partition_ab=)([a-b]).*|\2|' /proc/cmdline)"
104 if [ "$CURRENT_AB" != "a" ] && [ "$CURRENT_AB" != "b" ]; then
105 flog "[Info] There is no A/B partition scheme"
109 if [ "$CURRENT_AB" == "b" ]; then
114 check_used_block_device() {
115 local MAPPER_MATCH_REGEX='.*/dev/mapper.*'
116 ROOTFS_DEVICE="$(findmnt / -no SOURCE)"
118 if [[ "${ROOTFS_DEVICE}" =~ ${MAPPER_MATCH_REGEX} ]]; then
119 MAPPER_DEVICE="${ROOTFS_DEVICE}"
120 DM_NAME=$(basename "${MAPPER_DEVICE}")
121 DM_N=$(dmsetup ls -o blkdevname | grep "${DM_NAME}" | sed -e 's/^.*(\([^)]\+\))/\1/')
122 ROOTFS_DEVICE="/dev/$(ls /sys/class/block/${DM_N}/slaves/)"
125 if ! EMMC_DEVICE="/dev/$(/bin/lsblk -ndo pkname "${ROOTFS_DEVICE}")" ||\
126 [ "$EMMC_DEVICE" == "/dev/" ]; then
127 flog "[Error] Unable to find used block device: $EMMC_DEVICE, for /"
133 flog "[Info] Background copying A|B partitions for update..."
134 for partition_name in ${PARTITION_LIST}; do
135 # echo is there to suspend abort when partition will not be found e.g. hal
136 if ! CURRENT_PARTITION="$(/usr/bin/blkid-print "$EMMC_DEVICE" "$partition_name" "$CURRENT_AB" |\
137 sed -E 's|(part_nr: [0-9]+ )\((.*)\): (.*)|\3|' || echo "__FALSE__")" || \
138 [ "$CURRENT_PARTITION" == "__FALSE__" ]; then
139 flog "[Error] Unable to find: $partition_name current partition on $EMMC_DEVICE device on $CURRENT_AB slot"
140 check_optional_partition "$partition_name" 1
143 if ! NEXT_PARTITION="$(/usr/bin/blkid-print "$EMMC_DEVICE" "$partition_name" "$NEXT_AB" |\
144 sed -E 's|(part_nr: [0-9]+ )\((.*)\): (.*)|\3|')"; then
145 flog "[Error] Unable to find: $partition_name next partition on $EMMC_DEVICE device on $CURRENT_AB slot"
146 check_optional_partition "$partition_name" 1
149 if [ "$CURRENT_PARTITION" == "" ] || [ "$NEXT_PARTITION" = "" ]; then
150 flog "[Error] current: $CURRENT_PARTITION or next: $NEXT_PARTITION partition is empty on $EMMC_DEVICE device"
153 if [ "$CURRENT_PARTITION" == "$NEXT_PARTITION" ]; then
154 flog "[Info] $partition_name partition current and next are the same: $CURRENT_PARTITION on $EMMC_DEVICE device"
157 flog "[Info] Background copy $partition_name, from: $CURRENT_PARTITION to $NEXT_PARTITION"
158 /bin/dd if="$CURRENT_PARTITION" of="$NEXT_PARTITION" bs=4096
159 flog "[Info] Finished background copy $partition_name from $CURRENT_PARTITION to $NEXT_PARTITION"
161 if [ "$partition_name" == "rootfs" ]; then
162 flog "[Info] Checksum verification for $partition_name"
163 CUR_SHA1=$(sha1sum "$CURRENT_PARTITION" | awk '{print $1}')
164 NEXT_SHA1=$(sha1sum "$NEXT_PARTITION" | awk '{print $1}')
165 if [ "$CUR_SHA1" == "$NEXT_SHA1" ]; then
166 flog "[Info] Partition $partition_name was cloned correctly"
168 flog "[Error] Checksums are different: $CUR_SHA1 != $NEXT_SHA1"
176 load_background_copy_list() {
177 PARTITION_LIST=$(sed -e '/^#/d' -e '/^$/d' "${HAL_UPGRADE_CFG_DIR}/${HAL_PART_LIST_FILE}")
182 flog "[Info] Flash images for update..."
184 LABEL_MAP_PATH=${HAL_UPGRADE_CFG_DIR}/${HAL_}
185 while read LABEL PARTLABEL; do
186 declare "LABEL_MAP_${LABEL}=${PARTLABEL}"
187 done < <(sed -e '/^#/d' -e '/^$/d' "${LABEL_MAP_PATH}/${HAL_PART_MAP_FILE}")
189 # _OFFSET _SIZE _HASH1 _HASH2
190 while read -r LABEL_NAME DELTA_NAME TYPE DEV OFFSET OLD_SIZE NEW_SIZE OLD_SHA NEW_SHA
192 local LABEL_NAME="$(echo "$LABEL_NAME" | /bin/awk '{print tolower($0)}')"
194 # Translate LABEL to PARTLABEL using label_map.list
195 local TMP="LABEL_MAP_${LABEL_NAME}"
196 local PART_NAME=${!TMP}
197 if [ -z "${PART_NAME}" ]; then
198 PART_NAME=${LABEL_NAME}
201 TYPE_S=(${TYPE//:/ })
202 # We support only FULL_IMAGE, DELTA_IMAGE and DELTA_FS
203 if [[ ! "${TYPE_S[0]}" =~ ^(FULL_IMAGE|DELTA_IMAGE|DELTA_FS)$ ]]; then
204 PARTS_NAME_TO_UPDATE+=( "$PART_NAME:$TYPE" )
208 if ! /bin/tar tf "$DELTA_TAR" "$DELTA_NAME"; then
209 flog "[Info] There is no delta $DELTA_NAME for label $LABEL_NAME from part $PART_NAME"
213 local NEXT_PARTITION="$(/usr/bin/blkid-print "$EMMC_DEVICE" "$PART_NAME" "$NEXT_AB" |\
214 /bin/sed -E 's|(part_nr: [0-9]+ )\((.*)\): (.*)|\3|')"
215 local CURR_PARTITION="$(/usr/bin/blkid-print "$EMMC_DEVICE" "$PART_NAME" "$CURRENT_AB" |\
216 /bin/sed -E 's|(part_nr: [0-9]+ )\((.*)\): (.*)|\3|')"
218 flog "[Info] Flashing $DELTA_NAME... to $NEXT_PARTITION"
222 case "${TYPE_S[0]}" in
224 "$FOTA_DIR/upgrade-apply" --archive "$DELTA_TAR" \
225 --dest "$NEXT_PARTITION" \
226 --dest-size "$NEW_SIZE" \
227 --archive-file "$DELTA_NAME" \
229 --dest-sha1 "$NEW_SHA" && UP_RES=$? || UP_RES=$?
232 "$FOTA_DIR/upgrade-apply" --archive "$DELTA_TAR" \
233 --dest "$NEXT_PARTITION" \
234 --dest-size "$NEW_SIZE" \
235 --archive-file "$DELTA_NAME" \
236 --kind ss_brotli_patch \
237 --patch-orig "$CURR_PARTITION" \
239 --dest-sha1 "$NEW_SHA" && UP_RES=$? || UP_RES=$?
242 mkdir "$FOTA_DIR/partition_mnt"
243 mount "$NEXT_PARTITION" "$FOTA_DIR/partition_mnt"
244 "$FOTA_DIR/upgrade-apply-deltafs" --archive "$DELTA_TAR" \
245 --dest "$FOTA_DIR/partition_mnt" \
246 --archive-file "${DELTA_NAME}/" && UP_RES=$? || UP_RES=$?
247 umount "$NEXT_PARTITION"
248 rm -rf "$FOTA_DIR/partition_mnt"
254 flog "[Info] Finished flashing $DELTA_NAME... to $NEXT_PARTITION"
257 flog "[Info] Flashing error $DELTA_NAME... to $NEXT_PARTITION"
261 done < "$FOTA_DIR/$CONFIG_FILE"
266 SETUP_SCRIPT_NAME=setup.sh
267 SETUP_SCRIPT_PATH=$FOTA_DIR/$SETUP_SCRIPT_NAME
269 /bin/tar xvfp "$DELTA_TAR" -C "$FOTA_DIR" "$SETUP_SCRIPT_NAME" 2>/dev/null ||\
270 (log "[Info] setup.sh does not exist, skipping." "$LOG_FILE" && return)
272 if [ -e "$SETUP_SCRIPT_PATH" ]; then
273 /bin/sh "$SETUP_SCRIPT_PATH"
274 rm "$SETUP_SCRIPT_PATH"
278 write_version_info() {
280 if [ -f "$VERSION_FILE" ]; then
283 OLD_VER=$(/bin/grep platform.version\" /etc/config/model-config.xml \
284 | sed -e 's/.*>\(.*\)<.*/\1/' | head -1)
287 for ENT in $(echo "$OLD_VER" | tr "." "\n"); do
291 CVT_VER=${VER[0]}.${VER[1]}.${VER[2]}.${VER[3]}
293 echo "OLD_VER=$CVT_VER" > "$VERSION_FILE"
296 set_upgrade_status() {
298 ${SET_UPGRADE_STATUS} ${VALUE}
299 if [ $? -eq 0 ]; then
300 critical_log "set_upgrade_status success: ${VALUE}" "$LOG_FILE"
302 critical_log "set_upgrade_status failed: ${VALUE}" "$LOG_FILE"
307 set_upgrade_status -1
314 local MOUNT_OPTIONS="$3"
316 if ! SRC="$(/usr/bin/blkid-print "$EMMC_DEVICE" "$GPT_LABEL" "$NEXT_AB" |\
317 /bin/sed -E 's|(part_nr: [0-9]+ )\((.*)\): (.*)|\3|')"; then
318 flog "[Error] Unable to find $GPT_LABEL partition on $EMMC_DEVICE device for $NEXT_AB slot"
321 local MOUNTED="$(/bin/findmnt -n -o TARGET "$SRC" | /bin/head -n 1 || echo "")"
322 if [ "$MOUNTED" != "" ]; then
323 MOUNT_OPTIONS="bind,${MOUNT_OPTIONS}"
326 if ! /bin/mkdir -p "$DST"; then
327 flog "[Error] Unable to mkdir for mount destination: $DST"
330 if ! /bin/mount -o "$MOUNT_OPTIONS" "$SRC" "$DST"; then
331 flog "[Error] Unable to mount $SRC to $DST, options: $MOUNT_OPTIONS"
334 CLEANUP_PARTITION+=("$DST")
338 cleanup_partitions() {
339 # umount in reverse order
340 for (( idx=${#CLEANUP_PARTITION[@]}-1 ; idx>=0 ; idx-- )) ; do
341 local DST="${CLEANUP_PARTITION[idx]}"
342 if [ "$DST" == "" ]; then
343 flog "[Error] Partition for cleanup is empty, idx: $idx, partition count: ${#CLEANUP_PARTITION[@]}"
346 if ! /bin/umount "$DST"; then
347 flog "[Error] Unable to umount $DST"