diff --git a/projects/Amlogic/filesystem/usr/bin/emmctool b/projects/Amlogic/filesystem/usr/bin/emmctool index 29830e17bf..66dfeae564 100755 --- a/projects/Amlogic/filesystem/usr/bin/emmctool +++ b/projects/Amlogic/filesystem/usr/bin/emmctool @@ -3,95 +3,229 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (C) 2019-present Team LibreELEC (https://libreelec.tv) -BOOT=$(grep /flash /proc/mounts | awk '{print $1}' | sed 's/p[012]//g') -EMMC=$(ls /dev/mmcblk*rpmb | sed 's/rpmb//g' | head -n 1) +# ** !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! ** +# This script is not supported on generic box devices. If you choose to +# modify it to run on other hardware and you brick your device you will +# receive no support to restore your device. You have been warned! -do_checkboot(){ - case $(dtname) in - khadas,vim|khadas,vim2|libretech*) - if [ "$BOOT" = "$EMMC" ]; then - echo "error: You are booted from the eMMC module!" - exit 1 - fi - ;; - *) - echo "error: Your device is not supported for eMMC boot!" - exit 1 - ;; - esac +do_backup(){ + do_umount + echo "info: compressing ${EMMC} to ${2}, this will take time" + dd if="${EMMC}" | gzip > of="${2}" + echo "info: compressing completed" } do_detect(){ + # used on LibreComputer LePotato/LaFrite where pre-formatted modules + # must be attached after boot (LibreComputer supports this) else the + # device always boots to the pre-formatted OS on the module. echo "info: rebinding d0074000.mmc" echo -n d0074000.mmc > /sys/bus/platform/drivers/meson-gx-mmc/unbind echo -n d0074000.mmc > /sys/bus/platform/drivers/meson-gx-mmc/bind sleep 1 - parted -s $EMMC unit s print + parted -s "${EMMC}" unit s print } do_info(){ + BOOTINFO=$(dd if="${BOOT}" count=2048 2>/dev/null | strings | grep -e '^U-Boot ' | awk '{print $2}') + EMMCINFO=$(dd if="${EMMC}" count=2048 2>/dev/null | strings | grep -e '^U-Boot ' | awk '{print $2}') echo "" - echo "info: boot device is $BOOT" - echo "info: emmc device is $EMMC" + if [ -n "${BOOTINFO}" ]; then + echo "info: boot device is $BOOT, U-boot version is ${BOOTINFO}" + else + echo "info: boot device is $BOOT" + fi + if [ -n "${EMMCINFO}" ]; then + echo "info: emmc device is $EMMC, U-boot version is ${EMMCINFO}" + else + echo "info: emmc device is $EMMC" + fi + echo "" + parted -s "${EMMC}" print + echo "" +} + +do_labels(){ + if [ -n "${2}" ] && [ -n "${3}" ]; then + BOOTLABEL=$(echo "${2}" | awk 'BEGIN { getline; print toupper($0) }') + DISKLABEL=$(echo "${3}" | awk 'BEGIN { getline; print toupper($0) }') + else + BOOTLABEL="EMMC_BOOT" + DISKLABEL="EMMC_DISK" + fi + echo "info: using boot=LABEL=${BOOTLABEL} and disk=LABEL=${DISKLABEL}" + do_umount + echo "info: changing label values on partitions" + fatlabel "${EMMC}p1" "${BOOTLABEL}" + e2label "${EMMC}p2" "${DISKLABEL}" + sleep 1 + echo "info: remounting ${EMMC}p1 to /var/media/${BOOTLABEL}" + mkdir -p "/var/media/${BOOTLABEL}" + mount "${EMMC}p1" "/var/media/${BOOTLABEL}" + echo "info: remounting ${EMMC}p2 to /var/media/${DISKLABEL}" + mkdir -p "/var/media/${DISKLABEL}" + mount "${EMMC}p2" "/var/media/${DISKLABEL}" + sleep 1 + echo "info: changing label values in extlinux.conf" + sed -i "s/boot=LABEL=\w*/boot=LABEL=${BOOTLABEL}/g" "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" + sed -i "s/disk=LABEL=\w*/disk=LABEL=${DISKLABEL}/g" "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" + sleep 1 + echo "" + blkid | grep "${EMMC}p" + echo "" + cat "/var/media/${BOOTLABEL}/extlinux/extlinux.conf" echo "" - parted -s $EMMC print } do_resize(){ - for mount in $(grep ${EMMC}p2 /proc/mounts | awk '{print $1}'); do + if [ -z "${DISKLABEL}" ]; then + DISKLABEL=$(blkid | grep "${EMMC}"p2 | awk -F'"' '{print $2}') + fi + do_umount + echo "info: resizing partition ${EMMC}p2 to 100%" + parted -s -m "${EMMC}" resizepart 2 100% || parted -s -m "${EMMC}" resizepart 2 yes 100% + sleep 5 + do_umount + echo "info: checking filesystem" + e2fsck -f "${EMMC}p2" + sleep 1 + echo "info: resizing filesystem" + resize2fs "${EMMC}p2" + sync + sleep 1 + echo "info: remounting ${EMMC}p2 to /var/media/${DISKLABEL}" + mkdir -p "/var/media/${DISKLABEL}" + mount "${EMMC}p2" "/var/media/${DISKLABEL}" + sleep 1 + if [ -f "/var/media/${DISKLABEL}/.please_resize_me" ]; then + rm "/var/media/${DISKLABEL}/.please_resize_me" + fi + parted -s "${EMMC}" unit s print +} + +do_storage(){ + if [ -n "${2}" ]; then + DISKLABEL=$(echo "${2}" | awk 'BEGIN { getline; print toupper($0) }') + else + DISKLABEL="EMMC_DISK" + fi + do_umount + echo "info: converting emmc for /storage use" + parted -s "${EMMC}" mklabel gpt + parted -s "${EMMC}" -a min unit s mkpart EMMC_STORAGE ext4 34 100% + sleep 1 + mkfs.ext4 "${EMMC}p1" + sleep 1 + e2label "${EMMC}p1" EMMC_STORAGE + echo "info: changing label values in extlinux.conf" + mount -o remount,rw /flash + sleep 1 + sed -i "s/disk=LABEL=\w*/disk=LABEL=${DISKLABEL}/g" "/flash/extlinux/extlinux.conf" + mount -o remount,ro /flash + sleep 1 + echo "" + blkid | grep "${EMMC}p" + echo "" + cat "/flash/extlinux/extlinux.conf" + echo "" +} + +do_umount(){ + for mount in $(grep "${EMMC}" /proc/mounts | awk '{print $1}'); do echo "info: unmounting $mount" umount -f "$mount" sleep 1 done - echo "info: resizing ${EMMC}p2 to 100%" - parted -s -m $EMMC resizepart 2 100% - partprobe - sleep 1 - echo "info: remounting ${EMMC}p2 to /var/media/STORAGE" - mount ${EMMC}p2 /var/media/STORAGE - sleep 1 - if [ -f /var/media/STORAGE/.please_resize_me ]; then - rm /var/media/STORAGE/.please_resize_me +} + +do_write(){ + do_umount + if [ "${2: -7}" == ".img.gz" ]; then + echo "info: writing ${2} to ${EMMC}" + gunzip -c "${2}" | dd of="${EMMC}" bs=1M + elif [ "${2: -4}" == ".img" ]; then + echo "info: writing ${2} to ${EMMC}" + dd if="${2}" of="${EMMC}" bs=1M + else + echo "error: ${2} is not a valid image file!" + exit 1 fi - parted -s $EMMC unit s print } do_zero(){ - for mount in $(grep ${EMMC}p /proc/mounts | awk '{print $1}'); do - echo "info: unmounting $mount" - umount -f "$mount" - sleep 1 - done - dd if=/dev/zero of=$EMMC bs=1M + do_umount + echo "info: zeroing ${EMMC}, be patient, this will take time" + dd if="/dev/zero" of="${EMMC}" bs=1M + echo "info: zeroing complete" } do_help(){ echo "" - echo "usage: emmctool -d : (detect) detects a module attached after boot" - echo " emmctool -r : (resize) expands the storage partition to 100%" - echo " emmctool -i : (info) show information about the emmc module" - echo " emmctool -z : (zero) erases/wipes the module" - echo " emmctool -h : (help) displays this message" + echo "usage: emmctool (w)rite : write .img/.img.gz to the eMMC module" + echo " (b)backup : dump the emmc partition to an .img.gz file" + echo " (d)etect : detect an eMMC module attached after boot" + echo " (i)nfo : show info about the eMMC module" + echo " (l)abels : change eMMC disk labels to ${BOOTLABEL}/${DISKLABEL}" + echo " (r)esize : resize the storage partition to 100%" + echo " (s)storage : convert emmc for use as /storage (boot from sdcard)" + echo " (z)ero : zero (erase/wipe) the eMMC module" + echo " (h)elp : displays this help message" echo "" } -case $1 in - --detect|-d|detect) - do_checkboot +BOOT=$(grep /flash /proc/mounts | awk '{print $1}' | sed 's/p[012]//g') +EMMC=$(find /dev -name "mmcblk*rpmb" | sed 's/rpmb//g' | head -n 1) + +if [ -z "${EMMC}" ]; then + echo "error: no emmc module detected!" + exit 1 +fi + +case $(dtname) in + friendlyarm*|hardkernel*|khadas*|libretech*|wetek*) + if [ "${BOOT}" = "${EMMC}" ]; then + do_info + echo "Your device is booted from the eMMC module!" + echo "" + exit 1 + fi + ;; + *) + echo "Your device is not supported!" + echo "" + exit 1 + ;; +esac + +case "${1}" in + backup) + do_backup "$@" + ;; + detect|d) do_detect ;; - --info|-i|info) + info|i) do_info ;; - --resize|-r|resize) - do_checkboot + labels|l) + do_labels "$@" + ;; + resize|r) do_resize ;; - --zero|-z|zero) - do_checkboot + storage|s) + do_storage "$@" + ;; + write|w) + do_write "$@" + do_resize + do_labels + ;; + zero|z) do_zero ;; *) + do_info do_help ;; esac