2019-04-30 23:35:58 +02:00
|
|
|
#########################################
|
2017-07-24 21:10:01 +02:00
|
|
|
#
|
2017-06-18 18:15:44 +02:00
|
|
|
# Magisk General Utility Functions
|
|
|
|
# by topjohnwu
|
2017-07-24 21:10:01 +02:00
|
|
|
#
|
2019-04-30 23:35:58 +02:00
|
|
|
#########################################
|
2017-06-18 18:15:44 +02:00
|
|
|
|
2019-02-24 08:11:11 +01:00
|
|
|
#MAGISK_VERSION_STUB
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
###################
|
|
|
|
# Helper Functions
|
|
|
|
###################
|
2017-07-10 19:54:11 +02:00
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
ui_print() {
|
|
|
|
$BOOTMODE && echo "$1" || echo -e "ui_print $1\nui_print" >> /proc/self/fd/$OUTFD
|
|
|
|
}
|
2018-01-01 09:46:28 +01:00
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
toupper() {
|
|
|
|
echo "$@" | tr '[:lower:]' '[:upper:]'
|
|
|
|
}
|
2017-09-27 18:54:01 +02:00
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
grep_cmdline() {
|
|
|
|
local REGEX="s/^$1=//p"
|
|
|
|
cat /proc/cmdline | tr '[:space:]' '\n' | sed -n "$REGEX" 2>/dev/null
|
|
|
|
}
|
|
|
|
|
|
|
|
grep_prop() {
|
|
|
|
local REGEX="s/^$1=//p"
|
|
|
|
shift
|
|
|
|
local FILES=$@
|
|
|
|
[ -z "$FILES" ] && FILES='/system/build.prop'
|
|
|
|
sed -n "$REGEX" $FILES 2>/dev/null | head -n 1
|
|
|
|
}
|
|
|
|
|
|
|
|
getvar() {
|
|
|
|
local VARNAME=$1
|
|
|
|
local VALUE=
|
|
|
|
VALUE=`grep_prop $VARNAME /sbin/.magisk/config /data/.magisk /cache/.magisk`
|
|
|
|
[ ! -z $VALUE ] && eval $VARNAME=\$VALUE
|
|
|
|
}
|
|
|
|
|
|
|
|
is_mounted() {
|
|
|
|
grep -q " `readlink -f $1` " /proc/mounts 2>/dev/null
|
|
|
|
return $?
|
|
|
|
}
|
|
|
|
|
|
|
|
abort() {
|
|
|
|
ui_print "$1"
|
|
|
|
$BOOTMODE || recovery_cleanup
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
resolve_vars() {
|
|
|
|
MAGISKBIN=$NVBASE/magisk
|
2019-02-12 08:14:57 +01:00
|
|
|
POSTFSDATAD=$NVBASE/post-fs-data.d
|
|
|
|
SERVICED=$NVBASE/service.d
|
2019-02-11 23:14:07 +01:00
|
|
|
}
|
|
|
|
|
2020-03-09 06:25:06 +01:00
|
|
|
print_title() {
|
|
|
|
local len=$(echo -n $1 | wc -c)
|
|
|
|
len=$((len + 2))
|
|
|
|
local pounds=$(printf "%${len}s" | tr ' ' '*')
|
|
|
|
ui_print "$pounds"
|
|
|
|
ui_print " $1 "
|
|
|
|
ui_print "$pounds"
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
######################
|
|
|
|
# Environment Related
|
|
|
|
######################
|
2017-10-31 10:05:24 +01:00
|
|
|
|
2018-08-29 04:03:12 +02:00
|
|
|
setup_flashable() {
|
2019-02-24 08:11:11 +01:00
|
|
|
ensure_bb
|
|
|
|
$BOOTMODE && return
|
2018-07-07 11:48:05 +02:00
|
|
|
if [ -z $OUTFD ] || readlink /proc/$$/fd/$OUTFD | grep -q /tmp; then
|
2018-06-21 04:53:49 +02:00
|
|
|
# We will have to manually find out OUTFD
|
2018-07-07 11:48:05 +02:00
|
|
|
for FD in `ls /proc/$$/fd`; do
|
|
|
|
if readlink /proc/$$/fd/$FD | grep -q pipe; then
|
2020-02-04 20:55:03 +01:00
|
|
|
if ps | grep -v grep | grep -qE " 3 $FD |status_fd=$FD"; then
|
2017-07-09 18:17:34 +02:00
|
|
|
OUTFD=$FD
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2019-02-24 08:11:11 +01:00
|
|
|
ensure_bb() {
|
2020-03-09 06:25:06 +01:00
|
|
|
[ -o standalone ] && return
|
|
|
|
set -o standalone 2>/dev/null && return
|
|
|
|
|
|
|
|
# At this point, we are not running in BusyBox ash
|
|
|
|
# Find our busybox binary
|
|
|
|
local BUSYBOX
|
|
|
|
if [ -f $TMPDIR/busybox ]; then
|
|
|
|
BUSYBOX=$TMPDIR/busybox
|
|
|
|
elif [ -f $MAGISKBIN/busybox ]; then
|
|
|
|
BUSYBOX=$MAGISKBIN/busybox
|
2019-02-11 23:14:07 +01:00
|
|
|
else
|
2020-03-09 06:25:06 +01:00
|
|
|
abort "! Cannot find BusyBox"
|
2019-02-11 23:14:07 +01:00
|
|
|
fi
|
2020-03-09 06:25:06 +01:00
|
|
|
|
|
|
|
# Re-exec our script
|
|
|
|
chmod 755 $BUSYBOX
|
|
|
|
exec $BUSYBOX sh -o standalone $0 "$@"
|
2017-06-18 18:15:44 +02:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
recovery_actions() {
|
2020-01-11 22:48:21 +01:00
|
|
|
# Make sure random won't get blocked
|
2019-02-11 23:14:07 +01:00
|
|
|
mount -o bind /dev/urandom /dev/random
|
|
|
|
# Unset library paths
|
|
|
|
OLD_LD_LIB=$LD_LIBRARY_PATH
|
|
|
|
OLD_LD_PRE=$LD_PRELOAD
|
2019-02-24 08:11:11 +01:00
|
|
|
OLD_LD_CFG=$LD_CONFIG_FILE
|
2019-02-11 23:14:07 +01:00
|
|
|
unset LD_LIBRARY_PATH
|
|
|
|
unset LD_PRELOAD
|
2019-02-24 08:11:11 +01:00
|
|
|
unset LD_CONFIG_FILE
|
2019-02-11 23:14:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
recovery_cleanup() {
|
2020-02-04 20:55:03 +01:00
|
|
|
local DIR
|
2019-02-11 23:14:07 +01:00
|
|
|
ui_print "- Unmounting partitions"
|
2020-01-11 22:48:21 +01:00
|
|
|
(umount_apex
|
2020-02-04 20:55:03 +01:00
|
|
|
if [ ! -d /postinstall/tmp ]; then
|
|
|
|
umount -l /system
|
|
|
|
umount -l /system_root
|
|
|
|
fi
|
2020-01-11 22:48:21 +01:00
|
|
|
umount -l /vendor
|
|
|
|
umount -l /persist
|
2020-02-04 20:55:03 +01:00
|
|
|
for DIR in /apex /system /system_root; do
|
|
|
|
if [ -L "${DIR}_link" ]; then
|
|
|
|
rmdir $DIR
|
|
|
|
mv -f ${DIR}_link $DIR
|
|
|
|
fi
|
|
|
|
done
|
2020-01-11 22:48:21 +01:00
|
|
|
umount -l /dev/random) 2>/dev/null
|
2019-12-27 10:53:27 +01:00
|
|
|
export PATH=$OLD_PATH
|
|
|
|
[ -z $OLD_LD_LIB ] || export LD_LIBRARY_PATH=$OLD_LD_LIB
|
|
|
|
[ -z $OLD_LD_PRE ] || export LD_PRELOAD=$OLD_LD_PRE
|
|
|
|
[ -z $OLD_LD_CFG ] || export LD_CONFIG_FILE=$OLD_LD_CFG
|
2018-06-20 19:37:08 +02:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
#######################
|
|
|
|
# Installation Related
|
|
|
|
#######################
|
|
|
|
|
2020-02-08 12:26:39 +01:00
|
|
|
# find_block [partname...]
|
2018-06-20 19:37:08 +02:00
|
|
|
find_block() {
|
2018-07-02 20:57:57 +02:00
|
|
|
for BLOCK in "$@"; do
|
|
|
|
DEVICE=`find /dev/block -type l -iname $BLOCK | head -n 1` 2>/dev/null
|
|
|
|
if [ ! -z $DEVICE ]; then
|
|
|
|
readlink -f $DEVICE
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
# Fallback by parsing sysfs uevents
|
2018-06-20 19:37:08 +02:00
|
|
|
for uevent in /sys/dev/block/*/uevent; do
|
|
|
|
local DEVNAME=`grep_prop DEVNAME $uevent`
|
|
|
|
local PARTNAME=`grep_prop PARTNAME $uevent`
|
2018-12-24 14:36:37 +01:00
|
|
|
for BLOCK in "$@"; do
|
|
|
|
if [ "`toupper $BLOCK`" = "`toupper $PARTNAME`" ]; then
|
2018-06-20 19:37:08 +02:00
|
|
|
echo /dev/block/$DEVNAME
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
done
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2020-02-08 12:26:39 +01:00
|
|
|
# setup_mntpoint <mountpoint>
|
|
|
|
setup_mntpoint() {
|
2020-02-04 20:55:03 +01:00
|
|
|
local POINT=$1
|
|
|
|
[ -L $POINT ] && mv -f $POINT ${POINT}_link
|
|
|
|
if [ ! -d $POINT ]; then
|
|
|
|
rm -f $POINT
|
|
|
|
mkdir -p $POINT
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2020-02-08 12:26:39 +01:00
|
|
|
# mount_name <partname(s)> <mountpoint> <flag>
|
2019-12-27 10:53:27 +01:00
|
|
|
mount_name() {
|
2019-04-30 23:35:58 +02:00
|
|
|
local PART=$1
|
2019-12-27 10:53:27 +01:00
|
|
|
local POINT=$2
|
|
|
|
local FLAG=$3
|
2020-02-08 12:26:39 +01:00
|
|
|
setup_mntpoint $POINT
|
2019-04-30 23:35:58 +02:00
|
|
|
is_mounted $POINT && return
|
2019-12-27 10:53:27 +01:00
|
|
|
ui_print "- Mounting $POINT"
|
|
|
|
# First try mounting with fstab
|
|
|
|
mount $FLAG $POINT 2>/dev/null
|
2019-04-30 23:35:58 +02:00
|
|
|
if ! is_mounted $POINT; then
|
2019-12-27 10:53:27 +01:00
|
|
|
local BLOCK=`find_block $PART`
|
|
|
|
mount $FLAG $BLOCK $POINT
|
2019-04-30 23:35:58 +02:00
|
|
|
fi
|
2019-12-27 10:53:27 +01:00
|
|
|
}
|
|
|
|
|
2020-02-08 12:26:39 +01:00
|
|
|
# mount_ro_ensure <partname(s)> <mountpoint>
|
2019-12-27 10:53:27 +01:00
|
|
|
mount_ro_ensure() {
|
|
|
|
# We handle ro partitions only in recovery
|
|
|
|
$BOOTMODE && return
|
2020-01-11 22:48:21 +01:00
|
|
|
local PART=$1
|
|
|
|
local POINT=$2
|
|
|
|
mount_name "$PART" $POINT '-o ro'
|
2019-04-30 23:35:58 +02:00
|
|
|
is_mounted $POINT || abort "! Cannot mount $POINT"
|
|
|
|
}
|
|
|
|
|
2017-09-12 22:07:25 +02:00
|
|
|
mount_partitions() {
|
|
|
|
# Check A/B slot
|
2018-06-20 19:37:08 +02:00
|
|
|
SLOT=`grep_cmdline androidboot.slot_suffix`
|
|
|
|
if [ -z $SLOT ]; then
|
2019-04-30 23:35:58 +02:00
|
|
|
SLOT=`grep_cmdline androidboot.slot`
|
|
|
|
[ -z $SLOT ] || SLOT=_${SLOT}
|
2017-11-10 18:33:50 +01:00
|
|
|
fi
|
2018-06-20 19:37:08 +02:00
|
|
|
[ -z $SLOT ] || ui_print "- Current boot slot: $SLOT"
|
2018-01-01 09:46:28 +01:00
|
|
|
|
2019-12-27 10:53:27 +01:00
|
|
|
# Mount ro partitions
|
2020-01-11 22:48:21 +01:00
|
|
|
mount_ro_ensure "system$SLOT app$SLOT" /system
|
2019-03-03 12:35:25 +01:00
|
|
|
if [ -f /system/init.rc ]; then
|
2018-06-17 11:59:24 +02:00
|
|
|
SYSTEM_ROOT=true
|
2020-02-08 12:26:39 +01:00
|
|
|
setup_mntpoint /system_root
|
2020-03-09 06:38:47 +01:00
|
|
|
if ! mount --move /system /system_root; then
|
|
|
|
umount /system
|
|
|
|
umount -l /system 2>/dev/null
|
|
|
|
mount_ro_ensure "system$SLOT app$SLOT" /system_root
|
|
|
|
fi
|
2017-09-12 22:07:25 +02:00
|
|
|
mount -o bind /system_root/system /system
|
2019-04-30 23:35:58 +02:00
|
|
|
else
|
Logical Resizable Android Partitions support
The way how logical partition, or "Logical Resizable Android Partitions"
as they say in AOSP source code, is setup makes it impossible to early
mount the partitions from the shared super partition with just
a few lines of code; in fact, AOSP has a whole "fs_mgr" folder which
consist of multiple complex libraries, with 15K lines of code just
to deal with the device mapper shenanigans.
In order to keep the already overly complicated MagiskInit more
managable, I chose NOT to go the route of including fs_mgr directly
into MagiskInit. Luckily, starting from Android Q, Google decided to
split init startup into 3 stages, with the first stage doing _only_
early mount. This is great news, because we can simply let the stock
init do its own thing for us, and we intercept the bootup sequence.
So the workflow can be visualized roughly below:
Magisk First Stage --> First Stage Mount --> Magisk Second Stage --+
(MagiskInit) (Original Init) (MagiskInit) +
+
+
...Rest of the boot... <-- Second Stage <-- Selinux Setup <--+
(__________________ Original Init ____________________)
The catch here is that after doing all the first stage mounting, /init
will pivot /system as root directory (/), leaving us impossible to
regain control after we hand it over. So the solution here is to patch
fstab in /first_stage_ramdisk on-the-fly to redirect /system to
/system_root, making the original init do all the hard work for
us and mount required early mount partitions, but skips the step of
switching root directory. It will also conveniently hand over execution
back to MagiskInit, which we will reuse the routine for patching
root directory in normal system-as-root situations.
2019-06-29 09:47:29 +02:00
|
|
|
grep ' / ' /proc/mounts | grep -qv 'rootfs' || grep -q ' /system_root ' /proc/mounts \
|
|
|
|
&& SYSTEM_ROOT=true || SYSTEM_ROOT=false
|
2017-09-12 22:07:25 +02:00
|
|
|
fi
|
2020-01-11 22:48:21 +01:00
|
|
|
[ -L /system/vendor ] && mount_ro_ensure vendor$SLOT /vendor
|
2019-05-01 07:22:37 +02:00
|
|
|
$SYSTEM_ROOT && ui_print "- Device is system-as-root"
|
2019-12-27 10:53:27 +01:00
|
|
|
|
2020-01-11 22:48:21 +01:00
|
|
|
# Allow /system/bin commands (dalvikvm) on Android 10+ in recovery
|
|
|
|
$BOOTMODE || mount_apex
|
|
|
|
|
2020-01-01 07:02:44 +01:00
|
|
|
# Mount persist partition in recovery
|
2019-12-27 10:53:27 +01:00
|
|
|
if ! $BOOTMODE && [ ! -z $PERSISTDIR ]; then
|
|
|
|
# Try to mount persist
|
|
|
|
PERSISTDIR=/persist
|
|
|
|
mount_name persist /persist
|
|
|
|
if ! is_mounted /persist; then
|
|
|
|
# Fallback to cache
|
2020-01-11 22:48:21 +01:00
|
|
|
mount_name "cache cac" /cache
|
2019-12-27 10:53:27 +01:00
|
|
|
is_mounted /cache && PERSISTDIR=/cache || PERSISTDIR=
|
|
|
|
fi
|
|
|
|
fi
|
2017-09-12 22:07:25 +02:00
|
|
|
}
|
|
|
|
|
2020-02-08 12:26:39 +01:00
|
|
|
# loop_setup <ext4_img>, sets LOOPDEV
|
|
|
|
loop_setup() {
|
|
|
|
unset LOOPDEV
|
|
|
|
local LOOP
|
|
|
|
local MINORX=1
|
|
|
|
[ -e /dev/block/loop1 ] && MINORX=$(stat -Lc '%T' /dev/block/loop1)
|
|
|
|
local NUM=0
|
|
|
|
while [ $NUM -lt 64 ]; do
|
|
|
|
LOOP=/dev/block/loop$NUM
|
|
|
|
[ -e $LOOP ] || mknod $LOOP b 7 $((NUM * MINORX))
|
|
|
|
if losetup $LOOP "$1" 2>/dev/null; then
|
|
|
|
LOOPDEV=$LOOP
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
NUM=$((NUM + 1))
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2020-01-11 22:48:21 +01:00
|
|
|
mount_apex() {
|
2020-02-08 12:26:39 +01:00
|
|
|
$BOOTMODE || [ ! -d /system/apex ] && return
|
|
|
|
local APEX DEST
|
|
|
|
setup_mntpoint /apex
|
2020-01-11 22:48:21 +01:00
|
|
|
for APEX in /system/apex/*; do
|
|
|
|
DEST=/apex/$(basename $APEX .apex)
|
|
|
|
[ "$DEST" == /apex/com.android.runtime.release ] && DEST=/apex/com.android.runtime
|
2020-02-08 12:26:39 +01:00
|
|
|
mkdir -p $DEST 2>/dev/null
|
|
|
|
if [ -f $APEX ]; then
|
|
|
|
# APEX APKs, extract and loop mount
|
|
|
|
unzip -qo $APEX apex_payload.img -d /apex
|
|
|
|
loop_setup apex_payload.img
|
|
|
|
if [ ! -z $LOOPDEV ]; then
|
|
|
|
ui_print "- Mounting $DEST"
|
|
|
|
mount -t ext4 -o ro,noatime $LOOPDEV $DEST
|
|
|
|
fi
|
|
|
|
rm -f apex_payload.img
|
|
|
|
elif [ -d $APEX ]; then
|
|
|
|
# APEX folders, bind mount directory
|
|
|
|
ui_print "- Mounting $DEST"
|
|
|
|
mount -o bind $APEX $DEST
|
|
|
|
fi
|
2020-01-11 22:48:21 +01:00
|
|
|
done
|
|
|
|
export ANDROID_RUNTIME_ROOT=/apex/com.android.runtime
|
|
|
|
export ANDROID_TZDATA_ROOT=/apex/com.android.tzdata
|
2020-02-08 12:26:39 +01:00
|
|
|
local APEXRJPATH=/apex/com.android.runtime/javalib
|
|
|
|
local SYSFRAME=/system/framework
|
|
|
|
export BOOTCLASSPATH=\
|
|
|
|
$APEXRJPATH/core-oj.jar:$APEXRJPATH/core-libart.jar:$APEXRJPATH/okhttp.jar:\
|
|
|
|
$APEXRJPATH/bouncycastle.jar:$APEXRJPATH/apache-xml.jar:$SYSFRAME/framework.jar:\
|
|
|
|
$SYSFRAME/ext.jar:$SYSFRAME/telephony-common.jar:$SYSFRAME/voip-common.jar:\
|
|
|
|
$SYSFRAME/ims-common.jar:$SYSFRAME/android.test.base.jar:$SYSFRAME/telephony-ext.jar:\
|
|
|
|
/apex/com.android.conscrypt/javalib/conscrypt.jar:\
|
|
|
|
/apex/com.android.media/javalib/updatable-media.jar
|
2020-01-11 22:48:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
umount_apex() {
|
|
|
|
[ -d /apex ] || return
|
2020-02-08 12:26:39 +01:00
|
|
|
local DEST SRC
|
|
|
|
for DEST in /apex/*; do
|
|
|
|
[ "$DEST" = '/apex/*' ] && break
|
|
|
|
SRC=$(grep $DEST /proc/mounts | awk '{ print $1 }')
|
|
|
|
umount -l $DEST
|
|
|
|
# Detach loop device just in case
|
|
|
|
losetup -d $SRC 2>/dev/null
|
2020-01-11 22:48:21 +01:00
|
|
|
done
|
|
|
|
rm -rf /apex
|
|
|
|
unset ANDROID_RUNTIME_ROOT
|
|
|
|
unset ANDROID_TZDATA_ROOT
|
|
|
|
unset BOOTCLASSPATH
|
|
|
|
}
|
|
|
|
|
2018-06-17 19:40:56 +02:00
|
|
|
get_flags() {
|
|
|
|
# override variables
|
|
|
|
getvar KEEPVERITY
|
|
|
|
getvar KEEPFORCEENCRYPT
|
2018-12-24 18:08:46 +01:00
|
|
|
getvar RECOVERYMODE
|
2018-06-17 19:40:56 +02:00
|
|
|
if [ -z $KEEPVERITY ]; then
|
2018-08-29 06:40:14 +02:00
|
|
|
if $SYSTEM_ROOT; then
|
|
|
|
KEEPVERITY=true
|
2019-03-03 12:35:25 +01:00
|
|
|
ui_print "- System-as-root, keep dm/avb-verity"
|
2018-08-29 06:40:14 +02:00
|
|
|
else
|
|
|
|
KEEPVERITY=false
|
|
|
|
fi
|
2018-06-17 19:40:56 +02:00
|
|
|
fi
|
|
|
|
if [ -z $KEEPFORCEENCRYPT ]; then
|
2018-10-20 23:10:35 +02:00
|
|
|
grep ' /data ' /proc/mounts | grep -q 'dm-' && FDE=true || FDE=false
|
|
|
|
[ -d /data/unencrypted ] && FBE=true || FBE=false
|
|
|
|
# No data access means unable to decrypt in recovery
|
|
|
|
if $FDE || $FBE || ! $DATA; then
|
2018-06-17 19:40:56 +02:00
|
|
|
KEEPFORCEENCRYPT=true
|
2019-03-03 12:35:25 +01:00
|
|
|
ui_print "- Encrypted data, keep forceencrypt"
|
2018-06-17 19:40:56 +02:00
|
|
|
else
|
|
|
|
KEEPFORCEENCRYPT=false
|
|
|
|
fi
|
|
|
|
fi
|
2018-12-24 18:08:46 +01:00
|
|
|
[ -z $RECOVERYMODE ] && RECOVERYMODE=false
|
2018-06-17 19:40:56 +02:00
|
|
|
}
|
|
|
|
|
2018-06-20 19:37:08 +02:00
|
|
|
find_boot_image() {
|
|
|
|
BOOTIMAGE=
|
2019-03-30 05:49:48 +01:00
|
|
|
if $RECOVERYMODE; then
|
2020-01-11 22:48:21 +01:00
|
|
|
BOOTIMAGE=`find_block recovery_ramdisk$SLOT recovery sos`
|
2019-03-30 05:49:48 +01:00
|
|
|
elif [ ! -z $SLOT ]; then
|
2018-12-24 14:36:37 +01:00
|
|
|
BOOTIMAGE=`find_block ramdisk$SLOT recovery_ramdisk$SLOT boot$SLOT`
|
2018-06-20 19:37:08 +02:00
|
|
|
else
|
2019-04-05 21:18:39 +02:00
|
|
|
BOOTIMAGE=`find_block ramdisk recovery_ramdisk kern-a android_boot kernel boot lnx bootimg boot_a`
|
2018-06-20 19:37:08 +02:00
|
|
|
fi
|
2018-07-03 12:28:44 +02:00
|
|
|
if [ -z $BOOTIMAGE ]; then
|
|
|
|
# Lets see what fstabs tells me
|
|
|
|
BOOTIMAGE=`grep -v '#' /etc/*fstab* | grep -E '/boot[^a-zA-Z]' | grep -oE '/dev/[a-zA-Z0-9_./-]*' | head -n 1`
|
|
|
|
fi
|
2018-06-20 19:37:08 +02:00
|
|
|
}
|
|
|
|
|
2018-08-10 12:59:14 +02:00
|
|
|
flash_image() {
|
2017-09-27 18:54:01 +02:00
|
|
|
# Make sure all blocks are writable
|
2018-05-05 19:48:24 +02:00
|
|
|
$MAGISKBIN/magisk --unlock-blocks 2>/dev/null
|
2017-09-26 14:21:43 +02:00
|
|
|
case "$1" in
|
2019-03-08 00:07:23 +01:00
|
|
|
*.gz) CMD1="$MAGISKBIN/magiskboot decompress '$1' - 2>/dev/null";;
|
2019-02-11 23:14:07 +01:00
|
|
|
*) CMD1="cat '$1'";;
|
2017-09-26 14:21:43 +02:00
|
|
|
esac
|
2018-02-09 20:34:13 +01:00
|
|
|
if $BOOTSIGNED; then
|
2019-02-11 23:14:07 +01:00
|
|
|
CMD2="$BOOTSIGNER -sign"
|
2019-11-02 04:26:53 +01:00
|
|
|
ui_print "- Sign image with verity keys"
|
2018-02-09 20:34:13 +01:00
|
|
|
else
|
2019-02-11 23:14:07 +01:00
|
|
|
CMD2="cat -"
|
2018-08-10 12:59:14 +02:00
|
|
|
fi
|
|
|
|
if [ -b "$2" ]; then
|
2019-02-25 02:39:01 +01:00
|
|
|
local img_sz=`stat -c '%s' "$1"`
|
|
|
|
local blk_sz=`blockdev --getsize64 "$2"`
|
|
|
|
[ $img_sz -gt $blk_sz ] && return 1
|
2019-02-11 23:14:07 +01:00
|
|
|
eval $CMD1 | eval $CMD2 | cat - /dev/zero > "$2" 2>/dev/null
|
2018-08-10 12:59:14 +02:00
|
|
|
else
|
|
|
|
ui_print "- Not block device, storing image"
|
2019-02-11 23:14:07 +01:00
|
|
|
eval $CMD1 | eval $CMD2 > "$2" 2>/dev/null
|
2018-02-09 20:34:13 +01:00
|
|
|
fi
|
2018-08-11 09:56:12 +02:00
|
|
|
return 0
|
2017-09-06 10:13:23 +02:00
|
|
|
}
|
|
|
|
|
2020-01-01 07:02:44 +01:00
|
|
|
patch_dtb_partitions() {
|
|
|
|
local result=1
|
|
|
|
cd $MAGISKBIN
|
|
|
|
for name in dtb dtbo; do
|
|
|
|
local IMAGE=`find_block $name$SLOT`
|
|
|
|
if [ ! -z $IMAGE ]; then
|
|
|
|
ui_print "- $name image: $IMAGE"
|
|
|
|
if ./magiskboot dtb $IMAGE patch dt.patched; then
|
|
|
|
result=0
|
|
|
|
ui_print "- Backing up stock $name image"
|
|
|
|
cat $IMAGE > stock_${name}.img
|
|
|
|
ui_print "- Flashing patched $name"
|
|
|
|
cat dt.patched /dev/zero > $IMAGE
|
|
|
|
rm -f dt.patched
|
|
|
|
fi
|
2017-11-10 18:33:50 +01:00
|
|
|
fi
|
2020-01-01 07:02:44 +01:00
|
|
|
done
|
|
|
|
cd /
|
|
|
|
return $result
|
2017-11-10 18:33:50 +01:00
|
|
|
}
|
|
|
|
|
2019-12-27 10:53:27 +01:00
|
|
|
# Common installation script for flash_script.sh and addon.d.sh
|
2020-01-01 07:02:44 +01:00
|
|
|
install_magisk() {
|
2019-11-02 04:26:08 +01:00
|
|
|
cd $MAGISKBIN
|
|
|
|
|
2019-11-03 02:50:33 +01:00
|
|
|
eval $BOOTSIGNER -verify < $BOOTIMAGE && BOOTSIGNED=true
|
|
|
|
$BOOTSIGNED && ui_print "- Boot image is signed with AVB 1.0"
|
|
|
|
|
2019-11-02 04:26:08 +01:00
|
|
|
$IS64BIT && mv -f magiskinit64 magiskinit 2>/dev/null || rm -f magiskinit64
|
|
|
|
|
|
|
|
# Source the boot patcher
|
2020-01-01 07:02:44 +01:00
|
|
|
SOURCEDMODE=true
|
2019-11-02 04:26:08 +01:00
|
|
|
. ./boot_patch.sh "$BOOTIMAGE"
|
|
|
|
|
|
|
|
ui_print "- Flashing new boot image"
|
|
|
|
|
|
|
|
if ! flash_image new-boot.img "$BOOTIMAGE"; then
|
|
|
|
ui_print "- Compressing ramdisk to fit in partition"
|
|
|
|
./magiskboot cpio ramdisk.cpio compress
|
|
|
|
./magiskboot repack "$BOOTIMAGE"
|
|
|
|
flash_image new-boot.img "$BOOTIMAGE" || abort "! Insufficient partition size"
|
|
|
|
fi
|
|
|
|
|
|
|
|
./magiskboot cleanup
|
|
|
|
rm -f new-boot.img
|
|
|
|
|
2020-01-01 07:02:44 +01:00
|
|
|
patch_dtb_partitions
|
|
|
|
run_migrations
|
2019-11-02 04:26:08 +01:00
|
|
|
}
|
|
|
|
|
2017-09-06 10:13:23 +02:00
|
|
|
sign_chromeos() {
|
2017-10-07 16:08:10 +02:00
|
|
|
ui_print "- Signing ChromeOS boot image"
|
2017-09-06 10:13:23 +02:00
|
|
|
|
2017-10-07 16:08:10 +02:00
|
|
|
echo > empty
|
2018-05-05 19:48:24 +02:00
|
|
|
./chromeos/futility vbutil_kernel --pack new-boot.img.signed \
|
2017-09-06 10:13:23 +02:00
|
|
|
--keyblock ./chromeos/kernel.keyblock --signprivate ./chromeos/kernel_data_key.vbprivk \
|
|
|
|
--version 1 --vmlinuz new-boot.img --config empty --arch arm --bootloader empty --flags 0x1
|
|
|
|
|
|
|
|
rm -f empty new-boot.img
|
|
|
|
mv new-boot.img.signed new-boot.img
|
|
|
|
}
|
|
|
|
|
2017-06-18 18:15:44 +02:00
|
|
|
remove_system_su() {
|
|
|
|
if [ -f /system/bin/su -o -f /system/xbin/su ] && [ ! -f /su/bin/su ]; then
|
2018-08-29 04:03:12 +02:00
|
|
|
ui_print "- Removing system installed root"
|
2017-06-18 18:15:44 +02:00
|
|
|
mount -o rw,remount /system
|
|
|
|
# SuperSU
|
|
|
|
if [ -e /system/bin/.ext/.su ]; then
|
|
|
|
mv -f /system/bin/app_process32_original /system/bin/app_process32 2>/dev/null
|
|
|
|
mv -f /system/bin/app_process64_original /system/bin/app_process64 2>/dev/null
|
|
|
|
mv -f /system/bin/install-recovery_original.sh /system/bin/install-recovery.sh 2>/dev/null
|
|
|
|
cd /system/bin
|
|
|
|
if [ -e app_process64 ]; then
|
|
|
|
ln -sf app_process64 app_process
|
2019-02-12 07:48:33 +01:00
|
|
|
elif [ -e app_process32 ]; then
|
2017-06-18 18:15:44 +02:00
|
|
|
ln -sf app_process32 app_process
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
rm -rf /system/.pin /system/bin/.ext /system/etc/.installed_su_daemon /system/etc/.has_su_daemon \
|
|
|
|
/system/xbin/daemonsu /system/xbin/su /system/xbin/sugote /system/xbin/sugote-mksh /system/xbin/supolicy \
|
|
|
|
/system/bin/app_process_init /system/bin/su /cache/su /system/lib/libsupol.so /system/lib64/libsupol.so \
|
|
|
|
/system/su.d /system/etc/install-recovery.sh /system/etc/init.d/99SuperSUDaemon /cache/install-recovery.sh \
|
|
|
|
/system/.supersu /cache/.supersu /data/.supersu \
|
2020-01-11 22:48:21 +01:00
|
|
|
/system/app/Superuser.apk /system/app/SuperSU /cache/Superuser.apk
|
|
|
|
elif [ -f /cache/su.img -o -f /data/su.img -o -d /data/adb/su -o -d /data/su ]; then
|
|
|
|
ui_print "- Removing systemless installed root"
|
|
|
|
umount -l /su 2>/dev/null
|
|
|
|
rm -rf /cache/su.img /data/su.img /data/adb/su /data/adb/suhide /data/su /cache/.supersu /data/.supersu \
|
|
|
|
/cache/supersu_install /data/supersu_install
|
2017-06-18 18:15:44 +02:00
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2017-07-02 15:36:09 +02:00
|
|
|
api_level_arch_detect() {
|
|
|
|
API=`grep_prop ro.build.version.sdk`
|
|
|
|
ABI=`grep_prop ro.product.cpu.abi | cut -c-3`
|
|
|
|
ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3`
|
|
|
|
ABILONG=`grep_prop ro.product.cpu.abi`
|
|
|
|
|
|
|
|
ARCH=arm
|
2018-04-22 08:13:27 +02:00
|
|
|
ARCH32=arm
|
2017-07-02 15:36:09 +02:00
|
|
|
IS64BIT=false
|
2018-04-22 08:13:27 +02:00
|
|
|
if [ "$ABI" = "x86" ]; then ARCH=x86; ARCH32=x86; fi;
|
|
|
|
if [ "$ABI2" = "x86" ]; then ARCH=x86; ARCH32=x86; fi;
|
|
|
|
if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; ARCH32=arm; IS64BIT=true; fi;
|
|
|
|
if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; ARCH32=x86; IS64BIT=true; fi;
|
2017-07-02 15:36:09 +02:00
|
|
|
}
|
|
|
|
|
2018-06-26 16:41:03 +02:00
|
|
|
check_data() {
|
|
|
|
DATA=false
|
|
|
|
DATA_DE=false
|
|
|
|
if grep ' /data ' /proc/mounts | grep -vq 'tmpfs'; then
|
|
|
|
# Test if data is writable
|
|
|
|
touch /data/.rw && rm /data/.rw && DATA=true
|
|
|
|
# Test if DE storage is writable
|
|
|
|
$DATA && [ -d /data/adb ] && touch /data/adb/.rw && rm /data/adb/.rw && DATA_DE=true
|
|
|
|
fi
|
2019-02-11 23:14:07 +01:00
|
|
|
$DATA && NVBASE=/data || NVBASE=/cache/data_adb
|
|
|
|
$DATA_DE && NVBASE=/data/adb
|
|
|
|
resolve_vars
|
2018-06-26 16:41:03 +02:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
find_manager_apk() {
|
2019-11-02 04:26:08 +01:00
|
|
|
[ -z $APK ] && APK=/data/adb/magisk.apk
|
2019-02-11 23:14:07 +01:00
|
|
|
[ -f $APK ] || APK=/data/magisk/magisk.apk
|
|
|
|
[ -f $APK ] || APK=/data/app/com.topjohnwu.magisk*/*.apk
|
|
|
|
if [ ! -f $APK ]; then
|
2019-11-02 04:26:08 +01:00
|
|
|
DBAPK=`magisk --sqlite "SELECT value FROM strings WHERE key='requester'" 2>/dev/null | cut -d= -f2`
|
|
|
|
[ -z $DBAPK ] && DBAPK=`strings /data/adb/magisk.db | grep 5requester | cut -c11-`
|
|
|
|
[ -z $DBAPK ] || APK=/data/user_de/*/$DBAPK/dyn/*.apk
|
2019-11-02 05:41:51 +01:00
|
|
|
[ -f $APK ] || [ -z $DBAPK ] || APK=/data/app/$DBAPK*/*.apk
|
2017-08-12 10:44:58 +02:00
|
|
|
fi
|
2019-11-02 04:26:08 +01:00
|
|
|
[ -f $APK ] || ui_print "! Unable to detect Magisk Manager APK for BootSigner"
|
2017-07-02 15:36:09 +02:00
|
|
|
}
|
|
|
|
|
2020-01-01 07:02:44 +01:00
|
|
|
run_migrations() {
|
|
|
|
local LOCSHA1
|
|
|
|
local TARGET
|
|
|
|
# Legacy app installation
|
|
|
|
local BACKUP=/data/adb/magisk/stock_boot*.gz
|
|
|
|
if [ -f $BACKUP ]; then
|
|
|
|
cp $BACKUP /data
|
|
|
|
rm -f $BACKUP
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Legacy backup
|
|
|
|
for gz in /data/stock_boot*.gz; do
|
|
|
|
[ -f $gz ] || break
|
|
|
|
LOCSHA1=`basename $gz | sed -e 's/stock_boot_//' -e 's/.img.gz//'`
|
|
|
|
[ -z $LOCSHA1 ] && break
|
|
|
|
mkdir /data/magisk_backup_${LOCSHA1} 2>/dev/null
|
|
|
|
mv $gz /data/magisk_backup_${LOCSHA1}/boot.img.gz
|
|
|
|
done
|
|
|
|
|
|
|
|
# Stock backups
|
|
|
|
LOCSHA1=$SHA1
|
|
|
|
for name in boot dtb dtbo; do
|
|
|
|
BACKUP=/data/adb/magisk/stock_${name}.img
|
|
|
|
[ -f $BACKUP ] || continue
|
|
|
|
if [ $name = 'boot' ]; then
|
|
|
|
LOCSHA1=`$MAGISKBIN/magiskboot sha1 $BACKUP`
|
|
|
|
mkdir /data/magisk_backup_${LOCSHA1} 2>/dev/null
|
|
|
|
fi
|
|
|
|
TARGET=/data/magisk_backup_${LOCSHA1}/${name}.img
|
|
|
|
cp $BACKUP $TARGET
|
|
|
|
rm -f $BACKUP
|
|
|
|
gzip -9f $TARGET
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
2019-02-11 23:14:07 +01:00
|
|
|
#################
|
|
|
|
# Module Related
|
|
|
|
#################
|
2017-07-09 18:17:34 +02:00
|
|
|
|
|
|
|
set_perm() {
|
2018-02-09 20:34:13 +01:00
|
|
|
chown $2:$3 $1 || return 1
|
|
|
|
chmod $4 $1 || return 1
|
2019-02-12 08:14:57 +01:00
|
|
|
CON=$5
|
|
|
|
[ -z $CON ] && CON=u:object_r:system_file:s0
|
|
|
|
chcon $CON $1 || return 1
|
2017-07-09 18:17:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
set_perm_recursive() {
|
|
|
|
find $1 -type d 2>/dev/null | while read dir; do
|
|
|
|
set_perm $dir $2 $3 $4 $6
|
|
|
|
done
|
2017-07-30 21:03:52 +02:00
|
|
|
find $1 -type f -o -type l 2>/dev/null | while read file; do
|
2017-07-09 18:17:34 +02:00
|
|
|
set_perm $file $2 $3 $5 $6
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
mktouch() {
|
2017-07-30 21:03:52 +02:00
|
|
|
mkdir -p ${1%/*} 2>/dev/null
|
|
|
|
[ -z $2 ] && touch $1 || echo $2 > $1
|
2017-07-09 18:17:34 +02:00
|
|
|
chmod 644 $1
|
|
|
|
}
|
|
|
|
|
|
|
|
request_size_check() {
|
2019-02-12 08:14:57 +01:00
|
|
|
reqSizeM=`du -ms "$1" | cut -f1`
|
2017-07-09 18:17:34 +02:00
|
|
|
}
|
|
|
|
|
2017-08-12 17:15:39 +02:00
|
|
|
request_zip_size_check() {
|
2018-06-22 00:18:06 +02:00
|
|
|
reqSizeM=`unzip -l "$1" | tail -n 1 | awk '{ print int(($1 - 1) / 1048576 + 1) }'`
|
2017-08-12 17:15:39 +02:00
|
|
|
}
|
|
|
|
|
2019-02-24 08:11:11 +01:00
|
|
|
boot_actions() { return; }
|
2019-02-11 23:14:07 +01:00
|
|
|
|
2019-12-27 10:53:27 +01:00
|
|
|
##########
|
|
|
|
# Presets
|
|
|
|
##########
|
|
|
|
|
|
|
|
# Detect whether in boot mode
|
|
|
|
[ -z $BOOTMODE ] && ps | grep zygote | grep -qv grep && BOOTMODE=true
|
|
|
|
[ -z $BOOTMODE ] && ps -A 2>/dev/null | grep zygote | grep -qv grep && BOOTMODE=true
|
|
|
|
[ -z $BOOTMODE ] && BOOTMODE=false
|
|
|
|
|
|
|
|
MAGISKTMP=/sbin/.magisk
|
|
|
|
NVBASE=/data/adb
|
|
|
|
[ -z $TMPDIR ] && TMPDIR=/dev/tmp
|
|
|
|
|
|
|
|
# Bootsigner related stuff
|
|
|
|
BOOTSIGNERCLASS=a.a
|
2020-01-11 22:48:21 +01:00
|
|
|
BOOTSIGNER="/system/bin/dalvikvm -Xnoimage-dex2oat -cp \$APK \$BOOTSIGNERCLASS"
|
2019-12-27 10:53:27 +01:00
|
|
|
BOOTSIGNED=false
|
2019-02-11 23:14:07 +01:00
|
|
|
|
|
|
|
resolve_vars
|