#!/bin/bash
#
# Simple Linux shell script to patch the boot partition with Magisk on a rooted phone with installed Magisk using fastboot, adb, and TWRP
#
# History
#   11.06.2022 1.0.0.0 /bs
#     inital release
#
#   03.07.2022 1.1.0.0 /bs
#     the script now uses /tmp for temporary files if /sdcard/Download is not available
#
#
#H# Usage
#H# 
#H#    install_magisk_via_twrp.sh [boot_slot] [dd|fastboot] [twrp_image]
#H#
#H# All parameter are optional
#H#
#H# The parameter "boot_slot" can be a, b, active, inactive, next, current; default is the current boot slot of the phone
#H#
#H# Use the parameter "dd" to request repatching via dd in an adb session ; use the parameter "fastboot" to request repatching via "fastboot"
#H# Default is to use "fastboot" to flash the patched boot image
#H#
#H# The parameter "twrp_image" can be used to define another TWRP image to use. The parameter is optional - the 
#H# default for "twrp_image" is hardcoded in the script (variable TWRP_IMAGE)
#H# The default TWRP image of the script is the TWRP for the ASUS Zenfone 8.
#H#
#H# The phone to patch must be attached via USB. 
#H# The phone can be either in fastboot mode, in normal mode with enabled adb support, or already booted from the TWRP image 
#H#
#H# 
#H# To change some of the values used by the script you can set environment variables before starting the script:
#H#
#H#   Set the environment variable REBOOT to "yes" before starting the script to automatically reboot the phone after patching the new image
#H#   Set the environment variable REBOOT to "no" before starting the script to disable the automatic reboot after patching the new image.
#H#
#H#   Set the environment variable SERIAL_NUMBER to the serial number of the phone to patch if there is more then one phone connected via USB
#H#
#H#   Set the environment variable ADB_OPTIONS to the options to be used with the adb command
#H#
#H#   Set the environment variable FASTBOOT_OPTIONS to the options to be used with the fastboot command
#H#
#H#   Set the environment variable DOWNLOAD_DIR_ON_PHONE to the data directory to use on the phone (def.: /sdcard/Download)
#H#
#
#
# Author
#   Bernd.Schemmer (at) gmx.de
#   Homepage: http://bnsmb.de/
#
#
# Prerequisites
#   a computer running Linux with working adb and fastboot binaries available via PATH variable
#   a phone with installed Magisk and unlocked boot loader
#     Magisk must be used one time to patch a boot partition image file to create the neccessary scripts and binaries used by this script on the phone
#   a working recovery image (e.g. TWRP) for the attached phone that automatically mounts /data and has enabled adb support 
#
# Test Environment
#   Tested on an ASUS Zenfone 8 and with 
#     - OmniROM 12 (Android 12) and Magisk v24.3
#     - OmniROM 12 (Android 12) and Magisk v25.0
#     - AospExtended 9.x w/o GAPPS (Android 12) and Magisk v24.3
#     - AospExtended 9.x w/o GAPPS (Android 12) and Magisk v25.0
#     - ASUS Original Android 11 and Magisk v24.3
#     - ASUS Original Android 12 and Magisk v24.3
#     - ASUS Original Android 13 Beta 1 and Magisk v25.0
#
#
# Details
#
#   The patched boot images will be created in the directory "/sdcard/Downloads" on the phone (variable DOWNLOAD_DIR_ON_PHONE)
#
#   The script will use the directory /tmp for the boot images if the directory /sdcard/Downloads is not available
#     Note that /tmp is mounted on a ramdisk and the files in that directory will not survive a reboot
#
#   The script uses the original script called "boot_patch.sh" from Magisk to patch the boot image.
#
#   You can execute the script as often as you like.
#
#   The script will not delete the created files in the directory "/sdcard/Download" on the phone so you might do a cleanup of that directory manual
#
#   If the check sum of the boot image before the patching is equal to the check sum after the successfull patching then Magisk was already installed in the boot partition
#
#   The script will boot the phone up to 4 times.
#
# Notes [as of 06.06.2022]
#
#   For the ROMs based on Android 12 for the Asus Zenfone 8 the TWRP version 3.6.1_12 or newer is required .
#   Enter "/get working_twrp_for_a12" in the Telegram group  "OminiROM-zenfone8" to get the download link for that version.
#   The official TWRP images from https://twrp.me/asus/zenfone8.html can not mount the filesystem for /data (at least I did not get that working with these TWRP versions ...)
#
#
# Trouble Shooting
#
#   - Error message like this
#
#       /data/adb/magisk/boot_patch.sh[211]: can't create /proc/self/fd/: Is a directory
#
#     can be ignored (these are only error messages from the function to print some additional messages)
#
#   - Patching the boot partition via "dd" fails sometimes for unknown reason so you should only use it if you know how to fix a damaged boot partition!
#
#   - Downloading the patched boot image via "adb pull" ((neccessary for patching the boot partition using fastboot) sometimes fails for unknown reason:
#
#       So if you get an error message like this:
#
#       [ 77%] /sdcard/Download/patched_boot_a.391985.img
#       ERROR: Error downloading the file "/sdcard/Download/patched_boot_a.391985.img" from the phone!
#
#       just restart the script again (or download the file with the patched boot image and flash the boot partition manually)
#
#   - If the adb connection dies and there are error messages like this
#
#       adb: insufficient permissions for device
#
#     restart the adb server using
#
#       adb kill-server
#
#     if that does not work disconnect and reconnect the USB cable 
# 

SCRIPT_VERSION="1.1.0.0"

#
# for testing only
#
# PREFIX="echo"
PREFIX=""

#
# define constants
#
__TRUE=0
__FALSE=1

# Script return code
#
THISRC=${__TRUE}

# ---------------------------------------------------------------------
# init some global variables
#

# default TWRP image to use
#
TWRP_IMAGE="/data/backup/ASUS_ZENFONE8/twrp/twrp-3.6.1_12-1-I006D.img"

# name of the patch script from Magisk
#
MAGISK_BOOT_PATCH_SCRIPT_NAME="boot_patch.sh"

# directory used by Magisk for binaries, scripts, modules, etc
#
MAGISK_DATA_DIRECTORY="//data/adb/magisk"

# fully qualified name of the patch script from Magisk on the Phone
# (for details see the code to check if the script exists below)
#
MAGISK_BOOT_PATCH_SCRIPT="${MAGISK_DATA_DIRECTORY}/${MAGISK_BOOT_PATCH_SCRIPT_NAME}"

# the directory used for creating the image files on the phone
#
DOWNLOAD_DIR_ON_PHONE="${DOWNLOAD_DIR_ON_PHONE:=/sdcard/Download}"

FALLBACK_DOWNLOAD_DIR_ON_PHONE="${FALLBACK_DOWNLOAD_DIR_ON_PHONE:=/tmp}"

# general options for the adb command (-d : only use devices connected via USB)
#
ADB_OPTIONS="${ADB_OPTIONS:=-d}"

# general options for the fastboot command
#
FASTBOOT_OPTIONS="${FASTBOOT_OPTIONS:=}"

# The default for the boot slot that should be patched
#
CURRENT_BOOT_SLOT="active"

#
# new image created by the patch script from Magisk (the patch script from Magisk will create
# the new image in the directory with the patch script)
#
NEW_BOOT_IMG="${MAGISK_DATA_DIRECTORY}/new-boot.img"

NEW_BOOT_IMG_BACKUP="${NEW_BOOT_IMG}.$$"

# if this variable is ${__TRUE} the script uses fastboot to flash the boot partition with the patched boot image
# if this variable is ${__FALSE} the script uses dd in an adb session to write the patched boot image to the boot partition
#
USE_FASTBOOT_TO_FLASH_THE_BOOT_PARTITION=${__TRUE}

# ---------------------------------------------------------------------
# functions
#

# ----------------------------------------------------------------------
# die
#
# function: print a message and end the script
#
# usage: die [script_exit_code] [message]
#
# the parameter "message" is optional; the script will add a leading "ERROR: " 
# to the message if the script_exit_code is not zero
#
# returns: n/a
#
function die  {
  typeset THISRC=$1
  [ $# -ne 0 ] && shift
  typeset THISMSG="$*"

  if [ ${THISRC} != 0 ] ; then
    echo "ERROR: ${THISMSG}!" >&2
  else
    echo "${THISMSG}"
  fi
  exit ${THISRC}
}


# ----------------------------------------------------------------------
# isNumber
#
# function: check if a value is an integer
#
# usage: isNumber testValue
#
# returns: ${__TRUE} - testValue is a number else not
#
function isNumber {
  typeset __FUNCTION="isNumber"
  ${__DEBUG_CODE}
  ${__FUNCTION_INIT}
	
  typeset THISRC=${__FALSE}

  [[ $1 == +([0-9]) ]] && THISRC=${__TRUE} || THISRC=${__FALSE}

  return ${THISRC}
}


# ----------------------------------------------------------------------
# wait_for_phone_to_be_in_fastboot_mode
#
# function: wait up to n seconds for a phone with in fastboot mode
#
# usage: wait_for_phone_to_be_in_fastboot_mode [timeout_value_in_seconds]
#
# returns: ${__TRUE}  - found a phone in fastboot mode
#          ${__FALSE} - no phone in fastboot mode found
#
function wait_for_phone_to_be_in_fastboot_mode {
#
# the values below are seconds
#	
  typeset MAX_WAIT_TIME=60

  typeset THISRC=${__TRUE}

  if [ "$1"x != ""x ] ;then
    isNumber $1 && MAX_WAIT_TIME=$1
  fi
    
  echo "Waiting up to ${MAX_WAIT_TIME} seconds for the boot into the fastboot mode ..."

#  echo "[$( date "+%Y.%m.%d %H:%M:%S")] "
  
  CUR_FASTBOOT_VARIABLES="$( ${SUDO_PREFIX} timeout ${MAX_WAIT_TIME} fastboot ${FASTBOOT_OPTIONS} getvar all 2>&1 )"
  [ $? -eq 0 ] && THISRC=${__TRUE} || THISRC=${__FALSE}

#  echo "[$( date "+%Y.%m.%d %H:%M:%S")] "

  return ${THISRC}
}


# ----------------------------------------------------------------------
# wait_for_phone_with_a_working_adb_connection
#
# function: wait up to n seconds for a phone with a working adb connection
#
# usage: wait_for_phone_with_a_working_adb_connection [timeout_value_in_seconds]
#
# returns: ${__TRUE}  - found a phone with a working adb connection
#          ${__FALSE} - no phone with working adb connection found
#
function wait_for_phone_with_a_working_adb_connection {
#
# the values below are seconds
#	
  typeset MAX_WAIT_TIME=60
  typeset SECONDS=0
  typeset INTERVALL=5
    
  typeset THISRC=${__FALSE}

  if [ "$1"x != ""x ] ;then
    isNumber $1 && MAX_WAIT_TIME=$1
  fi
  
#  echo "[$( date "+%Y.%m.%d %H:%M:%S")] "
  
  printf "Waiting up to ${MAX_WAIT_TIME} seconds for the boot of the phone "

  while [ ${SECONDS} -lt ${MAX_WAIT_TIME} ] ; do
    CUR_PHONE_PROPERTIES="$( adb ${ADB_OPTIONS} shell getprop  all 2>&1 )"
    if [ $? -eq 0 ] ; then
      THISRC=${__TRUE} 
      break
    fi
    printf "."
    sleep ${INTERVALL}
    (( SECONDS = SECONDS + INTERVALL ))
  done
  printf "\n"
   
#  echo "[$( date "+%Y.%m.%d %H:%M:%S")] "
      
  return ${THISRC}
}

# ----------------------------------------------------------------------
# wait_some_seconds
#
# function: wait n seconds
#
# usage: wait_some_seconds [number_of_seconds]
#
# returns: ${__TRUE}  - waited n seconds
#          ${__FALSE} - no parameter found, to many parameter found,
#                       or the parameter is not a number
#
function wait_some_seconds {
  typeset THISRC=${__FALSE}

  typeset WAIT_TIME_IN_SECONDS="$1"
  
  if [ $# -eq 1 ] ; then
    if isNumber ${WAIT_TIME_IN_SECONDS} ; then
      echo "Waiting now ${WAIT_TIME_IN_SECONDS} seconds ..."
      sleep ${WAIT_TIME_IN_SECONDS}
      THISRC=${__TRUE}
    fi
  fi
      
  return ${THISRC}
}

# ---------------------------------------------------------------------
# main function
#

echo "$0 version - ${SCRIPT_VERSION} - add Magisk to the boot partition of a phone running Android using TWRP"
echo ""

if [ "$1"x = "-h"x -o "$1"x = "--help"x -o $# -gt 2 ] ; then

#
# extract the usage help from the script source
#
  grep "^#H#" $0 | cut -c4-
  
  echo ""
  echo " The default TWRP image to use is \"${TWRP_IMAGE}\" "
  echo ""
  exit 1
fi

#
# process the parameter for the slot to use (if any)
#
if [ $# -ge 1 ] ; then
  case $1 in
    a | slot_a | _a )
      CURRENT_BOOT_SLOT="_a"
      shift
    ;;

    b | slot_b  | _b )
      CURRENT_BOOT_SLOT="_b"
      shift
    ;;

    active | current )
      CURRENT_BOOT_SLOT="active"
      shift
    ;;

    inactive | next )
      CURRENT_BOOT_SLOT="inactive"
      shift
    ;;
    
  esac
fi

# process the parameter for how to patch the boot partition (if any)
#
if [ $# -ge 1 ] ; then
  case $1 in
    dd )
      USE_FASTBOOT_TO_FLASH_THE_BOOT_PARTITION=${__FALSE}    
      shift
      ;;
    
    fastboot )
      USE_FASTBOOT_TO_FLASH_THE_BOOT_PARTITION=${__TRUE}    
      shift
      ;;
  esac
fi


# process the parameter for the TWRP image to use (if any)
#
if [ $# -eq 1 ] ; then
  TWRP_IMAGE="$1"
  echo "Using the TWRP image found in the parameter: \"${TWRP_IMAGE}\" "
else
  echo "Using the TWRP image hardcoded in the script: \"${TWRP_IMAGE}\" "
fi

[ ! -r "${TWRP_IMAGE}" ] && die 5 "TWRP image \"${TWRP_IMAGE}\" not found"

ERRORS_FOUND=${__FALSE}

echo "Checking the script prerquisites ..."

if [ ${USE_FASTBOOT_TO_FLASH_THE_BOOT_PARTITION} = ${__TRUE} ] ; then
#
# if using fastboot to flash the boot image we must download the new boot image 
# file from the phone. This will be done in the current directory of the PC
#
# check if we can write to the current directory
#
  echo "Checking if we have write access for the current working directory \"${PWD}\"  ..."

  touch $PWD/xxx.$$ 
  if [ $? -eq 0 ] ; then
    \rm ${PWD}/xxx.$$ 2>/dev/null
  else
    echo "ERROR: Can not write to the current working directory \"${PWD}\" "
    ERRORS_FOUND=${__TRUE}
  fi
fi

for CUR_PROG in adb fastboot timeout cksum ; do
  EXECUTABLE="$( which "${CUR_PROG}" )"
  if [ "${EXECUTABLE}"x = ""x ] ; then
    echo "ERROR: The executable \"${CUR_PROG}\" is not available via the PATH"
    ERRORS_FOUND=${__TRUE}
  fi
done

if [ ${ERRORS_FOUND} = ${__TRUE} ] ; then
  die 7 "One or more errors found in the prerequisite checks"
fi

#
# fastboot must be executed by the user root -> use sudo if the script is executed by a non-root user
#
CUR_USER="$( whoami )"
if [ "${CUR_USER}"x != "root"x ] ; then
  SUDO_PREFIX="sudo"
  echo "The script is running as user \"${CUR_USER}\" -- will use \"${SUDO_PREFIX}\" for the fastboot commands ..."
else  
  SUDO_PREFIX=""
fi


# 
# check if the variable SERIAL_NUMBER is used
#
if [ "${SERIAL_NUMBER}"x != ""x ] ; then
  echo "Will patch the boot partition on the phone with the serial number found in the environment variable SERIAL_NUMBER: \"${SERIAL_NUMBER}\""
  ADB_OPTIONS="${ADB_OPTIONS} -s ${SERIAL_NUMBER} "
  FASTBOOT_OPTIONS="${FASTBOOT_OPTIONS} -s ${SERIAL_NUMBER} "
else
#
# check if there is more then one phone connected via USB
#
  ADB_DEVICES="$( adb ${ADB_OPTIONS} devices | tail -n +2 | grep -v ":" )"
  NO_OF_ADB_DEVICES=$( echo "${ADB_DEVICES}" | wc -l )

  if [ ${NO_OF_ADB_DEVICES} -gt 1 ] ; then
    echo "Found multiple phones connected via USB:"
    echo ""
    echo "${ADB_DEVICES}"
    echo  ""
    echo "ERROR: There are more than one phones connected via USB"
    echo "       Please select a phone to update by setting the variable SERIAL_NUMBER to the serial number of the phone that should be patched before executing this script"
    die 9 "To many phones connected"
  else
    SERIAL_NUMBER="$( echo "${ADB_DEVICES}" | awk '{ print $1}' )" 
    echo "Will patch the boot partition on the attached phone with the serial number \"${SERIAL_NUMBER}\""

    ADB_OPTIONS="${ADB_OPTIONS} -s ${SERIAL_NUMBER} "
    FASTBOOT_OPTIONS="${FASTBOOT_OPTIONS} -s ${SERIAL_NUMBER} "

  fi
fi


echo "Using the options \"${ADB_OPTIONS}\" for the adb commands "
echo "Using the options \"${FASTBOOT_OPTIONS}\" for the fastboot commands "

# Check if the phone is already booted in fastboot mode
#

echo "Checking for a connected phone booted into fastboot mode ..."

CUR_FASTBOOT_VARIABLES="$( ${SUDO_PREFIX} timeout 3 fastboot ${FASTBOOT_OPTIONS} getvar all 2>&1 )"
if [ $? -eq 0 ] ; then
  echo "The attached phone is already booted into the fastboot mode"
else
  echo "No attached phone in fastboot mode found"

  echo "Checking for an attached phone with working access via adb (USB) ..."

  adb ${ADB_OPTIONS} shell uname -a || die 11 "Can not access the phone - neither via fastboot nor via adb"

  echo ".. found a phone connected via USB with working adb access"

#
# check if the phone is already booted from the TWRP image
#  
  TWRP_STATUS="$( adb ${ADB_OPTIONS} shell getprop  ro.twrp.boot )"
  
  if [ "${TWRP_STATUS}"x = "1"x ] ; then
    TWRP_BOOT_IMAGE="$( adb ${ADB_OPTIONS} shell getprop  ro.product.bootimage.name )"
    TWRP_BOOT_IMAGE_VERSION="$( adb ${ADB_OPTIONS} shell getprop  ro.twrp.version )"
  
    echo "The phone is already booted from a TWRP image: \"${TWRP_BOOT_IMAGE}\" version \"${TWRP_BOOT_IMAGE_VERSION}\" "
  else
#
# the phone is booted in normal mode
#  
    echo "The phone is booted in normal mode"
    OS_SOFTWARE_VERSION="$( adb ${ADB_OPTIONS} shell getprop  ro.build.software.version )"
    [ "${OS_SOFTWARE_VERSION}"x = ""x ] && OS_SOFTWARE_VERSION="$( adb ${ADB_OPTIONS} shell getprop  ro.build.date )"
    
    OS_VERSION="$( adb ${ADB_OPTIONS} shell getprop  ro.build.version.release )"
    OS_DESC="$( adb ${ADB_OPTIONS} shell getprop  ro.build.description )"
    
    INSTALLED_MAGISK_VERSION="$(  adb ${ADB_OPTIONS} shell pm  list  packages --show-versioncode     com.topjohnwu.magisk  2>/dev/null  | cut -f2- -d":" | tr ":" " " )"
    
    echo "The installed OS is based on Android ${OS_VERSION} (${OS_SOFTWARE_VERSION}); the description for the distribution is \"${OS_DESC}\" "
    if [ "${INSTALLED_MAGISK_VERSION}"x = ""x ] ; then
      echo "WARNING: Can not detect the version of the installed Magisk"
    else
      echo "The installed version of Magisk is ${INSTALLED_MAGISK_VERSION} "
    fi

    echo "Booting the phone into the fastboot mode now ..."

    adb ${ADB_OPTIONS} reboot bootloader

    wait_for_phone_to_be_in_fastboot_mode || die 13 "Booting the phone into the bootloader failed - Giving up..."
  fi
fi

if [ "${TWRP_STATUS}"x != "1"x ] ; then

  echo "Booting the phone from the TWRP image \"${TWRP_IMAGE}\" now  ..."

  ${SUDO_PREFIX} fastboot ${FASTBOOT_OPTIONS} boot "${TWRP_IMAGE}"

  wait_for_phone_with_a_working_adb_connection || die 15 "Booting the phone from the TWRP image failed - Giving up..."
fi


echo "Retrieving the current boot slot from the phone ..."

ACTIVE_BOOT_SLOT="$( adb ${ADB_OPTIONS} shell getprop ro.boot.slot_suffix )"

if [ "${ACTIVE_BOOT_SLOT}"x = ""x ] ; then
  echo "No slot property found - seems the phone does not support the A/B partition scheme"
  CURRENT_BOOT_SLOT=""
else
  echo "The current boot slot is \"${ACTIVE_BOOT_SLOT}\" "  
fi

if [ "${CURRENT_BOOT_SLOT}"x = "_a"x -o "${CURRENT_BOOT_SLOT}"x = "_b"x ] ; then
  echo "Using the boot partition for the slot found in the parameter: ${CURRENT_BOOT_SLOT}"
else  

  if [ "${ACTIVE_BOOT_SLOT}"x != ""x ] ; then
    if [ "${CURRENT_BOOT_SLOT}"x = "active"x ] ; then
      CURRENT_BOOT_SLOT="${ACTIVE_BOOT_SLOT}"
    elif [ "${CURRENT_BOOT_SLOT}"x = "inactive"x ] ; then
      if [ "${ACTIVE_BOOT_SLOT}"x = "_a"x ] ; then
        CURRENT_BOOT_SLOT="_b"
      else
        CURRENT_BOOT_SLOT="_a"
      fi
    fi
  fi

  if [ "${CURRENT_BOOT_SLOT}"x != ""x ] ; then
    echo "The boot slot to patch is \"${CURRENT_BOOT_SLOT}\" "  
  fi

fi

[ "${VERBOSE}"x != ""x ] && set -x

CURRENT_BOOT_PARTITION_NAME="boot${CURRENT_BOOT_SLOT}"
CURRENT_BOOT_PARTITION="/dev/block/by-name/${CURRENT_BOOT_PARTITION_NAME}"

[ "${VERBOSE}"x != ""x ] && set +x

echo "The boot partition to patch is \"${CURRENT_BOOT_PARTITION_NAME}\" "

echo "Checking if the Magisk patch script \"${MAGISK_BOOT_PATCH_SCRIPT_NAME}\" exists on the phone ...."

adb ${ADB_OPTIONS} shell ls -l "${MAGISK_BOOT_PATCH_SCRIPT}"
if [ $? -ne 0 ] ; then
  echo "INFO: The script \"${MAGISK_BOOT_PATCH_SCRIPT}\" does not yet exist (=> Magisk was never installed in the boot partition on this phone before after the last factory reset)"
  echo "Searching the script \"${MAGISK_BOOT_PATCH_SCRIPT_NAME}\" now in the other directories in \"/data\" ..."

  ALTERNATE_PATCH_SCRIPT="$( adb ${ADB_OPTIONS} shell find /data -name "${MAGISK_BOOT_PATCH_SCRIPT_NAME}" 2>/dev/null | tail -1 )"
  if [  "${ALTERNATE_PATCH_SCRIPT}"x = ""x ] ; then
    echo "WARNING: No patch script found"
    echo ""
    echo "Will now create an image of the boot partition \"${CURRENT_BOOT_PARTITION}\" in \"${CURRENT_BOOT_IMAGE_FILE}\" that can be used in Magisk for patching "
    
    echo "  (to create the neccessary dirs and scripts used by this script ; this is a one time task)"
    adb ${ADB_OPTIONS} shell dd if=${CURRENT_BOOT_PARTITION} of=${CURRENT_BOOT_IMAGE_FILE}
    echo "The results are:"
    adb ${ADB_OPTIONS} shell  ls -l "${CURRENT_BOOT_IMAGE_FILE}"
    echo "The check sums are:"
    adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_PARTITION}" "${CURRENT_BOOT_IMAGE_FILE}" 
    echo ""
    die 17 "Patch boot script not found on the attached phone"
  else
    MAGISK_SCRIPT_DIR="${ALTERNATE_PATCH_SCRIPT%/*}"

    echo "Found the file \"${MAGISK_BOOT_PATCH_SCRIPT_NAME}\" in the directory \"${MAGISK_SCRIPT_DIR}\" "
    adb ${ADB_OPTIONS} shell ls -l "${MAGISK_SCRIPT_DIR}"

    adb ${ADB_OPTIONS} ls "${MAGISK_SCRIPT_DIR}/magiskboot" 2>/dev/null >/dev/null
    if [ $? -ne 0 ] ; then    
      die 19 "The directory \"${MAGISK_SCRIPT_DIR}\" seems not to be a valid Magisk directory"
    else
      MAGISK_BOOT_PATCH_SCRIPT="${ALTERNATE_PATCH_SCRIPT}"
      
      NEW_BOOT_IMG="${MAGISK_SCRIPT_DIR}/new-boot.img"
      NEW_BOOT_IMG_BACKUP="${NEW_BOOT_IMG}.$$"

      echo "Using the script \"${MAGISK_BOOT_PATCH_SCRIPT}\" to patch the boot image"
      
    fi
  fi
fi
  
echo "Checking if the download directory \"${DOWNLOAD_DIR_ON_PHONE}\" exists on the phone ...."

adb ${ADB_OPTIONS} shell ls -d "${DOWNLOAD_DIR_ON_PHONE}" 

if [ $? -ne 0 ] ; then
  echo "WARNING: Directory \"${DOWNLOAD_DIR_ON_PHONE}\"  not found on the phone ."
  echo "Checking if the download directory \"${FALLBACK_DOWNLOAD_DIR_ON_PHONE}\" exists on the phone ...."
  adb ${ADB_OPTIONS} shell ls -d "${FALLBACK_DOWNLOAD_DIR_ON_PHONE}" || die 21 "Directory \"${FALLBACK_DOWNLOAD_DIR_ON_PHONE}\" not found on the attached phone"
  DOWNLOAD_DIR_ON_PHONE="${FALLBACK_DOWNLOAD_DIR_ON_PHONE}"
fi

CURRENT_BOOT_IMAGE_FILE="${DOWNLOAD_DIR_ON_PHONE}/${CURRENT_BOOT_PARTITION_NAME}.$$.img"
CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME="patched_${CURRENT_BOOT_PARTITION_NAME}.$$.img"
CURRENT_PATCHED_BOOT_IMAGE_FILE="${DOWNLOAD_DIR_ON_PHONE}/${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}"


echo "Creating the boot image file \"${CURRENT_BOOT_IMAGE_FILE}\" from the partition \"${CURRENT_BOOT_PARTITION}\" ..."

adb ${ADB_OPTIONS} shell dd if="${CURRENT_BOOT_PARTITION}" of="${CURRENT_BOOT_IMAGE_FILE}" || die 23 "Error creating the image file \"${CURRENT_BOOT_IMAGE_FILE}\" "

echo ""
echo "Checking the result ..."
adb ${ADB_OPTIONS} shell ls -l "${CURRENT_BOOT_IMAGE_FILE}" || die 25 "Something went wrong creating the imaage file \"${CURRENT_BOOT_IMAGE_FILE}\" "


BOOT_PARTITION_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_PARTITION}" | cut -f1 -d " " )"
BOOT_PARTITION_IMG_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_IMAGE_FILE}" | cut -f1 -d " " )"
  
# adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_PARTITION}" "${CURRENT_BOOT_IMAGE_FILE}"

echo "The check sums are:"
echo "The check sum of the boot partition \"${CURRENT_BOOT_PARTITION}\" on the phohe is             \"${BOOT_PARTITION_CHKSUM}\" "
echo "The check sum of th boot image file on the phone is \"${CURRENT_BOOT_IMAGE_FILE}\" is \"${BOOT_PARTITION_IMG_CHKSUM}\"   "
   
if [ "${BOOT_PARTITION_CHKSUM}"x != "${BOOT_PARTITION_IMG_CHKSUM}"x ] ; then
  die 248 "Error creating the image file \"${CURRENT_BOOT_IMAGE_FILE}\" from the boot partition \"${CURRENT_BOOT_PARTITION}\" on the phone (the check sums do not match)"
fi
 
 #
# rename an existing patched image created by Magisk
#
adb ${ADB_OPTIONS} shell ls  "${NEW_BOOT_IMG}" 2>/dev/null >/dev/null 
if [ $? -eq 0 ] ; then
  echo "Renaming the file \"${NEW_BOOT_IMG}\" to \"${NEW_BOOT_IMG_BACKUP}\" ..."
  adb ${ADB_OPTIONS} shell mv "${NEW_BOOT_IMG}" "${NEW_BOOT_IMG_BACKUP}" || die 27 "Error renaming the file \"${NEW_BOOT_IMG}\" to \"${NEW_BOOT_IMG_BACKUP}\" "
fi

echo "Patching the boot image file \"${CURRENT_BOOT_IMAGE_FILE}\"  ..."
echo ""
echo "Note: The error message \"can't create /proc/self/fd/: Is a directory\" can be ignored"
echo ""

adb ${ADB_OPTIONS} shell "${MAGISK_BOOT_PATCH_SCRIPT}" "${CURRENT_BOOT_IMAGE_FILE}" || die 29 "Error patching the boot image file \"${CURRENT_BOOT_IMAGE_FILE}\" "

echo "Checking the result ..."

adb ${ADB_OPTIONS} shell ls -l "${NEW_BOOT_IMG}" || die 31 "Something went wrong creating the patched imaage file \"${NEW_BOOT_IMG}\" "

adb ${ADB_OPTIONS} shell mv "${NEW_BOOT_IMG}" "${CURRENT_PATCHED_BOOT_IMAGE_FILE}" || die 33 "Error creating the boot image file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" "
echo "The patched boot image is \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" "

if [ ${USE_FASTBOOT_TO_FLASH_THE_BOOT_PARTITION} = ${__FALSE} ] ; then

  # Note: The dd command does not work without this little pause (don't ask me why ...)
  wait_some_seconds 5

  echo "Patching the partition \"${CURRENT_BOOT_PARTITION}\" from the patched boot image file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" via dd ..."

  CUR_OUTPUT="$( exec 2>&1 ; ${PREFIX}  adb ${ADB_OPTIONS} shell dd  if="${CURRENT_PATCHED_BOOT_IMAGE_FILE}" of="${CURRENT_BOOT_PARTITION}" || die 35 "Error patching the patched image file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" to \"${CURRENT_BOOT_PARTITION}\" " )"
  echo "${CUR_OUTPUT}"

  if [ "${CUR_OUTPUT}"x = ""x ] ; then
    echo "WARNING: It looks like patching the \"${CURRENT_BOOT_PARTITION}\" via dd failed"
  fi
  
  echo "Checking the result ...."
  
  DEV_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_PARTITION}" | cut -f1 -d " " )"
  ORIGINAL_IMG_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_IMAGE_FILE}" | cut -f1 -d " " )"
  PATCHED_IMG_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_PATCHED_BOOT_IMAGE_FILE}" | cut -f1 -d " " )"
  
  echo ""
  echo "The check sums for the images and devices on the phone are:"
  echo ""
  adb ${ADB_OPTIONS} shell cksum "${CURRENT_BOOT_IMAGE_FILE}" "${CURRENT_PATCHED_BOOT_IMAGE_FILE}" "${CURRENT_BOOT_PARTITION}"
  echo ""

  if [ "${DEV_CHKSUM}"x = ""x -o "${PATCHED_IMG_CHKSUM}"x = ""x -o "${ORIGINAL_IMG_CHKSUM}"x = ""x ] ; then
    echo "ERROR : Something went terrible wrong -- please connect via \"adb shell\" and check and correct the error"
    die 249
  elif [ "${DEV_CHKSUM}"x = "${PATCHED_IMG_CHKSUM}"x ] ; then
    echo "OK, patching the boot partition \"${CURRENT_BOOT_PARTITION}\" was successfull"
  elif [ "${DEV_CHKSUM}"x = "${ORIGINAL_IMG_CHKSUM}"x ] ; then
    echo "ERROR: The patching was NOT successfull -- the boot partition \"${CURRENT_BOOT_PARTITION}\" did not change"
  else
    echo "ERROR: The patching of the boot partition \"${CURRENT_BOOT_PARTITION}\" failed !"
    echo "  
Most probably the phone will NOT boot now

To fix it connect via adb to the phone

  abb shell

and do 

# either restore the original boot partition

  dd if=\"${CURRENT_BOOT_IMAGE_FILE}\" of=\"${CURRENT_BOOT_PARTITION}\"

# or install the patched boot partition manual

  dd if=\"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" of=\"${CURRENT_BOOT_PARTITION}\"

"
    REBOOT_COMMAND="adb"
    die 251 "The patching of the boot partition \"${CURRENT_BOOT_PARTITION}\" was NOT successfull"
  fi
else

  wait_some_seconds 5

  echo "Patching the partition \"${CURRENT_BOOT_PARTITION}\" from the patched boot image file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" via fastboot ..."
  
  echo "Downloading the patched boot image \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" from the phone ..."
  cd /tmp && adb ${ADB_OPTIONS} pull "${CURRENT_PATCHED_BOOT_IMAGE_FILE}" || die 37 "Error downloading the file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" from the phone"
  
                 
  PATCHED_IMG_CHKSUM="$( adb ${ADB_OPTIONS} shell cksum "${CURRENT_PATCHED_BOOT_IMAGE_FILE}" | cut -f1 -d " " )"
  
  LOCAL_PATCHED_IMG_CHKSUM="$( cksum "${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}" | cut -f1 -d " " )"
  
  echo "The check sum of the patched boot image \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" on the phohe is \"${PATCHED_IMG_CHKSUM}\" "
  echo "The check sum of the downloaded patched boot image \"${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}\" is                    \"${LOCAL_PATCHED_IMG_CHKSUM}\"   "
   
  if [ "${PATCHED_IMG_CHKSUM}"x != "${LOCAL_PATCHED_IMG_CHKSUM}"x ] ; then
    echo "ERROR downloading the file \"${CURRENT_PATCHED_BOOT_IMAGE_FILE}\" from the phone (the check sums do not match)"
    die 250
  fi
  
  echo "Booting the phone into the fastboot mode now ..."

  adb ${ADB_OPTIONS} reboot bootloader

  wait_for_phone_to_be_in_fastboot_mode || die 39 "Booting the phone into the bootloader failed - Giving up..."

  echo "Flashing the partition \"${CURRENT_BOOT_PARTITION_NAME}\" with the patched image \"${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}\" ..."
  
  ${PREFIX}  ${SUDO_PREFIX} fastboot ${FASTBOOT_OPTIONS} flash "${CURRENT_BOOT_PARTITION_NAME}" "${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}"
  if [ $? -ne 0 ] ; then
    die 41 "Error flashing \"${CURRENT_PATCHED_BOOT_IMAGE_FILE_NAME}\" to the partition \"${CURRENT_BOOT_PARTITION_NAME}\" "
  fi
      
  REBOOT_COMMAND="fastboot"
fi

if [ "${REBOOT}"x = "yes"x -o "${REBOOT}"x = "YES"x ] ; then
  DO_REBOOT_THE_PHONE=${__TRUE}
elif [ "${REBOOT}"x = "no"x -o "${REBOOT}"x = "NO"x ] ; then
  echo "Automatically rebooting the phone is disabled"
  DO_REBOOT_THE_PHONE=${__FALSE}
else
  echo ""
  printf "*** Press return to reboot the phone now"
  read USER_INPUT
  printf "\n"
  
  if [ "${USER_INPUT}"x = "n"x -o "${USER_INPUT}"x = "N"x ] ; then
    DO_REBOOT_THE_PHONE=${__FALSE}
  else
    DO_REBOOT_THE_PHONE=${__TRUE}
  fi
fi

if [ ${DO_REBOOT_THE_PHONE} = ${__TRUE} ] ; then
  echo "Rebooting the phone now ..."

  if [ "${REBOOT_COMMAND}"x = "fastboot"x ] ; then
    ${SUDO_PREFIX} fastboot ${FASTBOOT_OPTIONS} reboot
  else  
    ${PREFIX} adb ${ADB_OPTIONS} reboot
  fi
fi

die ${THISRC}



