880 lines
28 KiB
Bash
880 lines
28 KiB
Bash
#!/bin/sh
|
|
|
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
|
|
|
ROOT_MOUNT="/rootfs"
|
|
ROOT_ROMOUNT="/rom"
|
|
#ROOT_RWMOUNT="/data/overlay"
|
|
INIT="/sbin/init"
|
|
ROOT_DEVICE="/dev/system"
|
|
DATA_DEVICE="/dev/data"
|
|
DATA_MOUNT="/data" # mount point of /dev/data in ramdisk
|
|
MOUNT="/bin/mount"
|
|
UMOUNT="/bin/umount"
|
|
FIRMWARE=""
|
|
VENDOR_DEVICE="/dev/vendor"
|
|
DM_VERITY_STATUS_SYSTEM="disabled"
|
|
DM_VERITY_STATUS_VENDOR="disabled"
|
|
DM_DEV_COUNT=0
|
|
ACTIVE_SLOT=""
|
|
root_fstype="ext4"
|
|
OVERLAY_DIR="$DATA_MOUNT/overlay"
|
|
UNENCRYPTED_DIR="$DATA_MOUNT/unencrypted"
|
|
SWUPDATE_DIR="$DATA_MOUNT/swupdate"
|
|
VBMETA_DEVICE=""
|
|
OverlayFS="enabled"
|
|
|
|
data_fbe_keyblob="fbe_keyblob"
|
|
data_fbe_root_dir=""
|
|
keyring_key_id=""
|
|
DATA_FBE_STATUS="disabled"
|
|
|
|
SELINUX_REFPOLICY="@@REFPOLICY_TYPE@@"
|
|
|
|
load_ramdisk_ko() {
|
|
if [ -f /modules/ramdisk/ramdisk_install.sh ]; then
|
|
cd /modules/ramdisk
|
|
/modules/ramdisk/ramdisk_install.sh
|
|
cd -
|
|
fi
|
|
}
|
|
|
|
early_setup() {
|
|
mkdir -p /proc
|
|
mkdir -p /sys
|
|
mount -t proc proc /proc
|
|
mount -t sysfs sysfs /sys
|
|
mount -t devtmpfs none /dev
|
|
|
|
mkdir -p /run
|
|
mkdir -p /var/run
|
|
|
|
# load ramidsk ko for kernel 5.15
|
|
load_ramdisk_ko
|
|
|
|
# wait gpt partition ready and map to /dev/name
|
|
upstream_emmc_mount
|
|
}
|
|
|
|
wait_for_emmc_partition () {
|
|
i=1
|
|
while [ "$i" -le 30 ]
|
|
do
|
|
if [ -d /sys/block/mmcblk0/mmcblk0p4/ ]; then
|
|
echo "mmcblk0p4 ready"
|
|
break
|
|
fi
|
|
|
|
echo "mmcblk0p4 is not ready. Waited for 50ms"
|
|
sleep 0.05
|
|
i=$((i+1))
|
|
done
|
|
}
|
|
|
|
upstream_emmc_mount() {
|
|
echo " do upstream emmc mount"
|
|
if [ ! -f /dev/system ];then
|
|
echo "/dev/system not exist!"
|
|
wait_for_emmc_partition
|
|
if [ -d /sys/block/mmcblk0/mmcblk0p4/ ]; then
|
|
cd /sys/block/mmcblk0/
|
|
for part in mmcblk0p*
|
|
do
|
|
cd $part
|
|
# major=`cat uevent | grep MAJOR= | sed 's/.*=//'`
|
|
# minor=`cat uevent | grep MINOR= | sed 's/.*=//'`
|
|
partname=`cat uevent | grep PARTNAME= | sed 's/.*=//'`
|
|
# echo "part: $part, partname $partname, major $major, minor: $minor"
|
|
# mknod /dev/$partname b $major $minor
|
|
ln -s /dev/$part /dev/$partname
|
|
cd ..
|
|
done
|
|
fi
|
|
cd ~
|
|
|
|
else
|
|
echo "/dev/system exist!"
|
|
fi
|
|
}
|
|
|
|
read_args() {
|
|
[ -z "$CMDLINE" ] && CMDLINE=`cat /proc/cmdline`
|
|
for arg in $CMDLINE; do
|
|
optarg=`expr "x$arg" : 'x[^=]*=\(.*\)'`
|
|
case $arg in
|
|
root=*)
|
|
ROOT_DEVICE=$optarg ;;
|
|
rootfstype=*)
|
|
root_fstype=$optarg
|
|
modprobe $optarg 2> /dev/null ;;
|
|
androidboot.slot_suffix=*)
|
|
ACTIVE_SLOT=$optarg
|
|
ROOT_DEVICE=${ROOT_DEVICE}${ACTIVE_SLOT};;
|
|
androidboot.vbmeta.device=*)
|
|
VBMETA_DEVICE=$optarg ;;
|
|
LABEL=*)
|
|
label=$optarg ;;
|
|
video=*)
|
|
video_mode=$arg ;;
|
|
vga=*)
|
|
vga_mode=$arg ;;
|
|
console=*)
|
|
if [ -z "${console_params}" ]; then
|
|
console_params=$arg
|
|
else
|
|
console_params="$console_params $arg"
|
|
fi ;;
|
|
firmware=*)
|
|
FIRMWARE=$optarg ;;
|
|
init=*)
|
|
init=$optarg ;;
|
|
debugshell*)
|
|
if [ -z "$optarg" ]; then
|
|
shelltimeout=30
|
|
else
|
|
shelltimeout=$optarg
|
|
fi
|
|
esac
|
|
done
|
|
}
|
|
|
|
#on read-only rootfs, .autorelabel can not be deleted, so move this file under /data, in this situation,
|
|
#if do factory reset, selinux relabel will happen again
|
|
selinux_relabel() {
|
|
if [ "$OverlayFS" = "disabled" ]; then
|
|
if [ ! -e $ROOT_MOUNT/data/.autorelabel ] && [ -f /sbin/setfiles ]; then
|
|
echo "selinux relabel"
|
|
touch $ROOT_MOUNT/data/.autorelabel
|
|
chroot ${ROOT_MOUNT} /sbin/setfiles -F /etc/selinux/${SELINUX_REFPOLICY}/contexts/files/file_contexts /data
|
|
fi
|
|
else
|
|
if [ -f ${ROOT_MOUNT}/.autorelabel ]; then
|
|
echo "selinux relabel"
|
|
relabel_list="/data /etc"
|
|
if [ -d /$ROOT_MOUNT/lost+found ]; then
|
|
relabel_list="${relabel_list} /lost+found"
|
|
fi
|
|
chroot ${ROOT_MOUNT} /sbin/setfiles -F /etc/selinux/${SELINUX_REFPOLICY}/contexts/files/file_contexts ${relabel_list}
|
|
rm ${ROOT_MOUNT}/.autorelabel
|
|
fi
|
|
fi
|
|
}
|
|
|
|
check_set_machine_id() {
|
|
if [ "$OverlayFS" = "disabled" ]; then
|
|
if [ ! -e ${ROOT_MOUNT}/data/etc/machine-id ];then
|
|
mkdir -p $ROOT_MOUNT/data/etc
|
|
if [ -f ${ROOT_MOUNT}/etc/machine-id ]; then
|
|
cp ${ROOT_MOUNT}/etc/machine-id $ROOT_MOUNT/data/etc/
|
|
else
|
|
touch $ROOT_MOUNT/data/etc/machine-id
|
|
fi
|
|
fi
|
|
mount --bind $ROOT_MOUNT/data/etc/machine-id ${ROOT_MOUNT}/etc/machine-id
|
|
fi
|
|
|
|
if [ -f ${ROOT_MOUNT}/etc/machine-id ]; then
|
|
mid=$(cat ${ROOT_MOUNT}/etc/machine-id)
|
|
fi
|
|
if [ -z "$mid" ]; then
|
|
mid=$(cat /proc/cpuinfo | grep "^Serial" | md5sum | awk '{print $1}')
|
|
echo $mid > ${ROOT_MOUNT}/etc/machine-id
|
|
fi
|
|
}
|
|
|
|
boot_root() {
|
|
check_set_machine_id
|
|
# The rootfs does not yet contain kernel modules. Copy it!
|
|
if [ ! -d ${ROOT_MOUNT}/lib/modules ]; then
|
|
cp -rf /lib/modules ${ROOT_MOUNT}/lib/
|
|
cp -rf /lib/firmware ${ROOT_MOUNT}/lib/
|
|
cp -rf /etc/modprobe.d ${ROOT_MOUNT}/etc/
|
|
cp -rf /etc/modules-load.d ${ROOT_MOUNT}/etc/
|
|
cp -rf /etc/modules ${ROOT_MOUNT}/etc/
|
|
fi
|
|
|
|
mount -n --move /proc ${ROOT_MOUNT}/proc
|
|
mount -n --move /sys ${ROOT_MOUNT}/sys
|
|
mount -n --move /dev ${ROOT_MOUNT}/dev
|
|
|
|
if [ "$DM_VERITY_STATUS_VENDOR" = "disabled" ] && [ "${ACTIVE_SLOT}" != "" ]; then
|
|
slot=$(cat ${ROOT_MOUNT}/etc/fstab | grep -E "/dev/vendor" | awk '{print $1}' | cut -c 12-)
|
|
if [ "${ACTIVE_SLOT}" != "${slot}" ]; then
|
|
echo "switch vendor${slot} to vendor${ACTIVE_SLOT}"
|
|
sed -i "s/vendor\\${slot}/vendor\\${ACTIVE_SLOT}/" ${ROOT_MOUNT}/etc/fstab
|
|
fi
|
|
fi
|
|
|
|
selinux_relabel
|
|
|
|
cd $ROOT_MOUNT
|
|
|
|
# busybox switch_root supports -c option
|
|
exec switch_root -c /dev/console $ROOT_MOUNT $INIT ||
|
|
fatal "Couldn't switch_root, dropping to shell"
|
|
}
|
|
|
|
fatal() {
|
|
echo $1 >$CONSOLE
|
|
echo >$CONSOLE
|
|
exec sh
|
|
}
|
|
|
|
early_setup
|
|
|
|
[ -z "$CONSOLE" ] && CONSOLE="/dev/console"
|
|
|
|
read_args
|
|
|
|
#Waiting for device to become ready
|
|
|
|
wait_for_device () {
|
|
i=1
|
|
while [ "$i" -le 30 ]
|
|
do
|
|
if [ -b "${ROOT_DEVICE}" ]; then
|
|
echo "${ROOT_DEVICE} is ready now."
|
|
break
|
|
fi
|
|
echo "${ROOT_DEVICE} is not ready. Waited for ${i} second"
|
|
sleep 1
|
|
i=$((i+1))
|
|
done
|
|
}
|
|
|
|
start_init() {
|
|
echo "Starting native initramfs init (/init2)..."
|
|
|
|
# check /init2 exist
|
|
if [ -x /init2 ]; then
|
|
echo "Executing /init2..."
|
|
# exec /init2, then enter rootfs if success
|
|
exec /init2 "$@"
|
|
init2_exit_code=$?
|
|
|
|
echo "/init2 exited with code $init2_exit_code"
|
|
else
|
|
echo "Error: /init2 not found or not executable"
|
|
init2_exit_code=127
|
|
fi
|
|
|
|
echo "Native initramfs init (/init2) failed. Staying in ramfs for debugging..."
|
|
echo "Exit code: $init2_exit_code"
|
|
echo "You can inspect the system and try to fix the issue."
|
|
echo "Available commands: ls, mount, cat, ps, etc."
|
|
echo "To try again manually, run: /init2"
|
|
echo "To enter shell, type 'sh' or 'bash' if available."
|
|
|
|
# enter debug shell
|
|
exec /bin/sh
|
|
}
|
|
|
|
format_and_install() {
|
|
if [ -f "/${ROOT_MOUNT}/${FIRMWARE}" ] ; then
|
|
echo "formating file system"
|
|
export LD_LIBRARY_PATH=/usr/lib
|
|
umount /dev/system
|
|
mkfs.ext4 -F /dev/system
|
|
mkdir -p system
|
|
if ! mount -o rw,noatime,nodiratime -t ext4 /dev/system /system ; then
|
|
fatal "Could not mount system device"
|
|
fi
|
|
echo "extracting file system ..."
|
|
gunzip -c /${ROOT_MOUNT}/${FIRMWARE} | tar -xf - -C /system
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: untar failed."
|
|
else
|
|
echo "Done"
|
|
fi
|
|
device=/dev/boot
|
|
if [ -f "/${ROOT_MOUNT}/boot.img" ]; then
|
|
echo "Writing boot.img into boot partition(${device})..."
|
|
dd if=/${ROOT_MOUNT}/boot.img of=${device}
|
|
echo "Done"
|
|
fi
|
|
sync
|
|
echo "copying existing modules to rootfs"
|
|
cp -rf /lib/modules /system/lib/
|
|
cp -rf /lib/firmware /system/lib/
|
|
cp -rf /etc/modprobe.d /system/etc/
|
|
cp -rf /etc/modules-load.d /system/etc/
|
|
cp -rf /etc/modules /system/etc/
|
|
echo "update complete"
|
|
umount $ROOT_MOUNT
|
|
ROOT_DEVICE=/dev/system
|
|
ROOT_MOUNT=/system
|
|
else
|
|
echo "cannot locate ${FIRMWARE}"
|
|
echo "boot normally..."
|
|
fi
|
|
}
|
|
|
|
# fbe_check_modules
|
|
# Search for necessary external modules for FBE.
|
|
# In case of builtin modules, nothing should be done.
|
|
# Input: N/A
|
|
# Return: N/A
|
|
fbe_check_modules() {
|
|
modules=""
|
|
# If /dev/tee0 is up, it seems the optee.ko and optee_armtz.ko
|
|
# are already builtin.
|
|
if [[ ! -e /dev/tee0 ]]; then
|
|
echo "FBE: /dev/tee0 is not up. Trying to insert optee.ko optee_armtz.ko."
|
|
modules="optee.ko optee_armtz.ko"
|
|
fi
|
|
# If there is /proc/config.gz, it might be able to find some clues in it.
|
|
if [[ -e /proc/config.gz ]]; then
|
|
cat /proc/config.gz | gunzip | grep CONFIG_TRUSTED_KEYS=y > /dev/null 2>&1
|
|
is_builtin1=$?
|
|
cat /proc/config.gz | gunzip | grep CONFIG_TRUSTED_KEYS_TEE=y > /dev/null 2>&1
|
|
is_builtin2=$?
|
|
if [[ $is_builtin1 -ne 0 ]] || [[ $is_builtin2 -ne 0 ]]; then
|
|
modules="$modules trusted.ko"
|
|
fi
|
|
else
|
|
modules="$modules trusted.ko"
|
|
fi
|
|
if [[ -n "$modules" ]]; then
|
|
echo "searching for $modules"
|
|
for mod in $modules; do
|
|
module_path=`find ${ROOT_ROMOUNT}/lib/modules/ -name $mod`
|
|
if [ "$module_path" != "" ]; then
|
|
insmod $module_path
|
|
if [ $? -ne 0 ]; then
|
|
echo "FBE: Cannot insert $mod."
|
|
fi
|
|
else
|
|
echo "FBE: Cannot find $mod."
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
#fbe_kernel_keyring_setup
|
|
# Input: $1: mount point of /dev/data
|
|
# $2: newly formatted or not
|
|
# Return: 0: success
|
|
# 1: failed
|
|
# 2: not newly formatted and no sealed key found
|
|
# (FBE is not enabled for current system)
|
|
fbe_kernel_keyring_setup() {
|
|
if [ $2 -ne 0 ]; then
|
|
echo -n "FBE: Found newly formatted data partition. Creating Data FBE Key ... "
|
|
keyring_key_id=`keyctl add trusted data_fbe_key "new 64" @u`
|
|
else
|
|
if [ -f $1/$data_fbe_keyblob ]; then
|
|
echo -n "FBE: Sealed key found. Trying to add it to kernel keyring ..."
|
|
sealed_key=`cat $1/$data_fbe_keyblob`
|
|
keyring_key_id=`keyctl add trusted data_fbe_key "load $sealed_key" @u`
|
|
else
|
|
echo "FBE: No sealed key found!"
|
|
return 2
|
|
fi
|
|
fi
|
|
#echo "keyring_key_id = $keyring_key_id"
|
|
if expr "$keyring_key_id" + 0 > /dev/null 2>&1; then
|
|
echo "[ Success ]"
|
|
return 0
|
|
else
|
|
echo "[ Failed ]"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
fbe_check_packages() {
|
|
packages="keyctl fscryptctl"
|
|
for p in $packages; do
|
|
which $p 1> /dev/null
|
|
if [ $? -ne 0 ]; then
|
|
echo "FBE: Cannot find $p. It looks like DISTRO_FEATURE, FBE, is not enabled."
|
|
echo "FBE: Skip setup."
|
|
return 1
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
fbe_fscrypt_setup() {
|
|
data_fbe_root_dir="fbe_root"
|
|
|
|
[ ! -d $1/$data_fbe_root_dir ] && mkdir -p $1/$data_fbe_root_dir
|
|
|
|
fscrypt_key_id=`echo $keyring_key_id | fscryptctl add_key_by_keyid $1/$data_fbe_root_dir`
|
|
#echo "fscrypt_key_id= $fscrypt_key_id"
|
|
|
|
echo -n "FBE: fscryptctl set_policy ... "
|
|
fscryptctl set_policy $fscrypt_key_id $1/$data_fbe_root_dir
|
|
if [ $? -ne 0 ]; then
|
|
echo "[ Failed ]"
|
|
return 1
|
|
fi
|
|
echo "[ Success ]"
|
|
return 0
|
|
}
|
|
|
|
data_fbe_bind() {
|
|
# param 1: mount point of /dev/data
|
|
if [ "$DATA_FBE_STATUS" = "setup" ]; then
|
|
# When DATA_FBE_STATUS = setup, it means FBE has been setup on <data mount point>/fbe_root
|
|
# We need to bind it to <root mount point>/data
|
|
mkdir -p $ROOT_MOUNT/data
|
|
mount --bind $1/$data_fbe_root_dir $ROOT_MOUNT/data
|
|
if [ $? != 0 ]; then
|
|
echo "FBE: Failed to bind $1/$data_fbe_root_dir to $ROOT_MOUNT/data"
|
|
DATA_FBE_STATUS="disabled"
|
|
return 1
|
|
fi
|
|
DATA_FBE_STATUS="bound"
|
|
return 0
|
|
else
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
data_fbe_add_unencrypted_folders() {
|
|
if [[ -z "$1" ]]; then
|
|
echo "Invalid foler name provided"
|
|
return
|
|
fi
|
|
# When DATA_FBE_STATUS == bound, it means FBE has been setup and bound to $ROOT_MOUNT/data
|
|
if [[ "$DATA_FBE_STATUS" = "bound" ]]; then
|
|
[[ ! -d $1 ]] && mkdir -p $1
|
|
[[ ! -d $ROOT_MOUNT/$1 ]] && mkdir -p $ROOT_MOUNT/$1
|
|
mount --bind $1 $ROOT_MOUNT/$1
|
|
if [[ $? != 0 ]]; then
|
|
echo "FBE: Failed to add $1 to $ROOT_MOUNT/$1"
|
|
DATA_FBE_STATUS="Error add $1"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
data_fbe_setup() {
|
|
#echo "param: $1 $2"
|
|
fbe_check_packages
|
|
ret=$?
|
|
if [ $ret -ne 0 ]; then
|
|
return $ret
|
|
fi
|
|
|
|
fbe_kernel_keyring_setup $1 $2
|
|
ret=$?
|
|
if [ $ret -eq 1 ]; then
|
|
fbe_check_modules
|
|
fbe_kernel_keyring_setup $1 $2
|
|
elif [[ $ret -eq 2 ]]; then
|
|
return $ret
|
|
fi
|
|
|
|
if expr "$keyring_key_id" + 0 > /dev/null 2>&1; then
|
|
fbe_fscrypt_setup $1
|
|
ret=$?
|
|
if [ $ret != 0 ]; then
|
|
return $ret
|
|
fi
|
|
# Only store key blob in case of newly created key
|
|
if [ $2 -ne 0 ]; then
|
|
keyctl pipe $keyring_key_id > $1/$data_fbe_keyblob
|
|
ret=$?
|
|
sync
|
|
if [ $ret -ne 0 ]; then
|
|
echo "FBE: Store key blob failed($ret)"
|
|
return $ret
|
|
else
|
|
echo "FBE: key blob saved as $1/$data_fbe_keyblob"
|
|
fi
|
|
fi
|
|
DATA_FBE_STATUS="setup"
|
|
else
|
|
echo "FBE: Error: Invalid key id($keyring_key_id)"
|
|
fi
|
|
}
|
|
|
|
data_ext4_handle() {
|
|
# param 1: mount point of /dev/data
|
|
echo -e "Partition formater on $DATA_DEVICE"
|
|
FsType=$(blkid $DATA_DEVICE | sed -n 's/.*TYPE=\"\([^\"]*\)\".*/\1/p')
|
|
newly_formatted=0
|
|
if [ "${FsType}" != "ext4" ]; then
|
|
echo -e "Formating $DATA_DEVICE to ext4 ..."
|
|
yes 2>/dev/null | mkfs.ext4 -q -m 0 -O encrypt $DATA_DEVICE
|
|
sync
|
|
FsType=$(blkid $DATA_DEVICE | sed -n 's/.*TYPE=\"\([^\"]*\)\".*/\1/p')
|
|
echo -e "After formating FSTYPE of $DATA_DEVICE = ${FsType} ..."
|
|
newly_formatted=1
|
|
else
|
|
echo -e "FSTYPE of $DATA_DEVICE is already ext4 ..."
|
|
FactoryReset=$(uenv get factory-reset | grep value | cut -d '[' -f2|cut -d ']' -f1)
|
|
if [ ${FactoryReset} == 1 ]; then
|
|
echo -e "factory reset, Formating $DATA_DEVICE to ext4 ..."
|
|
yes 2>/dev/null | mkfs.ext4 -q -m 0 -O encrypt $DATA_DEVICE
|
|
sync
|
|
uenv set factory-reset 0
|
|
fi
|
|
fi
|
|
|
|
[ ! -d $1 ] && mkdir -p $1
|
|
if ! mount -t ext4 -o rw,noatime,nodiratime $DATA_DEVICE $1 ; then
|
|
fatal "Could not mount $DATA_DEVICE"
|
|
fi
|
|
|
|
data_fbe_setup $1 $newly_formatted
|
|
}
|
|
|
|
dm_verity_setup() {
|
|
echo "setup dm-verity for ${1} partition(${2}) mount to ${3}"
|
|
VERITY_ENV=/usr/share/${1}-dm-verity.env
|
|
|
|
if [ "${root_fstype}" = "squashfs" ]; then
|
|
vbmeta_mtd_number=$(cat /proc/mtd | grep -E "vbmeta" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
VBMETA_DEVICE_REAL=/dev/mtdblock${vbmeta_mtd_number}
|
|
else
|
|
VBMETA_DEVICE_REAL=${VBMETA_DEVICE}${ACTIVE_SLOT}
|
|
# Change /dev/block/ to /dev/
|
|
if [ ! -b ${VBMETA_DEVICE_REAL} ]; then
|
|
VBMETA_DEVICE_REAL=`echo ${VBMETA_DEVICE_REAL} | sed "s/\/block\//\//g"`
|
|
fi
|
|
fi
|
|
|
|
echo "vbmeta device is $VBMETA_DEVICE_REAL"
|
|
|
|
if [ -b "${VBMETA_DEVICE_REAL}" ]; then
|
|
mkdir -p /tmp
|
|
AVB_DM_TOOL_PY=/usr/bin/avbtool-dm-verity.py
|
|
AVB_DM_TOOL_C=/usr/bin/aml-avb-dm-verity
|
|
if [ -x "${AVB_DM_TOOL_PY}" ]; then
|
|
AVB_DM_TOOL=${AVB_DM_TOOL_PY}
|
|
fi
|
|
if [ -x "${AVB_DM_TOOL_C}" ]; then
|
|
AVB_DM_TOOL=${AVB_DM_TOOL_C}
|
|
fi
|
|
if [ -x "${AVB_DM_TOOL}" ]; then
|
|
VERITY_ENV=/tmp/${1}-dm-verity.env
|
|
${AVB_DM_TOOL} print_partition_verity --image "${VBMETA_DEVICE_REAL}" --partition_name "${1}" --active_slot "${ACTIVE_SLOT}" --output "$VERITY_ENV"
|
|
if [ "$?" != "0" ]; then
|
|
echo "failed to read vbmeta device from ${VBMETA_DEVICE_REAL}"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
echo "verity env is $VERITY_ENV"
|
|
|
|
if [ -f $VERITY_ENV ]; then
|
|
. $VERITY_ENV
|
|
veritysetup --data-block-size=${DATA_BLOCK_SIZE} --hash-offset=${DATA_SIZE} \
|
|
create ${1} ${2} ${2} ${ROOT_HASH}
|
|
if [ $? = 0 ]; then
|
|
if [ "${3}" != "none" ]; then
|
|
#mount -o ro /dev/mapper/${1} ${3}
|
|
mount -o ro /dev/dm-${DM_DEV_COUNT} ${3}
|
|
else
|
|
echo "skip mounting ${2}"
|
|
fi
|
|
if [ "$1" = "system" ]; then
|
|
DM_VERITY_STATUS_SYSTEM="enabled"
|
|
elif [ "$1" = "vendor" ]; then
|
|
DM_VERITY_STATUS_VENDOR="enabled"
|
|
fi
|
|
DM_DEV_COUNT=$((DM_DEV_COUNT+1))
|
|
else
|
|
echo "dm-verity fails with return code $?"
|
|
if [ "$1" = "system" ]; then
|
|
DM_VERITY_STATUS_SYSTEM="disabled"
|
|
elif [ "$1" = "vendor" ]; then
|
|
DM_VERITY_STATUS_VENDOR="disabled"
|
|
fi
|
|
fi
|
|
else
|
|
echo "Cannot find root hash in initramfs"
|
|
if [ "$1" = "system" ]; then
|
|
DM_VERITY_STATUS_SYSTEM="disabled"
|
|
elif [ "$1" = "vendor" ]; then
|
|
DM_VERITY_STATUS_VENDOR="disabled"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
enable_irdeto_write_protection() {
|
|
echo "Enable write protection for bl2,tpl,logo,recovery,hwconfig"
|
|
# enable write protection for bl2
|
|
echo 0 > /sys/class/mtd/mtd0/writeable
|
|
# enable write protection for tpl
|
|
echo 0 > /sys/class/mtd/mtd1/writeable
|
|
# enable write protection for logo
|
|
echo 0 > /sys/class/mtd/mtd2/writeable
|
|
# enable write protection for recovery
|
|
echo 0 > /sys/class/mtd/mtd3/writeable
|
|
# enable write protection for hwconfig
|
|
echo 0 > /sys/class/mtd/mtd14/writeable
|
|
}
|
|
|
|
# Try to mount the root image read-write and then boot it up.
|
|
# This function distinguishes between a read-only image and a read-write image.
|
|
# In the former case (typically an iso), it tries to make a union mount if possible.
|
|
# In the latter case, the root image could be mounted and then directly booted up.
|
|
mount_and_boot() {
|
|
mkdir $ROOT_MOUNT
|
|
mknod /dev/loop0 b 7 0 2>/dev/null
|
|
|
|
if [ "${root_fstype}" = "ubifs" ]; then
|
|
ubi_rootfs_mount
|
|
ubi_vendor_attach
|
|
elif [ "${root_fstype}" = "squashfs" ]; then
|
|
squashfs_rootfs_mount
|
|
else
|
|
if [ "${FIRMWARE}" != "" ]; then
|
|
ROOT_DEVICE="/dev/mmcblk1p1"
|
|
fi
|
|
|
|
wait_for_device
|
|
|
|
if [ "$ROOT_DEVICE" != "" ]; then
|
|
dm_verity_setup system ${ROOT_DEVICE} ${ROOT_MOUNT}
|
|
dm_verity_setup vendor ${VENDOR_DEVICE}${ACTIVE_SLOT} none
|
|
echo "dm-verity for system is $DM_VERITY_STATUS_SYSTEM"
|
|
if [ "$DM_VERITY_STATUS_SYSTEM" = "disabled" ]; then
|
|
if ! mount -o ro,noatime,nodiratime $ROOT_DEVICE $ROOT_MOUNT ; then
|
|
SYSTEM_DEV="/dev/mmcblk0p4"
|
|
if [ -e $SYSTEM_DEV ];then
|
|
echo "Found $SYSTEM_DEV, try switch to start it"
|
|
# fsck.ext4 -f -y $SYSTEM_DEV
|
|
mount $SYSTEM_DEV /rootfs
|
|
cd /rootfs
|
|
mount --move /dev dev
|
|
mount --move /proc proc
|
|
mount --move /sys sys
|
|
echo "Switch rootfs ....... "
|
|
exec switch_root . /sbin/init
|
|
fi
|
|
fatal "Could not mount rootfs device"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ "${FIRMWARE}" != "" ]; then
|
|
format_and_install
|
|
fi
|
|
fi
|
|
|
|
if touch $ROOT_MOUNT/bin 2>/dev/null; then
|
|
echo "Root mount is RW"
|
|
# The root image is read-write, directly boot it up.
|
|
if [ "${root_fstype}" = "ext4" ]; then
|
|
data_ext4_handle $DATA_MOUNT
|
|
data_fbe_bind $DATA_MOUNT
|
|
if [[ $? -eq 0 ]]; then
|
|
if [[ -d $OVERLAY_DIR ]]; then
|
|
data_fbe_add_unencrypted_folders $OVERLAY_DIR
|
|
fi
|
|
data_fbe_add_unencrypted_folders $UNENCRYPTED_DIR
|
|
data_fbe_add_unencrypted_folders $SWUPDATE_DIR
|
|
[[ "$DATA_FBE_STATUS" = "bound" ]] && DATA_FBE_STATUS="enabled"
|
|
fi
|
|
if [[ "$DATA_FBE_STATUS" = "disabled" ]]; then
|
|
mkdir -p $ROOT_MOUNT/data
|
|
mount --move $DATA_MOUNT $ROOT_MOUNT/data
|
|
fi
|
|
echo "DATA FBE is: $DATA_FBE_STATUS!"
|
|
else
|
|
data_yaffs2_handle $ROOT_MOUNT/data
|
|
fi
|
|
boot_root
|
|
fi
|
|
|
|
# determine which unification filesystem to use
|
|
union_fs_type=""
|
|
if grep -q -w "overlay" /proc/filesystems; then
|
|
union_fs_type="overlay"
|
|
elif grep -q -w "aufs" /proc/filesystems; then
|
|
union_fs_type="aufs"
|
|
fi
|
|
|
|
# make a union mount if possible
|
|
case $union_fs_type in
|
|
"overlay")
|
|
mkdir -p $ROOT_ROMOUNT
|
|
if ! mount -n --move $ROOT_MOUNT $ROOT_ROMOUNT; then
|
|
rm -rf $ROOT_ROMOUNT
|
|
fatal "Could not move rootfs mount point"
|
|
else
|
|
echo "mount overlay"
|
|
if [ "${root_fstype}" = "ubifs" ]; then
|
|
if [ "$VENDOR_DEVICE" = "enabled" ]; then
|
|
data_ubi_handle 2 /data
|
|
else
|
|
data_ubi_handle 1 /data
|
|
fi
|
|
elif [ "${root_fstype}" = "squashfs" ]; then
|
|
data_ubi_handle 0 /data
|
|
else
|
|
data_ext4_handle $DATA_MOUNT
|
|
fi
|
|
mkdir -p $OVERLAY_DIR/upperdir $OVERLAY_DIR/work
|
|
mount -t overlay overlay -o "lowerdir=$ROOT_ROMOUNT,upperdir=$OVERLAY_DIR/upperdir,workdir=$OVERLAY_DIR/work" $ROOT_MOUNT
|
|
|
|
mkdir -p ${ROOT_MOUNT}/$ROOT_ROMOUNT
|
|
mount --move $ROOT_ROMOUNT ${ROOT_MOUNT}/$ROOT_ROMOUNT
|
|
data_fbe_bind $DATA_MOUNT
|
|
if [[ $? -eq 0 ]]; then
|
|
if [[ -d $OVERLAY_DIR ]]; then
|
|
data_fbe_add_unencrypted_folders $OVERLAY_DIR
|
|
fi
|
|
data_fbe_add_unencrypted_folders $UNENCRYPTED_DIR
|
|
data_fbe_add_unencrypted_folders $SWUPDATE_DIR
|
|
[[ "$DATA_FBE_STATUS" = "bound" ]] && DATA_FBE_STATUS="enabled"
|
|
fi
|
|
if [[ "$DATA_FBE_STATUS" = "disabled" ]]; then
|
|
mkdir -p $ROOT_MOUNT/data
|
|
mount --move $DATA_MOUNT $ROOT_MOUNT/data
|
|
fi
|
|
echo "DATA FBE is: $DATA_FBE_STATUS!"
|
|
fi
|
|
;;
|
|
"aufs")
|
|
mkdir -p /rootfs.ro /rootfs.rw
|
|
if ! mount -n --move $ROOT_MOUNT /rootfs.ro; then
|
|
rm -rf /rootfs.ro /rootfs.rw
|
|
fatal "Could not move rootfs mount point"
|
|
else
|
|
mount -t tmpfs -o rw,noatime,mode=755 tmpfs /rootfs.rw
|
|
mount -t aufs -o "dirs=/rootfs.rw=rw:/rootfs.ro=ro" aufs $ROOT_MOUNT
|
|
mkdir -p $ROOT_MOUNT/rootfs.ro $ROOT_MOUNT/rootfs.rw
|
|
mount --move /rootfs.ro $ROOT_MOUNT/rootfs.ro
|
|
mount --move /rootfs.rw $ROOT_MOUNT/rootfs.rw
|
|
fi
|
|
;;
|
|
"")
|
|
echo "OverlayFS is disabled"
|
|
OverlayFS="disabled"
|
|
if [ "${root_fstype}" = "ext4" ]; then
|
|
data_ext4_handle $DATA_MOUNT
|
|
data_fbe_bind $DATA_MOUNT
|
|
if [[ $? -eq 0 ]]; then
|
|
if [[ -d $OVERLAY_DIR ]]; then
|
|
data_fbe_add_unencrypted_folders $OVERLAY_DIR
|
|
fi
|
|
data_fbe_add_unencrypted_folders $UNENCRYPTED_DIR
|
|
data_fbe_add_unencrypted_folders $SWUPDATE_DIR
|
|
[[ "$DATA_FBE_STATUS" = "bound" ]] && DATA_FBE_STATUS="enabled"
|
|
fi
|
|
if [[ "$DATA_FBE_STATUS" = "disabled" ]]; then
|
|
mkdir -p $ROOT_MOUNT/data
|
|
mount --move $DATA_MOUNT $ROOT_MOUNT/data
|
|
fi
|
|
echo "DATA FBE is: $DATA_FBE_STATUS!"
|
|
elif [ "${root_fstype}" = "ubifs" ]; then
|
|
if [ "$VENDOR_DEVICE" = "enabled" ]; then
|
|
data_ubi_handle 2 /data
|
|
else
|
|
data_ubi_handle 1 /data
|
|
fi
|
|
elif [ "${root_fstype}" = "squashfs" ]; then
|
|
data_yaffs2_handle $ROOT_MOUNT/data
|
|
# data_ubi_handle 0 $ROOT_MOUNT/data
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Use the existence of the 'casecure' directory to determine if it is the Irdeto bootloader version
|
|
#enable_irdeto_write_protection
|
|
|
|
# boot the image
|
|
boot_root
|
|
}
|
|
|
|
squashfs_rootfs_mount()
|
|
{
|
|
vendor_mtd_number=$(cat /proc/mtd | grep -E "vendor" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
VENDOR_DEVICE=/dev/mtdblock${vendor_mtd_number}
|
|
|
|
system_mtd_number=$(cat /proc/mtd | grep -E "system" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
ROOT_DEVICE=/dev/mtdblock${system_mtd_number}
|
|
|
|
if [ -n "$system_mtd_number" ]; then
|
|
ln -sf "${ROOT_DEVICE}" "/dev/system"${ACTIVE_SLOT}
|
|
dm_verity_setup system ${ROOT_DEVICE} ${ROOT_MOUNT}
|
|
fi
|
|
|
|
if [ -n "$vendor_mtd_number" ]; then
|
|
ln -sf "${VENDOR_DEVICE}" "/dev/vendor"${ACTIVE_SLOT}
|
|
dm_verity_setup vendor ${VENDOR_DEVICE} none
|
|
fi
|
|
|
|
echo "dm-verity for system is $DM_VERITY_STATUS_SYSTEM"
|
|
if [ "$DM_VERITY_STATUS_SYSTEM" = "disabled" ]; then
|
|
if ! mount -t squashfs -o ro,noatime,nodiratime $ROOT_DEVICE $ROOT_MOUNT ; then
|
|
fatal "Could not mount $ROOT_DEVICE"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
ubi_rootfs_mount()
|
|
{
|
|
system_mtd_number=$(cat /proc/mtd | grep -E "system" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
ubiattach /dev/ubi_ctrl -m ${system_mtd_number}
|
|
|
|
if [ -c "/dev/ubi0_0" ]; then
|
|
if ! mount -t ubifs -o ro /dev/ubi0_0 $ROOT_MOUNT ; then
|
|
fatal "Could not mount /dev/ubi0_0"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
ubi_vendor_attach()
|
|
{
|
|
vendor_mtd_number=$(cat /proc/mtd | grep -E "vendor" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
|
|
if [ -n "$vendor_mtd_number" ]; then
|
|
ubiattach /dev/ubi_ctrl -m ${vendor_mtd_number}
|
|
VENDOR_DEVICE="enabled"
|
|
fi
|
|
}
|
|
|
|
data_ubi_handle()
|
|
{
|
|
data_mtd_number=$(cat /proc/mtd | grep -E -w "data" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
|
|
mkdir -p $2
|
|
if ! uenv get factory-reset | grep -q 'value:\[1\]'; then
|
|
mount | grep 'data' && echo "Already mounted" && return 0
|
|
|
|
# sure ubi vol exist or not
|
|
ubiattach /dev/ubi_ctrl -m ${data_mtd_number}
|
|
if [ -c "/dev/ubi${1}_0" ]; then
|
|
data_vol_name=`cat /sys/class/ubi/ubi${1}_0/name`
|
|
if [ "${data_vol_name}" = "data" ]; then
|
|
mount -t ubifs /dev/ubi${1}_0 $2
|
|
return 0
|
|
fi
|
|
fi
|
|
ubidetach /dev/ubi_ctrl -d ${1}
|
|
else
|
|
uenv set factory-reset 0
|
|
fi
|
|
|
|
#format data
|
|
flash_eraseall /dev/mtd${data_mtd_number}
|
|
ubiattach /dev/ubi_ctrl -m ${data_mtd_number}
|
|
ubimkvol /dev/ubi${1} -m -N data
|
|
|
|
mount -t ubifs /dev/ubi${1}_0 $2
|
|
}
|
|
|
|
data_yaffs2_handle()
|
|
{
|
|
data_mtd_number=$(cat /proc/mtd | grep -E -w "data" | awk -F : '{print $1}' | grep -o '[0-9]\+')
|
|
|
|
mkdir -p $1
|
|
if ! uenv get factory-reset | grep -q 'value:\[1\]'; then
|
|
mount | grep 'data' && echo "Already mounted" && return 0
|
|
else
|
|
flash_eraseall /dev/mtd${data_mtd_number}
|
|
uenv set factory-reset 0
|
|
fi
|
|
|
|
#mount data
|
|
mount -t yaffs2 /dev/mtdblock${data_mtd_number} $1
|
|
}
|
|
|
|
# mount_and_boot
|
|
start_init
|