2 PATH=/bin:/usr/bin:/sbin:/usr/sbin
4 FAKE_ROOT=/run/upgrade-sysroot
6 UPI_NO_DELTA_ERROR=fb15
9 STATUS_DIR=${FAKE_ROOT}/opt/data/update
10 STATUS_FILE=${STATUS_DIR}/RW.STATUS
11 DELTA_PATH_FILE=${STATUS_DIR}/DELTA.PATH
12 INT_LOG_DIR=${STATUS_DIR}
13 INT_LOG_FILE=${INT_LOG_DIR}/fota_internal.log
15 FOTA_LOG_DIR=/opt/data/update
16 FOTA_RESULT_DIR=${FOTA_LOG_DIR}
17 FOTA_TEMP_DIR=${FOTA_LOG_DIR}
19 PART_TBL_FILE="part_tbl.txt"
20 PART_TBL_PATH=${FOTA_TEMP_DIR}/${PART_TBL_FILE}
31 BLKID="/usr/sbin/blkid"
36 VERITYCTL="/usr/bin/verityctl"
37 VERITY_HANDLER="/usr/bin/verity_handler"
43 FOTA_GUI="/usr/bin/fota_gui"
50 SCRIPT_NAME="fota-init.sh"
54 #------------------------------------------------
56 #------------------------------------------------
58 # log format: [script_name][tag]actual_log
59 LOG="[${SCRIPT_NAME}]$1"
60 if [ "$2" != "" ]; then
66 #------------------------------------------------
68 #------------------------------------------------
70 P_SLOT=$([[ $(</proc/cmdline) =~ partition_ab=([ab]) ]]; echo ${BASH_REMATCH[1]})
73 if [ "${P_SLOT}" != "" ]; then
75 echo "Using A/B slot: ${P_SLOT}"
78 PART_ROOTFS=`/sbin/blkid -t PARTLABEL=rootfs${P_SUFFIX} -o device -l`
79 if [ x$PART_ROOTFS = "x" ]
81 PART_ROOTFS=`/sbin/blkid -L rootfs`
84 PART_SYSTEM_DATA=`/sbin/blkid -t PARTLABEL=system-data -o device -l`
85 if [ x$PART_SYSTEM_DATA = "x" ]
87 PART_SYSTEM_DATA=`/sbin/blkid -L system-data`
90 PART_RAMDISK=`/sbin/blkid -t PARTLABEL=ramdisk${P_SUFFIX} -o device -l`
91 if [ x$PART_RAMDISK = "x" ]
93 PART_RAMDISK=`/sbin/blkid -L ramdisk`
96 PART_HAL=`/sbin/blkid -t PARTLABEL=hal${P_SUFFIX} -o device -l`
97 if [ x$PART_HAL = "x" ]
99 PART_HAL=`/sbin/blkid -L hal`
102 PART_USER=$("$BLKID" --match-token PARTLABEL=user -o device -l || "$BLKID" --match-token LABEL=user -o device -l)
105 mount_bow_partition() {
109 BOWDEV_NAME=bowdev_${LABEL}
110 BOWDEV_PATH=/dev/mapper/${BOWDEV_NAME}
111 SECTORS=$(</sys/class/block/$(lsblk -no NAME ${PARTITION})/size)
113 if ! "${DMSETUP}" create "${BOWDEV_NAME}" --table "0 ${SECTORS} bow ${PARTITION}" ; then
114 log "[Error] Cannot create ${BOWDEV_NAME}"
118 if ! "${MOUNT}" "${BOWDEV_PATH}" "${DIRECTORY}" ; then
119 log "[Error] Cannot mount ${BOWDEV_PATH} into ${DIRECTORY}"
123 "${FSTRIM}" -v "${DIRECTORY}"
125 DM_NUMBER=$(($("${STAT}" -c "0x%T" $(readlink -f "${BOWDEV_PATH}"))))
126 echo 1 > /sys/block/dm-${DM_NUMBER}/bow/state
127 log "[Debug] Mounted ${PARTITION} as DM-BOW" "${INT_LOG_FILE}"
130 mount_f2fs_partition() {
134 if ! "${MOUNT}" -o checkpoint=disable "${PARTITION}" "${DIRECTORY}" ; then
135 log "[Error] Cannot mount ${PARTITION} into ${DIRECTORY}"
138 log "[Debug] Mounted ${PARTITION} as F2FS checkpoint=disable" "${INT_LOG_FILE}"
141 mount_checkpoint_partition() {
145 FSTYPE=$(lsblk -o FSTYPE -n "${PARTITION}")
147 if [ "${FSTYPE}" = "ext4" ]; then
148 if ! mount_bow_partition "${LABEL}" "${PARTITION}" "${DIRECTORY}" ; then
151 elif [ "${FSTYPE}" = "f2fs" ]; then
152 if ! mount_f2fs_partition "${LABEL}" "${PARTITION}" "${DIRECTORY}" ; then
156 "${MOUNT}" "${PARTITION}" "${DIRECTORY}"
157 log "[Info] Unsupported filesystem ${FSTYPE} on ${PARTITION}" "${INT_LOG_FILE}"
161 commit_bow_partition()
165 BOWDEV_NAME=bowdev_${LABEL}
166 BOWDEV_PATH=/dev/mapper/${BOWDEV_NAME}
167 DM_NUMBER=$(($("${STAT}" -c "0x%T" $(readlink -f "${BOWDEV_PATH}"))))
168 echo 2 > /sys/block/dm-${DM_NUMBER}/bow/state
169 log "[Info] Changes on partition ${LABEL} commited (dm-bow)" "${INT_LOG_FILE}"
172 commit_f2fs_partition()
175 PART_SYSTEM_DATA=$(blkid --match-token PARTLABEL="${LABEL}" -o device -l || blkid --match-token LABEL="${LABEL}" -o device -l)
176 "${MOUNT}" -o remount,checkpoint=enable "${PART_SYSTEM_DATA}"
177 log "[Info] Changes on partition ${LABEL} commited (f2fs)" "${INT_LOG_FILE}"
184 TYPE=$(blkid --match-token LABEL="${LABEL}" -o value -s TYPE | tail -n 1)
185 if [ "${TYPE}" = "ext4" ]; then
186 commit_bow_partition "${LABEL}"
187 elif [ "${TYPE}" = "f2fs" ]; then
188 commit_f2fs_partition "${LABEL}"
190 log "[Info] Cannot commit ${LABEL}: Unsupported filesystem ${TYPE}" "${INT_LOG_FILE}"
196 /usr/bin/verityctl create rootfs "${PART_ROOTFS}" "${FAKE_ROOT}"
199 echo "verifyboot: disabled"
203 echo "verityboot: enabled";
207 echo "verifyboot: enabled but corrupted"
208 # should deal with the error like reboot.
211 echo "verifyboot: disabling"
214 "$MOUNT" -o ro "${PART_ROOTFS}" "${FAKE_ROOT}"
217 #------------------------------------------------
219 #------------------------------------------------
222 if [[ "${P_SLOT}" != "" ]]
224 # For A/B Update rootfs should be updated before the system boots in fota mode.
225 # Therefore rootfs should be mounted as RO.
226 # We cannot mount rootfs as RW because mount timestamp would
227 # change and dmverity data would become incorrect
230 if ! mount_checkpoint_partition rootfs "${PART_ROOTFS}" "${FAKE_ROOT}"; then
235 if ! mount_checkpoint_partition system-data "${PART_SYSTEM_DATA}" "${FAKE_ROOT}/${SYSTEM_DATA_MNT}"; then
239 if [ ! "z${PART_USER}" = "z" ]; then
240 if ! mount_checkpoint_partition user "${PART_USER}" "${FAKE_ROOT}/${USER_MNT}"; then
244 if [ "${P_SUFFIX}" == "" ]; then
245 if [ ! "z${PART_HAL}" = "z" ]; then
246 if ! mount_checkpoint_partition hal "${PART_HAL}" "${FAKE_ROOT}/${HAL_MNT}"; then
251 "$MOUNT" "${PART_HAL}" "${FAKE_ROOT}/${HAL_MNT}"
254 "$MOUNT" -t proc none "${FAKE_ROOT}/proc"
255 "$MOUNT" -t sysfs none "${FAKE_ROOT}/sys"
256 "$MOUNT" -t devtmpfs devtmpfs "${FAKE_ROOT}/dev"
257 "$MOUNT" -t devpts devpts "${FAKE_ROOT}/dev/pts"
260 umount_bow_partition()
267 BOWDEV_NAME=bowdev_${LABEL}
268 "${DMSETUP}" remove ${BOWDEV_NAME}
276 TYPE=$(blkid --match-token LABEL="${LABEL}" -o value -s TYPE | tail -n 1)
277 if [ "${TYPE}" = "ext4" ]; then
278 umount_bow_partition "${LABEL}" "${DIRECTORY}"
280 "$UMOUNT" "${DIRECTORY}"
284 #------------------------------------------------
286 #------------------------------------------------
287 umount_partitions() {
289 "$UMOUNT" "${FAKE_ROOT}/dev/pts"
290 "$UMOUNT" "${FAKE_ROOT}/dev"
291 "$UMOUNT" "${FAKE_ROOT}/sys"
292 "$UMOUNT" "${FAKE_ROOT}/proc"
294 if [ "${P_SUFFIX}" == "" ]; then
295 if [ ! "z${PART_HAL}" = "z" ]; then
296 if [ "${UPGRADE_SUCCESS}" = "1" ]; then
297 commit_partition hal "${FAKE_ROOT}/${HAL_MNT}"
299 umount_partition hal "${FAKE_ROOT}/${HAL_MNT}"
302 "$UMOUNT" "${FAKE_ROOT}/${HAL_MNT}"
305 if [ ! "z${PART_USER}" = "z" ]; then
306 if [ "${UPGRADE_SUCCESS}" = "1" ]; then
307 commit_partition user "${FAKE_ROOT}/${USER_MNT}"
309 umount_partition user "${FAKE_ROOT}/${USER_MNT}"
312 if [ "${UPGRADE_SUCCESS}" = "1" ]; then
313 commit_partition system-data "${FAKE_ROOT}/${SYSTEM_DATA_MNT}"
315 umount_partition system-data "${FAKE_ROOT}/${SYSTEM_DATA_MNT}"
317 if [[ "${P_SLOT}" != "" ]]
319 "$UMOUNT" "${FAKE_ROOT}"
321 if [ "${UPGRADE_SUCCESS}" = "1" ]; then
322 commit_partition rootfs "${FAKE_ROOT}"
324 umount_partition rootfs "${FAKE_ROOT}"
328 #------------------------------------------------
330 #------------------------------------------------
332 log "[Error] delta does not exist ..." "${INT_LOG_FILE}"
334 echo "${UPI_NO_DELTA_ERROR}" > "${RESULT_FILE}"
337 #------------------------------------------------
339 #------------------------------------------------
341 log "[Error] ua does not exist ..." "${INT_LOG_FILE}"
343 echo "${UPI_NO_UA_ERROR}" > "${RESULT_FILE}"
346 #------------------------------------------------
347 # do_create_part_table
348 #------------------------------------------------
349 do_create_part_table() {
351 EMMC_DEVICE="/dev/mmcblk0"
352 PART_LIST=$("$BLKID" -o full | "$GREP" "${EMMC_DEVICE}p" |
353 "$SED" -e 's/\/dev\/mmcblk0p//g' -e 's/\ .*LABEL=\"\(.*\).*$/\1/' |
354 "$CUT" -d '"' -f 1 | "$SED" 's/\:/\ /' |
355 "$TR" '[:upper:]' '[:lower:]' |
357 PART_NUM=$(echo "$PART_LIST" | "$WC" -l)
359 echo "$PART_NUM" > "${PART_TBL_PATH}"
360 echo "$PART_LIST" >> "${PART_TBL_PATH}"
364 #------------------------------------------------
366 #------------------------------------------------
368 log "[Info] fota update start ..." "${INT_LOG_FILE}"
370 DELTA_DIR=$("$CAT" "${DELTA_PATH_FILE}")
371 log "[Info] DELTA_DIR = ${DELTA_DIR}" "${INT_LOG_FILE}"
373 RESULT_FILE=${FAKE_ROOT}${FOTA_RESULT_DIR}/result
374 if [ -e "${RESULT_FILE}" ]; then
375 rm -fr "${RESULT_FILE}"
378 UA=${DELTA_DIR}/delta.ua
379 if [ ! -s "${UA}" ]; then
384 /bin/chmod +x "${UA}"
386 DELTA=${DELTA_DIR}/delta.tar
387 if [ ! -s "${DELTA}" ]; then
393 if [ ! -e "${PART_TBL_PATH}" ]; then
394 log "[Error] No partition table" "${INT_LOG_FILE}"
398 VERIFY_TOOL=/usr/sbin/img-verifier
399 if [ -e "${VERIFY_TOOL}" ]; then
400 if ! "${VERIFY_TOOL}" -i "${DELTA}" -l "/opt/var/log/last_iv.log"; then
401 log "[Error] signature verification failed!" "${INT_LOG_FILE}"
404 log "[Info] update package verification success"
407 log "[Error] Warning: No signature verifier... Skip it" "${INT_LOG_FILE}"
411 if [ "$FOTA_GUI_ENABLE" = "1" ]; then
414 if ! "${UA}" "${DELTA_DIR}" "${FOTA_TEMP_DIR}" "$FOTA_ARG"; then
415 log "[Error] update agent fail!!!" "${INT_LOG_FILE}"
418 log "[Info] update agent success"
424 #------------------------------------------------
426 #------------------------------------------------
427 clear_internal_log() {
429 if [ -e "${INT_LOG_FILE}" ]; then
430 /bin/rm -fr "${INT_LOG_FILE}"
435 #------------------------------------------------
437 #------------------------------------------------
440 TEST_DIRS=("${FAKE_ROOT}${FOTA_LOG_DIR}" "${FAKE_ROOT}${FOTA_RESULT_DIR}" "${FAKE_ROOT}${FOTA_TEMP_DIR}")
441 for TEST_DIR in "${TEST_DIRS[@]}"; do
442 if [ ! -e "${TEST_DIR}" ]; then
443 if "$MKDIR" -p "${TEST_DIR}"; then
444 log "[Info] Successfully created <${TEST_DIR}>" "${INT_LOG_FILE}"
446 log "[Error] Unable to create <${TEST_DIR}>"
452 #------------------------------------------------
454 #------------------------------------------------
466 #------------------------------------------------
467 # check_for_rw_power_fail
468 #------------------------------------------------
469 check_for_rw_power_fail() {
470 # Case : Power fail during RW update after RO update
471 if [ -r "${STATUS_FILE}" ]; then
472 log "[Info] ${STATUS_FILE} exists" "${INT_LOG_FILE}"
473 log "[Info] Status file: $("$CAT" "${STATUS_FILE}")" "${INT_LOG_FILE}"
477 exec /sbin/fus_rw-init
481 #------------------------------------------------
483 #------------------------------------------------
484 check_for_fota_gui() {
485 if [ -r "${FOTA_GUI}" ]; then
486 log "[Info] GUI Enabled" "${INT_LOG_FILE}"
491 #------------------------------------------------
493 #------------------------------------------------
495 DEBUG_MODE_FILE=${FAKE_ROOT}/opt/usr/.upgdebug_ro
496 if [ -f "${DEBUG_MODE_FILE}" ]; then
497 DEBUG_MODE_FILE_OWNER=$("${LS}" -l "${DEBUG_MODE_FILE}" | "${CUT}" -d " " -f 3)
498 if [ "${DEBUG_MODE_FILE_OWNER}" = "0" ]; then
499 log "[Info] Enter RO debug mode"
500 log "[Info] If you want to continue FOTA, please remove ${DEBUG_MODE_FILE}"
501 # Wait until debug mode file is removed
502 while [ -f "${DEBUG_MODE_FILE}" ]; do
505 log "[Info] Debug mode file is removed. Resume FOTA"
507 log "[Info] Warning: somebody made non-root debug mode file... ignore it"
512 #------------------------------------------------
514 #------------------------------------------------
515 remake_hash_table() {
516 if [ -f "${VERITYCTL}" ]; then
517 if [ -f "${VERITY_HANDLER}" ]; then
518 "$MOUNT" -o remount,ro "${FAKE_ROOT}"
520 if ! "${VERITY_HANDLER}" "${PART_ROOTFS}"; then
521 log "[Error] verity-handler fail!!!"
524 log "[Info] verity-handler success"
528 log "[Error] Warning: ${VERITYCTL} exists but ${VERITY_HANDLER} does not exists"
532 log "[Info] verityctl does not exist. Skip hash remaking"
537 #------------------------------------------------
539 #------------------------------------------------
541 echo "start" > ${STATUS_FILE}
544 #------------------------------------------------
546 #------------------------------------------------
548 "${MOUNT}" "${PART_RAMDISK}" "${FAKE_ROOT}"
550 mkdir -p "${SYSROOT_DIR}"
551 ./sbin/pivot_root . ./${SYSROOT_DIR}
552 ./bin/mount -M ./${SYSROOT_DIR}/dev /dev
553 ./bin/mount -M ./${SYSROOT_DIR}/sys /sys
554 ./bin/mount -M ./${SYSROOT_DIR}/proc /proc
555 ./bin/umount -l ./${SYSROOT_DIR}
558 ./bin/umount -l /proc
559 exec chroot . /sbin/init
560 # WARNING! never rearch
561 log "[Error] jump_to_ramdisk() failed"
565 #------------------------------------------------
567 #------------------------------------------------
569 mkdir -p ${FAKE_ROOT}
572 #------------------------------------------------
574 #------------------------------------------------
575 function log_boot_info() {
576 CMDLINE_ROOT=$([[ $(</proc/cmdline) =~ (root=[^ ]*) ]]; echo ${BASH_REMATCH[1]})
577 CMDLINE_PARTITION_AB=$([[ $(</proc/cmdline) =~ (partition_ab=[ab]) ]]; echo ${BASH_REMATCH[1]})
578 CMDLINE_BOOTMODE=$([[ $(</proc/cmdline) =~ (bootmode=[^ ]*) ]]; echo ${BASH_REMATCH[1]})
579 log "[Info] Initrd-fota booting (/proc/cmdline $CMDLINE_BOOTMODE $CMDLINE_PARTITION_AB $CMDLINE_ROOT)"
582 #------------------------------------------------
584 #------------------------------------------------
589 if ! mount_partitions ; then
591 log "[Error] Upgrade failed"
597 if [ "${P_SLOT}" != "" ]
599 log "[Info] FOTA with A/B detected - skip RO update"
603 exec /sbin/fus_rw-init
606 # For debugging - It should be deleted on Release
607 /sbin/agetty -l /bin/bash -n --keep-baud 115200,38400,9600 console linux &
613 check_for_rw_power_fail
615 "$MOUNT" -o remount,rw "${FAKE_ROOT}"
619 if [ "$FOTA_GUI_ENABLE" = "1" ]; then
620 export XDG_RUNTIME_DIR=/run
621 export TBM_DISPLAY_SERVER=1
626 /sbin/progress_restart RO &
629 if [ "$fota_result" = "0" ]; then
630 /bin/rm -fr "${DELTA_DIR:?}"/*
636 RO_PROGRESS_FILE=/tmp/upgrade/ro_progress
637 if [ -f "${RO_PROGRESS_FILE}" ]; then
638 echo -1 > "${RO_PROGRESS_FILE}"
641 if [ "$fota_result" = "0" ] && [ "$remake_result" = "0" ]; then
645 exec /sbin/fus_rw-init
648 log "[Error] Upgrade FAILED"