You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
6.9 KiB
212 lines
6.9 KiB
#! /bin/bash |
|
|
|
set -e |
|
|
|
print_message() { |
|
printf "$1\n" |
|
} |
|
|
|
PHONE_ADB_SERIAL_NUMBER=${ADB_DEVICE} # The adb serial number can be found by running `adb devices`. |
|
if [$PHONE_ADB_SERIAL_NUMBER = '']; then |
|
PHONE_ADB_SERIAL_NUMBER=$(echo $(adb devices) | sed -rn 's/(^|(.* ))([^ ]*) device(( .*)|$)/\3/; T; p; q') |
|
if [[ -z $PHONE_ADB_SERIAL_NUMBER ]]; then |
|
print_message "ERROR: no suitable phone connected" |
|
exit 1 |
|
fi |
|
fi |
|
|
|
check_phone_is_connected() { |
|
if ! adb devices | grep --silent "$PHONE_ADB_SERIAL_NUMBER"; then |
|
print_message "ERROR: phone '$PHONE_ADB_SERIAL_NUMBER' is not connected" |
|
adb devices -l |
|
exit 1 |
|
fi |
|
print_message "Operations will be performed on:" |
|
adb devices -l | grep $PHONE_ADB_SERIAL_NUMBER |
|
} |
|
|
|
check_phone_is_in_fastboot_mode() { |
|
fastboot devices | grep --silent "$PHONE_ADB_SERIAL_NUMBER" |
|
} |
|
|
|
get_lineage_version() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" shell getprop ro.lineage.version | tr -d '\n' |
|
} |
|
|
|
get_device_name() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" shell getprop ro.lineage.device | tr -d '\n' |
|
} |
|
|
|
get_device_downloads_page() { |
|
echo "https://download.lineageos.org/$(get_device_name)" |
|
} |
|
|
|
get_build_url() { |
|
curl --no-progress-meter "$(get_device_downloads_page)" | |
|
grep --only-matching --ignore-case \ |
|
"https://mirrorbits.lineageos.org/[^\"]*"$( |
|
)"$(get_lineage_version)-signed.zip" | |
|
head -1 |
|
} |
|
|
|
check_exists_latest_lineageos_build() { |
|
if [[ -f "/tmp/lineageos.zip" ]]; then |
|
# The --location lets curl follow the redirection. |
|
print_message "$(get_build_url)?sha256" |
|
curl --location "$(get_build_url)?sha256" --output /tmp/lineageos.sha256 |
|
hash1=$( awk '{print $1}' /tmp/lineageos.sha256 ) |
|
hash2=$( sha256sum /tmp/lineageos.zip | awk '{print $1}' ) |
|
[[ -n $hash1 && -n $hash2 && $hash1 == $hash2 ]] |
|
return |
|
fi |
|
false |
|
} |
|
|
|
download_latest_lineageos_build() { |
|
# The --location lets curl follow the redirection. |
|
curl --location "$(get_build_url)" --output /tmp/lineageos.zip |
|
} |
|
|
|
extract_boot_image() { |
|
# See https://wiki.lineageos.org/extracting_blobs_from_zips to understand the different ways to extract the boot.img file. |
|
if is_ota_block_based; then |
|
extract_boot_image_from_block_based_ota |
|
elif is_ota_payload_based; then |
|
extract_boot_image_from_payload_based_ota |
|
else |
|
extract_boot_image_from_file_based_ota |
|
fi |
|
} |
|
|
|
extract_boot_image_from_file_based_ota() { |
|
echo 'ERROR: the function "extract_boot_image_from_file_based_ota" is not implemented' |
|
exit 1 |
|
} |
|
|
|
extract_payload_from_payload_based_ota() { |
|
unzip -od /tmp /tmp/lineageos.zip payload.bin |
|
} |
|
|
|
generate_random_alnum_string_of_length_6() { |
|
tr -dc A-Za-z0-9 </dev/urandom | head -c 6 |
|
} |
|
|
|
extract_boot_image_from_payload_file() { |
|
# For cases in which the repo has already been cloned, I prefer to create a random directory name to clone into, instead of deleting any file or directory on the user's machine. |
|
scripts_directory_name="scripts_$(generate_random_alnum_string_of_length_6)" |
|
git clone https://github.com/LineageOS/scripts /tmp/$scripts_directory_name |
|
python3 /tmp/$scripts_directory_name/update-payload-extractor/extract.py --partitions boot --output_dir /tmp/ /tmp/payload.bin |
|
} |
|
|
|
extract_boot_image_from_payload_based_ota() { |
|
extract_payload_from_payload_based_ota |
|
extract_boot_image_from_payload_file |
|
} |
|
|
|
is_ota_payload_based() { |
|
unzip -l /tmp/lineageos.zip | grep -wq payload.bin |
|
} |
|
|
|
is_ota_block_based() { |
|
unzip -l /tmp/lineageos.zip | grep -wq boot.img |
|
} |
|
|
|
extract_boot_image_from_block_based_ota() { |
|
unzip -od /tmp /tmp/lineageos.zip boot.img |
|
} |
|
|
|
transfer_unpatched_boot_image_to_phone() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" push /tmp/boot.img /sdcard/Download/boot.img |
|
} |
|
|
|
patch_boot_image_on_phone() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" shell /data/adb/magisk/boot_patch.sh /sdcard/Download/boot.img |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" shell mv /data/adb/magisk/new-boot.img /sdcard/Download/patched-boot.img |
|
} |
|
|
|
transfer_patched_boot_image_to_pc() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" pull /sdcard/Download/patched-boot.img /tmp |
|
} |
|
|
|
reboot_to_bootloader() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" reboot bootloader |
|
} |
|
|
|
wait_for_phone_to_be_in_fastboot() { |
|
SECONDS=0 |
|
until check_phone_is_in_fastboot_mode; do |
|
|
|
if ((SECONDS > 60)); then |
|
echo "Giving up..." |
|
exit 2 |
|
fi |
|
|
|
echo "Phone is not in fastboot mode yet. Waiting..." |
|
sleep 5 |
|
done |
|
} |
|
|
|
flash_patched_boot_image() { |
|
fastboot -s "$PHONE_ADB_SERIAL_NUMBER" flash boot /tmp/patched-boot.img |
|
} |
|
|
|
reboot_phone() { |
|
fastboot -s "$PHONE_ADB_SERIAL_NUMBER" reboot |
|
} |
|
|
|
check_magisk_app() { |
|
magisk_package_name="com.topjohnwu.magisk" |
|
magisk_package_name_count=$(adb -s "$PHONE_ADB_SERIAL_NUMBER" shell pm list packages "$magisk_package_name" | wc -l) |
|
if [ "${magisk_package_name_count}" -eq 1 ] |
|
then |
|
print_message "Magisk app seems to be installed on selected phone" |
|
elif [ "${magisk_package_name_count}" -eq 0 ] |
|
then |
|
print_message "ERROR: Magisk app seems not installed on selected phone." |
|
exit -1 |
|
else |
|
print_message "ERROR: More than one Magisk app entry is present:" |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" shell pm list packages "$magisk_package_name" |
|
exit -1 |
|
fi |
|
} |
|
|
|
is_rooted_debugging_enabled() { |
|
adb -s "$PHONE_ADB_SERIAL_NUMBER" root |
|
} |
|
|
|
main() { |
|
print_message "Looking for phone '$PHONE_ADB_SERIAL_NUMBER'" |
|
check_phone_is_connected |
|
print_message "Checking on phone if rooted debugging is enabled" |
|
is_rooted_debugging_enabled |
|
print_message "Checking on phone if Magisk is installed" |
|
check_magisk_app |
|
print_message "Checking if build archive already exists" |
|
if check_exists_latest_lineageos_build; then |
|
print_message "Build archive found, skipping download" |
|
else |
|
print_message "Build archive not found or hash mismatch, downloading from $(get_build_url)" |
|
download_latest_lineageos_build |
|
fi |
|
print_message "Extracting 'boot.img' from build archive in /tmp/boot.img" |
|
extract_boot_image |
|
print_message "Copying from PC to phone the boot image in /sdcard/Download/boot.img" |
|
transfer_unpatched_boot_image_to_phone |
|
print_message "Patching boot image with Magisk script and moving it in /sdcard/Download/patched-boot.img" |
|
patch_boot_image_on_phone |
|
print_message "Copying patched boot image from phone to PC in /tmp/patched-boot.img" |
|
transfer_patched_boot_image_to_pc |
|
print_message "Rebooting phone in fastboot mode" |
|
reboot_to_bootloader |
|
wait_for_phone_to_be_in_fastboot |
|
print_message "Flashing patched boot image on phone" |
|
flash_patched_boot_image |
|
print_message "Rebooting phone" |
|
reboot_phone |
|
} |
|
|
|
# Run the main only when this file is executed as script, to help with testing. |
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then |
|
main "$@" |
|
fi
|
|
|