| #!/bin/bash |
| |
| GBMC_IMAGE=@GBMC_IMAGE@ |
| |
| if [ "${GBMC_IMAGE}" == "true" ]; then |
| echo "Getting activation half" >&2 |
| source /usr/lib/payload-lib.sh || exit 1 |
| payload_status || exit 1 |
| else |
| echo "vendor image, using fixed location" |
| active_half=0 |
| fi |
| |
| MACHINE=@MACHINE@ |
| |
| img="emmc-image-${MACHINE}.squashfs-xz.verity" |
| emmcdir="/mnt/luks-mmcblk0_fs/emmc-image/${active_half}" |
| hashfile="/usr/share/emmc-image-verity/${img}.env" |
| mountdir="/run/emmc-image" |
| mutableconfdir=/var/lib/extensions.mutable |
| |
| clear_mount_ref() { |
| local mergetime=$(systemctl show emmc-image-setup | grep ExecMainStartTimestampMonotonic | cut -d'=' -f 2) |
| local service |
| for service in $(systemctl list-units | grep service | grep running | cut -d" " -f 3); do |
| local starttime=$(systemctl show $service | grep ExecMainStartTimestampMonotonic | cut -d'=' -f 2) |
| (( starttime > mergetime )) && systemctl restart "${service}" |
| done |
| } |
| |
| if [ $1 == "start" ]; then |
| if [[ -f "/run/emmc-image-runtime/VERSION" ]]; then |
| echo "already have a running eMMC image, probably in netboot" >&2 |
| exit 0 |
| fi |
| |
| if ! source "${hashfile}"; then |
| echo "${emmcimg}: hash file not found" >&2 |
| exit 1 |
| fi |
| |
| if [[ ! -f "${emmcdir}/VERSION" ]]; then |
| echo "${emmcimg}: VERSION file not found" >&2 |
| exit 1 |
| fi |
| |
| mkdir -p "${mountdir}/${img}" |
| mkdir -p /run/extensions/ |
| mkdir -p /run/confexts/ |
| |
| echo "Loading image ${emmcdir}/${img}" >&2 |
| veritysetup --data-block-size=$DATA_BLOCK_SIZE --hash=$HASH_ALGORITHM --hash-block-size=$HASH_BLOCK_SIZE --hash-offset=$DATA_SIZE open "${emmcdir}/${img}" "${img}" "${emmcdir}/${img}" $ROOT_HASH |
| echo "Mounting image links for ${img}" >&2 |
| mount /dev/mapper/${img} "${mountdir}/${img}" || exit |
| echo "Setting sysext links for ${img}" >&2 |
| rm -f /run/extensions/${img} && ln -s "${mountdir}/${img}" "/run/extensions/${img}" |
| rm -f /run/confexts/${img} && ln -s "${mountdir}/${img}" "/run/confexts/${img}" |
| echo "Finished setup runtime image ${img}" >&2 |
| # make the overlay mutable after merge |
| mkdir -p ${mutableconfdir} && rm -f ${mutableconfdir}/* |
| ln -s /run/initramfs/rw/cow/etc ${mutableconfdir}/etc |
| ln -s /run/initramfs/rw/cow/usr ${mutableconfdir}/usr |
| |
| echo "Merging sysext ..." >&2 |
| systemd-sysext merge --force --mutable=auto || exit |
| echo "Merging confext ..." >&2 |
| systemd-confext merge --force --mutable=auto --noexec=false || exit |
| echo "Starting all services" |
| systemctl daemon-reload |
| systemctl start emmc-image.target |
| cp ${emmcdir}/VERSION ${mountdir}/VERSION |
| echo "Loaded emmc images" >&2 |
| |
| elif [ $1 == "stop" ]; then |
| # In regular cases, eMMC image will stay alive until reboot/powercycle. |
| # Clean up could happen in maintenance mode for emmc erase |
| |
| # skip process when reboot |
| systemctl is-active -q reboot.target && exit 0 |
| # skip clean up if eMMC does not exist |
| [[ -f "${emmcdir}/VERSION" ]] || exit 0 |
| echo "clearing emmc image configurations in best effort" >&2 |
| echo "This should be an operation only during maintenance" >&2 |
| rm -rf "${mountdir}/VERSION" |
| # no need to unmerge and reload if no extension config at all. |
| if [[ -d ${mutableconfdir} ]]; then |
| systemctl stop emmc-image.target |
| systemd-confext unmerge |
| systemd-sysext unmerge |
| systemctl daemon-reload |
| rm -rf ${mutableconfdir} |
| # services running after merge is possibly still using the mount. |
| # stop them here |
| clear_mount_ref |
| fi |
| rm -rf /run/extensions /run/confexts |
| |
| umount -l /dev/mapper/${img} |
| rm -rf "${mountdir}/${img}" |
| # deferred close, it won't close until this clean up process quit itself. |
| veritysetup close --deferred "${img}" |
| # waiting for periodic oneshot process to clean up, most of the process can finish within 60s. |
| sleep 120 |
| fi |