mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-07-04 14:43:01 +02:00
feat: root bl9000 script with backup functionality
This commit is contained in:
parent
41fe3b9b26
commit
c1b1282d64
911
scripts/utils/root_bl9000.sh
Executable file
911
scripts/utils/root_bl9000.sh
Executable file
@ -0,0 +1,911 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Root BL9000 phone from Arch Linux
|
||||
#
|
||||
# This script automates the rooting process for BL9000 phones using Magisk.
|
||||
# It handles:
|
||||
# - Installing required dependencies (ADB, fastboot, boot image tools)
|
||||
# - Detecting and connecting to the device
|
||||
# - Unlocking the bootloader (with user confirmation)
|
||||
# - Extracting boot image from device
|
||||
# - Patching boot image with Magisk
|
||||
# - Flashing patched boot image
|
||||
#
|
||||
# Prerequisites:
|
||||
# - USB debugging must be enabled on the phone
|
||||
# - OEM unlocking must be enabled in Developer Options
|
||||
# - Phone should be charged to at least 50%
|
||||
#
|
||||
# Conventions: sudo re-exec, idempotent, log with timestamps, follow repo style
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_NAME="$(basename "$0")"
|
||||
LOG_FILE="/var/log/bl9000-root.log"
|
||||
WORK_DIR="${HOME}/.cache/bl9000-root"
|
||||
MAGISK_APK_URL="https://github.com/topjohnwu/Magisk/releases/latest/download/Magisk.apk"
|
||||
BOOT_IMG=""
|
||||
PATCHED_BOOT_IMG=""
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
timestamp() { date '+%Y-%m-%d %H:%M:%S%z'; }
|
||||
|
||||
log() {
|
||||
local msg="$1"
|
||||
echo -e "${GREEN}[$(timestamp)]${NC} $msg"
|
||||
if [[ -w "$(dirname "$LOG_FILE")" ]] || [[ ! -e $LOG_FILE && -w /var/log ]]; then
|
||||
echo "[$(timestamp)] $msg" >>"$LOG_FILE" 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
warn() {
|
||||
local msg="$1"
|
||||
echo -e "${YELLOW}[WARN]${NC} $msg" >&2
|
||||
if [[ -w "$(dirname "$LOG_FILE")" ]] || [[ ! -e $LOG_FILE && -w /var/log ]]; then
|
||||
echo "[$(timestamp)] [WARN] $msg" >>"$LOG_FILE" 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
error() {
|
||||
local msg="$1"
|
||||
echo -e "${RED}[ERROR]${NC} $msg" >&2
|
||||
if [[ -w "$(dirname "$LOG_FILE")" ]] || [[ ! -e $LOG_FILE && -w /var/log ]]; then
|
||||
echo "[$(timestamp)] [ERROR] $msg" >>"$LOG_FILE" 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
error "$1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
print_header() {
|
||||
echo
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo -e "${BLUE} $1${NC}"
|
||||
echo -e "${BLUE}========================================${NC}"
|
||||
echo
|
||||
}
|
||||
|
||||
confirm() {
|
||||
local prompt="$1"
|
||||
local reply
|
||||
read -r -p "$(echo -e "${YELLOW}${prompt}${NC} [y/N]: ")" reply
|
||||
case "$reply" in
|
||||
[Yy][Ee][Ss] | [Yy]) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
require_non_root() {
|
||||
if [[ ${EUID:-$(id -u)} -eq 0 ]]; then
|
||||
die "Do not run this script as root. ADB must run as your regular user to access USB devices properly."
|
||||
fi
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $SCRIPT_NAME [OPTIONS] [COMMAND]
|
||||
|
||||
Root BL9000 phone from Arch Linux using Magisk.
|
||||
|
||||
Commands:
|
||||
install-deps Install required dependencies (adb, fastboot, tools)
|
||||
check Check device connection and prerequisites
|
||||
backup Backup phone data before unlocking bootloader
|
||||
unlock Unlock bootloader (WARNING: wipes all data!)
|
||||
root Extract boot, patch with Magisk, and flash
|
||||
full Run complete rooting process (deps + unlock + root)
|
||||
clean Remove temporary working directory
|
||||
help Show this message
|
||||
|
||||
Options:
|
||||
-h, --help Show this message
|
||||
--work-dir DIR Set working directory (default: $WORK_DIR)
|
||||
--boot-img FILE Use existing boot.img instead of extracting from device
|
||||
|
||||
Examples:
|
||||
$SCRIPT_NAME install-deps # Install required tools
|
||||
$SCRIPT_NAME check # Verify device connection
|
||||
$SCRIPT_NAME backup # Backup phone data first!
|
||||
$SCRIPT_NAME full # Complete rooting process
|
||||
$SCRIPT_NAME root # Root only (assumes bootloader unlocked)
|
||||
|
||||
WARNING: Unlocking the bootloader will ERASE ALL DATA on your phone!
|
||||
Make sure to back up important data before proceeding.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
install_dependencies() {
|
||||
print_header "Installing Dependencies"
|
||||
|
||||
local packages=()
|
||||
local missing=()
|
||||
|
||||
# Check for required commands
|
||||
if ! command -v adb >/dev/null 2>&1; then
|
||||
packages+=("android-tools")
|
||||
missing+=("adb")
|
||||
fi
|
||||
|
||||
if ! command -v fastboot >/dev/null 2>&1 && ! pacman -Q android-tools >/dev/null 2>&1; then
|
||||
packages+=("android-tools")
|
||||
missing+=("fastboot")
|
||||
fi
|
||||
|
||||
if ! command -v unzip >/dev/null 2>&1; then
|
||||
packages+=("unzip")
|
||||
missing+=("unzip")
|
||||
fi
|
||||
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
packages+=("curl")
|
||||
missing+=("curl")
|
||||
fi
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
packages+=("python")
|
||||
missing+=("python3")
|
||||
fi
|
||||
|
||||
# Check for python-protobuf (needed for boot image tools)
|
||||
if ! python3 -c "import google.protobuf" 2>/dev/null; then
|
||||
packages+=("python-protobuf")
|
||||
missing+=("python-protobuf")
|
||||
fi
|
||||
|
||||
if [[ ${#missing[@]} -eq 0 ]]; then
|
||||
log "All dependencies are already installed."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Missing dependencies: ${missing[*]}"
|
||||
|
||||
# Remove duplicates
|
||||
readarray -t packages < <(printf '%s\n' "${packages[@]}" | sort -u)
|
||||
|
||||
if ! confirm "Install missing packages: ${packages[*]}?"; then
|
||||
die "Cannot proceed without required dependencies."
|
||||
fi
|
||||
|
||||
log "Installing packages: ${packages[*]}"
|
||||
sudo pacman -S --needed --noconfirm "${packages[@]}" || die "Failed to install dependencies"
|
||||
|
||||
# Install payload-dumper-go from AUR if not present (for extracting boot.img from payload.bin)
|
||||
if ! command -v payload-dumper-go >/dev/null 2>&1; then
|
||||
if confirm "Install payload-dumper-go from AUR for extracting boot images?"; then
|
||||
if command -v yay >/dev/null 2>&1; then
|
||||
yay -S --needed --noconfirm payload-dumper-go || warn "Failed to install payload-dumper-go (optional)"
|
||||
elif command -v paru >/dev/null 2>&1; then
|
||||
paru -S --needed --noconfirm payload-dumper-go || warn "Failed to install payload-dumper-go (optional)"
|
||||
else
|
||||
warn "No AUR helper found. Install payload-dumper-go manually if needed."
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Dependencies installed successfully."
|
||||
}
|
||||
|
||||
setup_udev_rules() {
|
||||
print_header "Setting Up USB Access"
|
||||
|
||||
local udev_file="/etc/udev/rules.d/51-android.rules"
|
||||
|
||||
if [[ -f $udev_file ]]; then
|
||||
log "Android udev rules already exist at $udev_file"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if ! confirm "Create udev rules for Android device access?"; then
|
||||
warn "Skipping udev rules. You may need to run commands with sudo."
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Creating Android udev rules..."
|
||||
|
||||
# Create comprehensive udev rules for Android devices
|
||||
sudo tee "$udev_file" >/dev/null <<'EOF'
|
||||
# Android Debug Bridge (ADB) devices
|
||||
# Add your device's vendor ID if not listed
|
||||
|
||||
# Google
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666", GROUP="adbusers"
|
||||
# MediaTek (common in BL9000)
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0e8d", MODE="0666", GROUP="adbusers"
|
||||
# Generic catch-all for Android devices
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="*", ATTR{idProduct}=="*", MODE="0666", GROUP="adbusers", SYMLINK+="android%n"
|
||||
EOF
|
||||
|
||||
# Create adbusers group if it doesn't exist
|
||||
if ! getent group adbusers >/dev/null; then
|
||||
sudo groupadd -r adbusers
|
||||
log "Created adbusers group"
|
||||
fi
|
||||
|
||||
# Add current user to adbusers group
|
||||
if ! groups "$USER" | grep -q '\badbusers\b'; then
|
||||
sudo usermod -aG adbusers "$USER"
|
||||
log "Added $USER to adbusers group"
|
||||
warn "You need to log out and back in for group membership to take effect."
|
||||
warn "Alternatively, run: newgrp adbusers"
|
||||
fi
|
||||
|
||||
# Reload udev rules
|
||||
sudo udevadm control --reload-rules
|
||||
sudo udevadm trigger
|
||||
|
||||
log "USB access configured successfully."
|
||||
}
|
||||
|
||||
backup_device_data() {
|
||||
print_header "Backing Up Device Data"
|
||||
|
||||
local backup_dir
|
||||
backup_dir="${WORK_DIR}/backup_$(date +%Y%m%d_%H%M%S)"
|
||||
mkdir -p "$backup_dir"
|
||||
|
||||
log "Backup directory: $backup_dir" # Check device connection first
|
||||
if ! adb get-state >/dev/null 2>&1; then
|
||||
error "Device not connected. Please connect your device first."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Starting comprehensive backup process..."
|
||||
|
||||
# 1. Backup internal storage (DCIM, Pictures, Documents, Downloads, etc.)
|
||||
log "Backing up internal storage (this may take a while)..."
|
||||
local storage_dirs=("DCIM" "Pictures" "Documents" "Download" "Music" "Movies" "WhatsApp" "Telegram")
|
||||
|
||||
for dir in "${storage_dirs[@]}"; do
|
||||
if adb shell "[ -d /sdcard/$dir ]" 2>/dev/null; then
|
||||
log " → Backing up /sdcard/$dir..."
|
||||
if adb pull "/sdcard/$dir" "$backup_dir/$dir" 2>&1 | grep -v "^$"; then
|
||||
log " ✓ $dir backed up successfully"
|
||||
else
|
||||
warn " ⚠ Could not backup $dir (may be empty or inaccessible)"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 2. Backup SMS/MMS (if possible)
|
||||
log "Backing up SMS/MMS database..."
|
||||
if adb shell "su -c 'cp /data/data/com.android.providers.telephony/databases/mmssms.db /sdcard/mmssms.db'" 2>/dev/null; then
|
||||
adb pull /sdcard/mmssms.db "$backup_dir/mmssms.db" 2>/dev/null && log " ✓ SMS/MMS backed up"
|
||||
adb shell "rm /sdcard/mmssms.db" 2>/dev/null || true
|
||||
else
|
||||
warn " ⚠ SMS/MMS backup requires root (skipping)"
|
||||
fi
|
||||
|
||||
# 3. Backup contacts
|
||||
log "Backing up contacts..."
|
||||
if adb shell "su -c 'cp /data/data/com.android.providers.contacts/databases/contacts2.db /sdcard/contacts2.db'" 2>/dev/null; then
|
||||
adb pull /sdcard/contacts2.db "$backup_dir/contacts2.db" 2>/dev/null && log " ✓ Contacts backed up"
|
||||
adb shell "rm /sdcard/contacts2.db" 2>/dev/null || true
|
||||
else
|
||||
warn " ⚠ Contacts backup requires root (skipping)"
|
||||
fi
|
||||
|
||||
# 4. Backup call logs
|
||||
log "Backing up call logs..."
|
||||
if adb shell "su -c 'cp /data/data/com.android.providers.contacts/databases/calllog.db /sdcard/calllog.db'" 2>/dev/null; then
|
||||
adb pull /sdcard/calllog.db "$backup_dir/calllog.db" 2>/dev/null && log " ✓ Call logs backed up"
|
||||
adb shell "rm /sdcard/calllog.db" 2>/dev/null || true
|
||||
else
|
||||
warn " ⚠ Call logs backup requires root (skipping)"
|
||||
fi
|
||||
|
||||
# 5. Backup app list
|
||||
log "Backing up installed apps list..."
|
||||
adb shell "pm list packages -f" >"$backup_dir/installed_apps.txt"
|
||||
log " ✓ App list saved to installed_apps.txt"
|
||||
|
||||
# 6. Backup APKs for user-installed apps (optional, can be large)
|
||||
if confirm "Backup APK files for installed apps? (This can take a long time and use lots of space)"; then
|
||||
log "Backing up user-installed APKs..."
|
||||
local apk_dir="$backup_dir/apks"
|
||||
mkdir -p "$apk_dir"
|
||||
|
||||
# Get user-installed packages
|
||||
local user_apps
|
||||
user_apps=$(adb shell "pm list packages -3 -f" | sed 's/package://' | cut -d'=' -f2)
|
||||
|
||||
local count=0
|
||||
while IFS= read -r pkg; do
|
||||
if [[ -n $pkg ]]; then
|
||||
log " → Backing up $pkg..."
|
||||
local apk_path
|
||||
apk_path=$(adb shell "pm path $pkg" | head -n1 | sed 's/package://')
|
||||
if [[ -n $apk_path ]]; then
|
||||
adb pull "$apk_path" "$apk_dir/${pkg}.apk" >/dev/null 2>&1 && count=$((count + 1))
|
||||
fi
|
||||
fi
|
||||
done <<<"$user_apps"
|
||||
|
||||
log " ✓ Backed up $count APK files"
|
||||
fi
|
||||
|
||||
# 7. Full ADB backup (app data, if device supports it)
|
||||
log "Creating full ADB backup (app data)..."
|
||||
if confirm "Create full ADB backup? (You'll need to confirm on your device)"; then
|
||||
echo
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " On your phone: Tap 'Back up my data' when prompted"
|
||||
echo " You can set a password or leave it blank"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
|
||||
if adb backup -apk -shared -all -system -f "$backup_dir/full_backup.ab"; then
|
||||
log " ✓ Full ADB backup completed"
|
||||
log " Note: Restore with: adb restore full_backup.ab"
|
||||
else
|
||||
warn " ⚠ ADB backup failed or was cancelled"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 8. Backup device info
|
||||
log "Saving device information..."
|
||||
{
|
||||
echo "Device Backup Information"
|
||||
echo "========================="
|
||||
echo "Date: $(date)"
|
||||
echo
|
||||
echo "Device Model: $(adb shell getprop ro.product.model | tr -d '\r\n')"
|
||||
echo "Android Version: $(adb shell getprop ro.build.version.release | tr -d '\r\n')"
|
||||
echo "Build Number: $(adb shell getprop ro.build.display.id | tr -d '\r\n')"
|
||||
echo "Security Patch: $(adb shell getprop ro.build.version.security_patch | tr -d '\r\n')"
|
||||
echo "Serial: $(adb shell getprop ro.serialno | tr -d '\r\n')"
|
||||
echo
|
||||
echo "Installed Apps:"
|
||||
adb shell "pm list packages -3" | sed 's/package:/ - /'
|
||||
} >"$backup_dir/device_info.txt"
|
||||
|
||||
log " ✓ Device info saved"
|
||||
|
||||
# Summary
|
||||
local backup_size
|
||||
backup_size=$(du -sh "$backup_dir" 2>/dev/null | cut -f1 || echo "unknown")
|
||||
|
||||
echo
|
||||
echo -e "${GREEN}╔═══════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ Backup Completed Successfully! ║${NC}"
|
||||
echo -e "${GREEN}╚═══════════════════════════════════════════════════════╝${NC}"
|
||||
echo
|
||||
log "Backup location: $backup_dir"
|
||||
log "Backup size: $backup_size"
|
||||
echo
|
||||
echo "What was backed up:"
|
||||
echo " ✓ Photos (DCIM)"
|
||||
echo " ✓ Pictures"
|
||||
echo " ✓ Documents"
|
||||
echo " ✓ Downloads"
|
||||
echo " ✓ Music"
|
||||
echo " ✓ Movies"
|
||||
echo " ✓ WhatsApp data (if present)"
|
||||
echo " ✓ Telegram data (if present)"
|
||||
echo " ✓ Installed apps list"
|
||||
echo " ✓ Device information"
|
||||
if [[ -f "$backup_dir/full_backup.ab" ]]; then
|
||||
echo " ✓ Full app data backup"
|
||||
fi
|
||||
if [[ -d "$backup_dir/apks" ]]; then
|
||||
echo " ✓ APK files"
|
||||
fi
|
||||
echo
|
||||
log "Keep this backup safe! You'll need it to restore your data after rooting."
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
check_device() {
|
||||
print_header "Checking Device Connection"
|
||||
|
||||
log "Starting ADB server..."
|
||||
adb start-server >/dev/null 2>&1 || true
|
||||
|
||||
log "Waiting for device..."
|
||||
if ! adb wait-for-device; then
|
||||
error "Failed to detect device via ADB."
|
||||
echo
|
||||
echo "Troubleshooting steps:"
|
||||
echo "1. Make sure USB debugging is enabled on your phone"
|
||||
echo " Settings → About Phone → Tap Build Number 7 times"
|
||||
echo " Settings → Developer Options → Enable USB Debugging"
|
||||
echo "2. Connect your phone via USB cable"
|
||||
echo "3. Accept the 'Allow USB debugging' prompt on your phone"
|
||||
echo "4. Run: adb devices"
|
||||
echo
|
||||
return 1
|
||||
fi
|
||||
|
||||
local device_info
|
||||
device_info=$(adb devices -l | grep -v "List of devices" | grep -v "^$" | head -n1)
|
||||
|
||||
if [[ -z $device_info ]]; then
|
||||
error "No device detected"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Device connected: $device_info"
|
||||
|
||||
# Check device properties
|
||||
local model
|
||||
model=$(adb shell getprop ro.product.model 2>/dev/null | tr -d '\r\n' || echo "Unknown")
|
||||
log "Model: $model"
|
||||
|
||||
local android_version
|
||||
android_version=$(adb shell getprop ro.build.version.release 2>/dev/null | tr -d '\r\n' || echo "Unknown")
|
||||
log "Android version: $android_version"
|
||||
|
||||
local battery_level
|
||||
battery_level=$(adb shell dumpsys battery | grep level | awk '{print $2}' | tr -d '\r\n' || echo "Unknown")
|
||||
log "Battery level: ${battery_level}%"
|
||||
|
||||
if [[ $battery_level != "Unknown" && $battery_level -lt 50 ]]; then
|
||||
warn "Battery level is below 50%. Charge your phone before proceeding."
|
||||
if ! confirm "Continue anyway?"; then
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if bootloader is unlocked
|
||||
local unlock_status
|
||||
unlock_status=$(adb shell getprop ro.boot.verifiedbootstate 2>/dev/null | tr -d '\r\n' || echo "unknown")
|
||||
if [[ $unlock_status == "orange" || $unlock_status == "red" ]]; then
|
||||
log "Bootloader unlock status: ${GREEN}UNLOCKED${NC}"
|
||||
else
|
||||
warn "Bootloader appears to be LOCKED. You'll need to unlock it to root."
|
||||
fi
|
||||
|
||||
# Check if OEM unlocking is enabled
|
||||
local oem_unlock
|
||||
oem_unlock=$(adb shell getprop sys.oem_unlock_allowed 2>/dev/null | tr -d '\r\n' || echo "unknown")
|
||||
if [[ $oem_unlock == "1" ]]; then
|
||||
log "OEM unlocking: ${GREEN}ENABLED${NC}"
|
||||
else
|
||||
warn "OEM unlocking is not enabled in Developer Options."
|
||||
echo "Enable it at: Settings → Developer Options → OEM unlocking"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
unlock_bootloader() {
|
||||
print_header "Unlocking Bootloader"
|
||||
|
||||
echo
|
||||
echo -e "${RED}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${RED}║ WARNING ║${NC}"
|
||||
echo -e "${RED}║ ║${NC}"
|
||||
echo -e "${RED}║ Unlocking the bootloader will ERASE ALL DATA on your phone! ║${NC}"
|
||||
echo -e "${RED}║ ║${NC}"
|
||||
echo -e "${RED}║ This includes: ║${NC}"
|
||||
echo -e "${RED}║ - All apps and app data ║${NC}"
|
||||
echo -e "${RED}║ - Photos, videos, and files ║${NC}"
|
||||
echo -e "${RED}║ - System settings ║${NC}"
|
||||
echo -e "${RED}║ - Everything else on internal storage ║${NC}"
|
||||
echo -e "${RED}║ ║${NC}"
|
||||
echo -e "${RED}║ Make sure you have backed up important data! ║${NC}"
|
||||
echo -e "${RED}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo
|
||||
|
||||
if ! confirm "Have you backed up all important data and want to proceed?"; then
|
||||
log "Bootloader unlock cancelled by user."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! confirm "Are you ABSOLUTELY SURE? This cannot be undone!"; then
|
||||
log "Bootloader unlock cancelled by user."
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Rebooting device to bootloader..."
|
||||
adb reboot bootloader || die "Failed to reboot to bootloader"
|
||||
|
||||
log "Waiting for fastboot mode..."
|
||||
sleep 5
|
||||
|
||||
if ! fastboot devices | grep -q .; then
|
||||
error "Device not detected in fastboot mode."
|
||||
echo
|
||||
echo "If the device doesn't enter fastboot automatically:"
|
||||
echo "1. Power off the phone completely"
|
||||
echo "2. Hold Volume Down + Power buttons simultaneously"
|
||||
echo "3. Release when you see the bootloader/fastboot screen"
|
||||
echo "4. Run: fastboot devices"
|
||||
echo
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Device in fastboot mode"
|
||||
|
||||
# Check current bootloader status
|
||||
local bl_status
|
||||
bl_status=$(fastboot getvar unlocked 2>&1 | grep "unlocked:" | awk '{print $2}' || echo "unknown")
|
||||
if [[ $bl_status == "yes" ]]; then
|
||||
log "Bootloader is already unlocked."
|
||||
fastboot reboot
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Attempting to unlock bootloader..."
|
||||
|
||||
# Try different unlock commands (varies by device)
|
||||
if fastboot flashing unlock 2>&1 | grep -qi "okay\|finished"; then
|
||||
log "Bootloader unlock command sent successfully."
|
||||
elif fastboot oem unlock 2>&1 | grep -qi "okay\|finished"; then
|
||||
log "Bootloader unlock command sent successfully."
|
||||
else
|
||||
error "Bootloader unlock command may have failed."
|
||||
echo
|
||||
echo "On your phone:"
|
||||
echo "1. Use volume buttons to select 'Unlock the bootloader'"
|
||||
echo "2. Press power button to confirm"
|
||||
echo
|
||||
|
||||
if ! confirm "Did you complete the unlock on the device?"; then
|
||||
fastboot reboot
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Rebooting device..."
|
||||
fastboot reboot || true
|
||||
|
||||
log "Bootloader unlocked successfully!"
|
||||
log "Device will now boot up and perform factory reset..."
|
||||
log "Waiting for device to come back online..."
|
||||
|
||||
sleep 10
|
||||
adb wait-for-device || true
|
||||
|
||||
log "Please complete the initial setup on your phone, then re-enable USB debugging."
|
||||
echo
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
download_magisk() {
|
||||
print_header "Downloading Magisk"
|
||||
|
||||
local magisk_apk="$WORK_DIR/magisk.apk"
|
||||
|
||||
if [[ -f $magisk_apk ]]; then
|
||||
log "Magisk APK already downloaded at $magisk_apk"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Downloading latest Magisk APK..."
|
||||
if ! curl -L -o "$magisk_apk" "$MAGISK_APK_URL"; then
|
||||
error "Failed to download Magisk APK"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Magisk downloaded successfully: $magisk_apk"
|
||||
return 0
|
||||
}
|
||||
|
||||
extract_boot_image() {
|
||||
print_header "Extracting Boot Image"
|
||||
|
||||
local boot_img="$WORK_DIR/boot.img"
|
||||
|
||||
if [[ -n ${BOOT_IMG:-} && -f $BOOT_IMG ]]; then
|
||||
log "Using provided boot image: $BOOT_IMG"
|
||||
cp "$BOOT_IMG" "$boot_img"
|
||||
BOOT_IMG="$boot_img"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log "Attempting to extract boot image from device..."
|
||||
|
||||
# Method 1: Try to pull boot partition directly
|
||||
local boot_partition
|
||||
boot_partition=$(adb shell "find /dev/block -name boot | head -n1" 2>/dev/null | tr -d '\r\n' || echo "")
|
||||
|
||||
if [[ -n $boot_partition ]]; then
|
||||
log "Found boot partition: $boot_partition"
|
||||
if adb pull "$boot_partition" "$boot_img" 2>/dev/null; then
|
||||
log "Boot image extracted successfully"
|
||||
BOOT_IMG="$boot_img"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Method 2: Try to get boot partition via by-name
|
||||
boot_partition=$(adb shell "ls /dev/block/by-name/boot*" 2>/dev/null | head -n1 | tr -d '\r\n' || echo "")
|
||||
|
||||
if [[ -n $boot_partition ]]; then
|
||||
log "Found boot partition: $boot_partition"
|
||||
if adb shell "su -c 'dd if=$boot_partition of=/sdcard/boot.img'" 2>/dev/null &&
|
||||
adb pull /sdcard/boot.img "$boot_img" 2>/dev/null; then
|
||||
adb shell rm /sdcard/boot.img 2>/dev/null || true
|
||||
log "Boot image extracted successfully"
|
||||
BOOT_IMG="$boot_img"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
error "Failed to extract boot image automatically."
|
||||
echo
|
||||
echo "Manual extraction options:"
|
||||
echo "1. Extract boot.img from your device's firmware package"
|
||||
echo "2. Use MTK Droid Tools (for MediaTek devices)"
|
||||
echo "3. Get boot.img from device manufacturer's official ROM"
|
||||
echo
|
||||
echo "Then run: $SCRIPT_NAME root --boot-img /path/to/boot.img"
|
||||
echo
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
patch_boot_with_magisk() {
|
||||
print_header "Patching Boot Image with Magisk"
|
||||
|
||||
if [[ ! -f ${BOOT_IMG:-} ]]; then
|
||||
die "Boot image not found: ${BOOT_IMG:-none}"
|
||||
fi
|
||||
|
||||
local magisk_apk="$WORK_DIR/magisk.apk"
|
||||
if [[ ! -f $magisk_apk ]]; then
|
||||
die "Magisk APK not found. Run download step first."
|
||||
fi
|
||||
|
||||
log "Installing Magisk APK on device..."
|
||||
if ! adb install -r "$magisk_apk" 2>/dev/null; then
|
||||
error "Failed to install Magisk APK"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Pushing boot image to device..."
|
||||
adb push "$BOOT_IMG" /sdcard/Download/boot.img || die "Failed to push boot image"
|
||||
|
||||
echo
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " MANUAL STEP REQUIRED"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
echo "On your phone:"
|
||||
echo "1. Open the Magisk app"
|
||||
echo "2. Tap 'Install' next to Magisk"
|
||||
echo "3. Select 'Select and Patch a File'"
|
||||
echo "4. Navigate to Downloads and select boot.img"
|
||||
echo "5. Tap 'Let's Go' and wait for patching to complete"
|
||||
echo "6. The patched file will be saved as magisk_patched_*.img"
|
||||
echo
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo
|
||||
|
||||
if ! confirm "Have you completed patching the boot image in Magisk app?"; then
|
||||
error "Patching cancelled by user"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Pulling patched boot image from device..."
|
||||
|
||||
local patched_img
|
||||
patched_img=$(adb shell "ls /sdcard/Download/magisk_patched_*.img 2>/dev/null" | tr -d '\r\n' | head -n1 || echo "")
|
||||
|
||||
if [[ -z $patched_img ]]; then
|
||||
error "Could not find patched boot image on device."
|
||||
echo "Please ensure the patching completed successfully in Magisk app."
|
||||
return 1
|
||||
fi
|
||||
|
||||
PATCHED_BOOT_IMG="$WORK_DIR/magisk_patched.img"
|
||||
if ! adb pull "$patched_img" "$PATCHED_BOOT_IMG"; then
|
||||
error "Failed to pull patched boot image"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Patched boot image saved to: $PATCHED_BOOT_IMG"
|
||||
return 0
|
||||
}
|
||||
|
||||
flash_patched_boot() {
|
||||
print_header "Flashing Patched Boot Image"
|
||||
|
||||
if [[ ! -f ${PATCHED_BOOT_IMG:-} ]]; then
|
||||
die "Patched boot image not found: ${PATCHED_BOOT_IMG:-none}"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${YELLOW}This will flash the patched boot image to your device.${NC}"
|
||||
echo
|
||||
|
||||
if ! confirm "Proceed with flashing?"; then
|
||||
log "Flashing cancelled by user"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Rebooting to bootloader..."
|
||||
adb reboot bootloader || die "Failed to reboot to bootloader"
|
||||
|
||||
log "Waiting for fastboot mode..."
|
||||
sleep 5
|
||||
|
||||
if ! fastboot devices | grep -q .; then
|
||||
die "Device not detected in fastboot mode"
|
||||
fi
|
||||
|
||||
log "Flashing patched boot image..."
|
||||
if ! fastboot flash boot "$PATCHED_BOOT_IMG"; then
|
||||
error "Failed to flash boot image"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "Flashed successfully!"
|
||||
log "Rebooting device..."
|
||||
fastboot reboot
|
||||
|
||||
log "Waiting for device to boot..."
|
||||
sleep 10
|
||||
adb wait-for-device || true
|
||||
|
||||
echo
|
||||
echo -e "${GREEN}╔═══════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${GREEN}║ Root Process Complete! ║${NC}"
|
||||
echo -e "${GREEN}╚═══════════════════════════════════════════════════════╝${NC}"
|
||||
echo
|
||||
echo "Your BL9000 phone should now be rooted with Magisk!"
|
||||
echo
|
||||
echo "Next steps:"
|
||||
echo "1. Open the Magisk app on your phone"
|
||||
echo "2. Verify that it shows 'Installed' for both Magisk and App"
|
||||
echo "3. Grant root access to apps as needed"
|
||||
echo "4. Install Magisk modules if desired"
|
||||
echo
|
||||
echo "Note: Some banking and secure apps may not work with root."
|
||||
echo " Use Magisk's DenyList feature to hide root from specific apps."
|
||||
echo
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
clean_work_dir() {
|
||||
if [[ -d $WORK_DIR ]]; then
|
||||
log "Removing working directory: $WORK_DIR"
|
||||
rm -rf "$WORK_DIR"
|
||||
log "Cleaned successfully"
|
||||
else
|
||||
log "Work directory doesn't exist: $WORK_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
run_full_process() {
|
||||
print_header "BL9000 Full Root Process"
|
||||
|
||||
log "Starting complete rooting process..."
|
||||
|
||||
install_dependencies || die "Failed to install dependencies"
|
||||
setup_udev_rules || true
|
||||
|
||||
echo
|
||||
if ! confirm "Continue to device check?"; then
|
||||
die "Process cancelled by user"
|
||||
fi
|
||||
|
||||
check_device || die "Device check failed"
|
||||
|
||||
echo
|
||||
if ! confirm "Continue to backup device data?"; then
|
||||
die "Process cancelled by user"
|
||||
fi
|
||||
|
||||
backup_device_data || warn "Backup failed or incomplete"
|
||||
|
||||
echo
|
||||
if ! confirm "Continue to bootloader unlock?"; then
|
||||
die "Process cancelled by user"
|
||||
fi
|
||||
|
||||
unlock_bootloader || die "Bootloader unlock failed"
|
||||
|
||||
echo
|
||||
log "Please complete device setup and re-enable USB debugging, then press Enter..."
|
||||
read -r
|
||||
|
||||
check_device || die "Device check failed after unlock"
|
||||
|
||||
download_magisk || die "Failed to download Magisk"
|
||||
extract_boot_image || die "Failed to extract boot image"
|
||||
patch_boot_with_magisk || die "Failed to patch boot image"
|
||||
flash_patched_boot || die "Failed to flash patched boot"
|
||||
|
||||
log "Full root process completed successfully!"
|
||||
}
|
||||
|
||||
run_root_only() {
|
||||
print_header "BL9000 Root Process (Skip Unlock)"
|
||||
|
||||
log "Starting root process (assuming bootloader is already unlocked)..."
|
||||
|
||||
check_device || die "Device check failed"
|
||||
download_magisk || die "Failed to download Magisk"
|
||||
extract_boot_image || die "Failed to extract boot image"
|
||||
patch_boot_with_magisk || die "Failed to patch boot image"
|
||||
flash_patched_boot || die "Failed to flash patched boot"
|
||||
|
||||
log "Root process completed successfully!"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_non_root
|
||||
|
||||
# Create work directory
|
||||
mkdir -p "$WORK_DIR"
|
||||
|
||||
local command="${1:-help}"
|
||||
shift || true
|
||||
|
||||
# Parse options
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--work-dir)
|
||||
WORK_DIR="$2"
|
||||
mkdir -p "$WORK_DIR"
|
||||
shift 2
|
||||
;;
|
||||
--boot-img)
|
||||
BOOT_IMG="$2"
|
||||
if [[ ! -f $BOOT_IMG ]]; then
|
||||
die "Boot image file not found: $BOOT_IMG"
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
-h | --help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
error "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$command" in
|
||||
install-deps)
|
||||
install_dependencies
|
||||
setup_udev_rules
|
||||
;;
|
||||
check)
|
||||
check_device
|
||||
;;
|
||||
backup)
|
||||
check_device || die "Device check failed"
|
||||
backup_device_data
|
||||
;;
|
||||
unlock)
|
||||
check_device || die "Device check failed"
|
||||
unlock_bootloader
|
||||
;;
|
||||
root)
|
||||
run_root_only
|
||||
;;
|
||||
full)
|
||||
run_full_process
|
||||
;;
|
||||
clean)
|
||||
clean_work_dir
|
||||
;;
|
||||
help | --help | -h)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
error "Unknown command: $command"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Loading…
Reference in New Issue
Block a user