| #!/bin/sh |
| # |
| # Volume check service |
| # |
| |
| . /etc/utils.sh |
| |
| sata_blkdev=$(find_sata_blkdev) |
| platform=$(cat /etc/platform) |
| |
| # 'data+ubi' partition |
| DATA_MTD_NAME='"data+ubi"' |
| DATA_MTD_NO= |
| |
| DRM0_MTD_NAME='"drmregion0"' |
| DRM0_MTD_NO= |
| DRM1_MTD_NAME='"drmregion1"' |
| DRM1_MTD_NO= |
| |
| # 'rootfs' on /dev/ubi0 |
| # 'data+ubi' on /dev/ubi1 |
| DATA_UBI_NO=1 |
| |
| # eMMC support |
| DATA_MMC_NAME="data+ext4" |
| ATV_DATA_MMC_NAME="userdata" |
| ATV_HWCFG_MMC_NAME="hwcfg" |
| DRM_FS_NAME="drmfs1" |
| DRM_FS_RECOVER_NAME="drmfs2" |
| |
| USER_NAME=user |
| CONFIG_NAME=config |
| |
| CONFIG_SIZE=$((16*1024*1024)) # 16MiB |
| USER_SIZE=0 |
| BADBLOCK_FILE=/tmp/gpio/ledcontrol/flash_bad_blocks |
| |
| |
| check_mtd() |
| { |
| local a b c d e |
| cat /proc/mtd | |
| while read a b c d; do |
| # convert 'mtdxx:' to 'xx' |
| e=${a%:*} |
| [ $d = $1 ] && echo "${e#mtd}" |
| done |
| } |
| |
| get_mtd_size() |
| { |
| local a b c d e |
| cat /proc/mtd | |
| while read a b c d; do |
| e=${a%:*} |
| [ "${e#mtd}" = "$1" ] && printf "%d" 0x${b} |
| done |
| } |
| |
| |
| check_mmc() |
| { |
| local result= |
| sgdisk -p /dev/mmcblk0 >/tmp/mmcpart |
| while read number start end size unit code name; do |
| if [ "$name" = "$1" ]; then |
| result=$number |
| fi |
| done </tmp/mmcpart |
| rm -f /tmp/mmcpart |
| [ -n "$result" ] && echo "$result" |
| } |
| |
| |
| fail() |
| { |
| echo "$(basename $0):" "$@" >&2 |
| [ -f $BADBLOCK_FILE ] || echo "" >$BADBLOCK_FILE |
| } |
| |
| |
| recover_volume() |
| { |
| # Format MTD device and mount UBI volumes. |
| # $1 - MTD device number |
| # $2 - UBI device number |
| |
| echo "Failed to mount ubifs on mtd$1, formatting..." |
| |
| # umount UBI volumes detach UBI devices |
| umount_ubifs $2 |
| |
| # format MTD partition |
| ubiformat /dev/mtd$1 -y |
| |
| # attach UBI devices and mount UBI volumes |
| mount_ubifs $1 $2 |
| } |
| |
| |
| mount_ubifs() |
| { |
| # Attach MTD device to UBI device. |
| # $1 - MTD device number |
| # $2 - UBI device number |
| |
| #echo "Attach mtd$1 to /dev/ubi$2" |
| # If UBI device failed to attach, return 1 to call 'recover_volume()': |
| # 1. detach UBI devices |
| # 2. erase MTD partition |
| # 3. format MTD partition |
| # 4. attach UBI devices and mount UBI volumes again |
| ubiattach -m $1 -d $2 |
| if [ $? -eq 0 ]; then |
| mount_volumes $1 $2 || return 1 |
| else |
| echo "Failed to attach mtd$1 to /dev/ubi$2" |
| return 1 |
| fi |
| } |
| |
| |
| mount_volumes() |
| { |
| # Mount UBI volumes. |
| # $1 - MTD device number |
| # $2 - UBI device number |
| |
| if [ $1 -eq ${DATA_MTD_NO} ]; then |
| # For platforms with a single, small MTD partition; |
| # (ie gfrg240) create a single /user partition and |
| # have /config reside under /user. |
| |
| actual_size=$(get_mtd_size $1) |
| if [ "${actual_size}" -gt "${CONFIG_SIZE}" ]; then |
| # mount UBI 'config' volume |
| mount_volume "${CONFIG_NAME}" "$2" "${CONFIG_SIZE}" || return 1 |
| |
| # mount UBI 'user' volume |
| mount_volume "${USER_NAME}" "$2" "${USER_SIZE}" || return 1 |
| else |
| # mount UBI 'user' volume |
| mount_volume "${USER_NAME}" "$2" "${USER_SIZE}" || return 1 |
| |
| # bring /config under /user |
| mkdir -p "/${USER_NAME}/${CONFIG_NAME}" |
| mount --bind "/${USER_NAME}/${CONFIG_NAME}" "/${CONFIG_NAME}" || return 1 |
| fi |
| fi |
| } |
| |
| |
| mount_volume() |
| { |
| # Mount UBI volume. |
| # $1 - UBI volume name |
| # $2 - UBI device number |
| # $3 - UBI volume size |
| |
| # make UBI volume |
| make_volume $1 $2 $3 || return 1 |
| |
| # mount UBI volume |
| [ ! -d /$1 ] && mkdir -p /$1 |
| if ! mount -o chk_data_crc -t ubifs ubi$2:$1 /$1; then |
| echo "Failed to mount '$1' volume" |
| return 1 |
| fi |
| } |
| |
| |
| make_volume() |
| { |
| # Make UBI volume. |
| # $1 - UBI volume name |
| # $2 - UBI device number |
| # $3 - UBI volume size |
| |
| # get UBI volume name and remove 'space' characters |
| if ubinfo -d $2 -N $1; then |
| echo "UBI volume '$1' exists" |
| return 0 |
| fi |
| |
| # echo "Make '$1' volume on /dev/ubi$2 (size:$3)" |
| if [ $3 = "0" ]; then |
| size_args="-m" |
| else |
| size_args="-s $3" |
| fi |
| |
| if ! ubimkvol /dev/ubi$2 ${size_args} -N $1; then |
| echo "Failed to make '$1' volume" |
| return 1 |
| fi |
| } |
| |
| |
| umount_ubifs() |
| { |
| # Umount UBI volumes. |
| # $1 - UBI device number |
| |
| if [ $1 -eq ${DATA_UBI_NO} ]; then |
| [ -d /${USER_NAME} ] && umount /${USER_NAME} |
| [ -d /${CONFIG_NAME} ] && umount /${CONFIG_NAME} |
| else |
| return 1 |
| fi |
| |
| sleep 1 |
| ubidetach -d $1 |
| } |
| |
| |
| mount_drmfs_ro() |
| { |
| # TODO(jnewlin): Making this mount rw for a few builds. |
| # The first batch of EVT2 boards has unbound keyboxes so we need |
| # this writable so the keybox gets bound when oregano starts. |
| mount -t ext4 -o rw,defaults $1 $2 || return 1 |
| } |
| |
| mount_hwcfg_ro() |
| { |
| mount -t cramfs -o ro,relatime,barrier=1 $1 $2 || return 1 |
| } |
| |
| # $1 : primary drmfs |
| # $2 : secondary drmfs |
| recover_drmfs() |
| { |
| e2fsck $1 || mkfs.ext4 $1 || return 1 |
| mkdir -p /tmp/drmfs_primary |
| mkdir -p /tmp/drmfs_secondary |
| mount -t ext4 -o ro,defaults $2 /tmp/drmfs_secondary || return 1 |
| mount -t ext4 -o defaults $1 /tmp/drmfs_primary || return 1 |
| # TODO(jnewlin): Need to revisit with real keybox name. |
| cp /tmp/drmfs_secondary/drm.bin /tmp/drmfs_primary/drm.bin |
| |
| umount /tmp/drmfs_primary |
| umount /tmp/drmfs_secondary |
| mount_drmfs_ro $1 /user/drmfs |
| } |
| |
| mount_ext4fs() |
| { |
| mount -t ext4 -o defaults,noatime,discard,data=writeback $1 /user || return 1 |
| [ ! -d /user/config ] && mkdir -p /user/config |
| mount --bind /user/config /config || return 1 |
| } |
| |
| mount_atv_ext4fs() |
| { |
| mount -t ext4 -o defaults,noatime,discard,data=writeback $1 /atv_userdata || return 1 |
| mkdir -p /atv_userdata/gfiber/user |
| mount --bind /atv_userdata/gfiber/user /user || return 1 |
| mkdir -p /user/config |
| mount --bind /user/config /config || return 1 |
| } |
| |
| recover_ext4fs() |
| { |
| e2fsck $1 || mkfs.ext4 -E discard -m 2 -L ${DATA_MMC_NAME} $1 |
| mount_ext4fs $1 |
| } |
| |
| recover_atv_ext4fs() |
| { |
| e2fsck $1 || mkfs.ext4 -E discard -m 2 -L ${ATV_DATA_MMC_NAME} $1 |
| mount_atv_ext4fs $1 |
| } |
| |
| |
| case "$1" in |
| start) |
| wait-scsi & # pre-start this so later scripts can use the result |
| |
| # Get MTD partition number |
| DATA_MTD_NO=$(check_mtd ${DATA_MTD_NAME}) |
| DRM0_MTD_NO=$(check_mtd ${DRM0_MTD_NAME}) |
| DRM1_MTD_NO=$(check_mtd ${DRM1_MTD_NAME}) |
| |
| # Log bbinfo at boot |
| BBT="" |
| cat /proc/sys/dev/repartition/bbinfo | |
| while read a b ; do |
| BBT="$BBT$a$b " |
| done |
| echo "Bad Blocks: $BBT" |
| |
| if [ ! -z "${DATA_MTD_NO}" ]; then |
| mount_ubifs ${DATA_MTD_NO} ${DATA_UBI_NO} || \ |
| recover_volume ${DATA_MTD_NO} ${DATA_UBI_NO} |
| else |
| DATA_MMC_NO=$(check_mmc ${DATA_MMC_NAME}) |
| if [ -n "${DATA_MMC_NO}" ]; then |
| DATA_BLK_NAME=/dev/mmcblk0p${DATA_MMC_NO} |
| echo "Found non-ATV partition table ${DATA_MMC_NAME} at ${DATA_BLK_NAME}!" |
| if [ -b ${DATA_BLK_NAME} ]; then |
| mount_ext4fs ${DATA_BLK_NAME} || recover_ext4fs ${DATA_BLK_NAME} |
| fi |
| else |
| # try if this is a dual-boot Android TV system |
| ATV_DATA_MMC_NO=$(check_mmc ${ATV_DATA_MMC_NAME}) |
| if [ -n "${ATV_DATA_MMC_NO}" ]; then |
| ATV_DATA_BLK_NAME=/dev/mmcblk0p${ATV_DATA_MMC_NO} |
| echo "Found ATV partition table ${ATV_DATA_MMC_NAME} at ${ATV_DATA_BLK_NAME}!" |
| if [ -b ${ATV_DATA_BLK_NAME} ]; then |
| mount_atv_ext4fs ${ATV_DATA_BLK_NAME} || \ |
| recover_atv_ext4fs ${ATV_DATA_BLK_NAME} |
| fi |
| else |
| echo "Error-Could not find either ${DATA_MMC_NAME} or ${ATV_DATA_MMC_NAME}" |
| fi |
| fi |
| fi |
| |
| # Fix access permissions on drm partitions |
| if [ ! -z "${DRM0_MTD_NO}" ]; then |
| chown appclient:appclient /dev/mtd${DRM0_MTD_NO} |
| chown appclient:appclient /dev/mtdblock${DRM0_MTD_NO} |
| fi |
| if [ ! -z "${DRM1_MTD_NO}" ]; then |
| chown appclient:appclient /dev/mtd${DRM1_MTD_NO} |
| chown appclient:appclient /dev/mtdblock${DRM1_MTD_NO} |
| fi |
| |
| [ ! -d /user/rw ] && mkdir -p /user/rw |
| [ ! -d /user/bsa ] && mkdir -p /user/bsa |
| [ ! -d /user/netflix ] && mkdir -p /user/netflix |
| [ ! -d /user/vudu ] && mkdir -p /user/vudu |
| [ ! -d /user/drm ] && mkdir -p /user/drm |
| [ ! -d /user/widevine ] && mkdir -p /user/widevine |
| [ ! -d /user/ytlb ] && mkdir -p /user/ytlb |
| [ ! -d /tmp/vudu ] && mkdir -p /tmp/vudu |
| [ ! -d /tmp/oprofile ] && mkdir -p /tmp/oprofile |
| |
| if has-drm-fs; then |
| # create folder for SAGE usage tables if not present |
| [ ! -d /user/widevine/brcm_sage ] && mkdir -p /user/widevine/brcm_sage && chmod 777 /user/widevine/brcm_sage |
| [ ! -d /user/drmfs ] && mkdir -p /user/drmfs |
| ATV_HWCFG_MMC_NO=$(check_mmc ${ATV_HWCFG_MMC_NAME}) |
| DRMFS_MOUNTED=0 # not mounted yet |
| if [ -n "${ATV_HWCFG_MMC_NO}" ]; then |
| ATV_HWCFG_BLK_NAME=/dev/mmcblk0p${ATV_HWCFG_MMC_NO} |
| echo "Found ATV partition table ${ATV_HWCFG_MMC_NAME} at ${ATV_HWCFG_BLK_NAME}!" |
| if [ -b ${ATV_HWCFG_BLK_NAME} ]; then |
| if mount_hwcfg_ro ${ATV_HWCFG_BLK_NAME} /user/drmfs; then |
| DRMFS_MOUNTED=1 |
| else |
| echo "failed mounting ${ATV_HWCFG_BLK_NAME}" |
| fi |
| fi |
| fi |
| if [ ${DRMFS_MOUNTED} -eq 0 ]; then |
| DRM_FS_MMC_NO=$(check_mmc ${DRM_FS_NAME}) |
| DRM_FS_RECOVER_MMC_NO=$(check_mmc ${DRM_FS_RECOVER_NAME}) |
| DRM_FS_BLK_NAME=/dev/mmcblk0p${DRM_FS_MMC_NO} |
| DRM_FS_RECOVER_BLK_NAME=/dev/mmcblk0p${DRM_FS_RECOVER_MMC_NO} |
| if [ -b ${DRM_FS_BLK_NAME} ]; then |
| if ! mount_drmfs_ro ${DRM_FS_BLK_NAME} /user/drmfs; then |
| echo "DRMFS is corrupt, attempting to recover keybox..." |
| if ! recover_drmfs ${DRM_FS_BLK_NAME} ${DRM_FS_RECOVER_BLK_NAME}; then |
| echo "DRMFS is corrupted and not recoverable." |
| fi |
| fi |
| fi |
| fi |
| fi |
| |
| rm -rf /user/diag/diagdb.bin /user/diag/*.tmp /user/diag/log |
| |
| # /config must be writeable by non-root |
| chown bin.sys /config |
| chmod 775 /config |
| |
| # Application data must be owned by appclient |
| chown -R appclient.appclient /user/netflix |
| chown -R appclient.appclient /user/vudu |
| chown -R appclient.appclient /user/drm |
| chown -R appclient.appclient /user/widevine |
| chown -R appclient.appclient /user/ytlb |
| chown -R appclient.appclient /tmp/vudu |
| |
| # Application user must be able to write kmsg with logos |
| chmod 622 /dev/kmsg |
| |
| if [ -e "$sata_blkdev" ]; then |
| ( |
| smartctl -A "$sata_blkdev" |
| smartctl -t short "$sata_blkdev" |
| sleep 60 |
| smartctl -l selftest "$sata_blkdev" |
| ) 2>&1 | logos smartctl & |
| fi |
| |
| if [ -e /config/DEBUG ]; then |
| echo "Enabling DEBUG mode because /config/DEBUG is set." >&2 |
| echo >/tmp/DEBUG |
| fi |
| ;; |
| stop) |
| # Get MTD partition number |
| DATA_MTD_NO=$(check_mtd ${DATA_MTD_NAME}) |
| |
| umount_ubifs ${DATA_UBI_NO} |
| ;; |
| restart|reload) |
| ;; |
| *) |
| echo "Usage: $0 {start|stop|restart}" >&2 |
| exit 1 |
| esac |