Last active
June 27, 2026 05:19
-
-
Save tas33n/55032ab0a3319def46132437852f8392 to your computer and use it in GitHub Desktop.
Fast Xiaomi ROM downloader and boot image extractor for Linux/Codespaces. Downloads ROMs with aria2c, detects Fastboot or Recovery/OTA packages, extracts payload.bin when needed, and collects boot.img/init_boot.img/vendor_boot.img.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -Eeuo pipefail | |
| APP_NAME="BootX" | |
| VERBOSE=0 | |
| show_help() { | |
| cat <<'HELP' | |
| BootX - Fast Xiaomi/Android ROM downloader and boot image extractor | |
| Usage: | |
| bash bootx.sh "ROM_URL" "optional-file-name.zip" "optional-workdir" | |
| bash bootx.sh --verbose "ROM_URL" "rom.zip" | |
| Examples: | |
| bash bootx.sh "https://example.com/rom.zip" "xiaomi-rom.zip" | |
| CONNECTIONS=32 SPLITS=32 bash bootx.sh "ROM_URL" "rom.zip" | |
| Output: | |
| rom_work/needed_images/ | |
| rom_work/rom_report.txt | |
| rom_work/setup.log | |
| HELP | |
| } | |
| if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then | |
| show_help | |
| exit 0 | |
| fi | |
| if [ "${1:-}" = "--verbose" ] || [ "${1:-}" = "-v" ]; then | |
| VERBOSE=1 | |
| shift | |
| fi | |
| URL="${1:-}" | |
| OUT="${2:-}" | |
| WORKDIR="${3:-rom_work}" | |
| CONNECTIONS="${CONNECTIONS:-16}" | |
| SPLITS="${SPLITS:-16}" | |
| CHUNK_SIZE="${CHUNK_SIZE:-1M}" | |
| PDG_WORKERS="${PDG_WORKERS:-4}" | |
| TARGET_PARTITIONS="${TARGET_PARTITIONS:-boot,init_boot,vendor_boot,vendor_kernel_boot,dtbo,vbmeta,vbmeta_system,vbmeta_vendor,recovery}" | |
| DOWNLOAD_DIR="$WORKDIR/downloads" | |
| EXTRACT_DIR="$WORKDIR/extracted" | |
| PAYLOAD_OUT="$WORKDIR/payload_extracted" | |
| NEEDED_DIR="$WORKDIR/needed_images" | |
| TOOLS_DIR="$WORKDIR/tools" | |
| REPORT="$WORKDIR/rom_report.txt" | |
| SETUP_LOG="$WORKDIR/setup.log" | |
| ARCHIVE_LIST="$WORKDIR/archive_list.txt" | |
| mkdir -p "$DOWNLOAD_DIR" "$EXTRACT_DIR" "$PAYLOAD_OUT" "$NEEDED_DIR" "$TOOLS_DIR" | |
| : > "$REPORT" | |
| : > "$SETUP_LOG" | |
| if [ -t 1 ]; then | |
| C_RESET="\033[0m" | |
| C_BOLD="\033[1m" | |
| C_GREEN="\033[32m" | |
| C_BLUE="\033[34m" | |
| C_YELLOW="\033[33m" | |
| C_RED="\033[31m" | |
| C_GRAY="\033[90m" | |
| else | |
| C_RESET="" | |
| C_BOLD="" | |
| C_GREEN="" | |
| C_BLUE="" | |
| C_YELLOW="" | |
| C_RED="" | |
| C_GRAY="" | |
| fi | |
| SUDO="" | |
| if [ "$(id -u)" -ne 0 ]; then | |
| SUDO="sudo" | |
| fi | |
| log() { | |
| echo -e "$*" | tee -a "$REPORT" >/dev/null | |
| } | |
| say() { | |
| echo -e "$*" | |
| echo -e "$*" >> "$REPORT" | |
| } | |
| info() { | |
| echo -e "${C_BLUE}▶${C_RESET} $*" | |
| echo -e "▶ $*" >> "$REPORT" | |
| } | |
| ok() { | |
| echo -e "${C_GREEN}✓${C_RESET} $*" | |
| echo -e "✓ $*" >> "$REPORT" | |
| } | |
| warn() { | |
| echo -e "${C_YELLOW}!${C_RESET} $*" | |
| echo -e "! $*" >> "$REPORT" | |
| } | |
| fail() { | |
| echo -e "${C_RED}✗${C_RESET} $*" | |
| echo -e "✗ $*" >> "$REPORT" | |
| } | |
| quiet_run() { | |
| local message="$1" | |
| shift | |
| info "$message" | |
| if [ "$VERBOSE" = "1" ]; then | |
| "$@" | |
| ok "$message done" | |
| else | |
| if "$@" >>"$SETUP_LOG" 2>&1; then | |
| ok "$message done" | |
| else | |
| fail "$message failed" | |
| echo | |
| echo "Last setup log:" | |
| tail -n 80 "$SETUP_LOG" || true | |
| echo | |
| echo "Full log: $SETUP_LOG" | |
| exit 1 | |
| fi | |
| fi | |
| } | |
| soft_run() { | |
| local message="$1" | |
| shift | |
| info "$message" | |
| if [ "$VERBOSE" = "1" ]; then | |
| if "$@"; then | |
| ok "$message done" | |
| return 0 | |
| else | |
| warn "$message skipped or failed" | |
| return 1 | |
| fi | |
| fi | |
| if "$@" >>"$SETUP_LOG" 2>&1; then | |
| ok "$message done" | |
| return 0 | |
| else | |
| warn "$message skipped or failed" | |
| return 1 | |
| fi | |
| } | |
| need_cmd() { | |
| command -v "$1" >/dev/null 2>&1 | |
| } | |
| if [ -z "$URL" ]; then | |
| show_help | |
| exit 1 | |
| fi | |
| if [ -z "$OUT" ]; then | |
| OUT="$(basename "${URL%%\?*}")" | |
| [ -z "$OUT" ] || [ "$OUT" = "/" ] || [ "$OUT" = "." ] && OUT="rom.bin" | |
| fi | |
| print_header() { | |
| echo | |
| echo -e "${C_BOLD}$APP_NAME${C_RESET}" | |
| echo -e "${C_GRAY}Fast ROM downloader and boot image extractor${C_RESET}" | |
| echo | |
| } | |
| apt_update_once() { | |
| if [ ! -f "$WORKDIR/.apt_updated" ]; then | |
| quiet_run "Preparing package manager" \ | |
| $SUDO env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a \ | |
| apt-get update -qq | |
| touch "$WORKDIR/.apt_updated" | |
| fi | |
| } | |
| install_packages() { | |
| apt_update_once | |
| quiet_run "Installing required tools" \ | |
| $SUDO env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a \ | |
| apt-get install -y -qq --no-install-recommends \ | |
| aria2 curl ca-certificates jq unzip p7zip-full tar gzip xz-utils zstd lz4 brotli \ | |
| python3 python3-pip file findutils coreutils | |
| soft_run "Installing optional Android image tools" \ | |
| $SUDO env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a \ | |
| apt-get install -y -qq --no-install-recommends android-sdk-libsparse-utils erofs-utils | |
| } | |
| install_payload_dumper_go() { | |
| if need_cmd payload-dumper-go; then | |
| ok "payload-dumper-go already installed" | |
| return 0 | |
| fi | |
| info "Installing payload-dumper-go" | |
| local arch asset_arch api_json asset_url tmp pkg filetype pdg_bin gobin | |
| arch="$(uname -m)" | |
| case "$arch" in | |
| x86_64|amd64) asset_arch="amd64" ;; | |
| aarch64|arm64) asset_arch="arm64" ;; | |
| armv7l|armhf) asset_arch="armv7" ;; | |
| *) | |
| warn "Unsupported CPU arch for binary auto-download: $arch" | |
| asset_arch="" | |
| ;; | |
| esac | |
| tmp="$TOOLS_DIR/payload-dumper-go_download" | |
| rm -rf "$tmp" | |
| mkdir -p "$tmp" | |
| if [ -n "$asset_arch" ]; then | |
| api_json="$(curl -fsSL https://api.github.com/repos/ssut/payload-dumper-go/releases/latest || true)" | |
| asset_url="$( | |
| printf '%s' "$api_json" | jq -r --arg arch "$asset_arch" ' | |
| .assets[]? | |
| | select(.name | test("linux"; "i")) | |
| | select(.name | test($arch; "i")) | |
| | select(.name | test("tar.gz|tgz|zip"; "i")) | |
| | .browser_download_url | |
| ' | head -n1 | |
| )" | |
| if [ -n "$asset_url" ] && [ "$asset_url" != "null" ]; then | |
| pkg="$tmp/payload-dumper-go.pkg" | |
| if [ "$VERBOSE" = "1" ]; then | |
| curl -fL "$asset_url" -o "$pkg" | |
| else | |
| curl -fsSL "$asset_url" -o "$pkg" >>"$SETUP_LOG" 2>&1 | |
| fi | |
| filetype="$(file -b "$pkg" || true)" | |
| case "$asset_url" in | |
| *.zip) | |
| quiet_run "Extracting payload-dumper-go" unzip -o "$pkg" -d "$tmp" | |
| ;; | |
| *.tar.gz|*.tgz) | |
| quiet_run "Extracting payload-dumper-go" tar -xzf "$pkg" -C "$tmp" | |
| ;; | |
| *.tar.xz) | |
| quiet_run "Extracting payload-dumper-go" tar -xJf "$pkg" -C "$tmp" | |
| ;; | |
| *) | |
| if echo "$filetype" | grep -qi "Zip archive"; then | |
| quiet_run "Extracting payload-dumper-go" unzip -o "$pkg" -d "$tmp" | |
| elif echo "$filetype" | grep -qi "gzip compressed"; then | |
| quiet_run "Extracting payload-dumper-go" tar -xzf "$pkg" -C "$tmp" | |
| elif echo "$filetype" | grep -qi "XZ compressed"; then | |
| quiet_run "Extracting payload-dumper-go" tar -xJf "$pkg" -C "$tmp" | |
| else | |
| warn "Unknown payload-dumper archive type. Trying fallback extraction." | |
| tar -xzf "$pkg" -C "$tmp" >>"$SETUP_LOG" 2>&1 || unzip -o "$pkg" -d "$tmp" >>"$SETUP_LOG" 2>&1 || true | |
| fi | |
| ;; | |
| esac | |
| pdg_bin="$(find "$tmp" -type f -name 'payload-dumper-go' | head -n1 || true)" | |
| if [ -n "$pdg_bin" ]; then | |
| chmod +x "$pdg_bin" | |
| $SUDO cp "$pdg_bin" /usr/local/bin/payload-dumper-go | |
| ok "payload-dumper-go installed" | |
| return 0 | |
| fi | |
| fi | |
| fi | |
| warn "Binary install failed. Trying Go fallback." | |
| if ! need_cmd go; then | |
| apt_update_once | |
| quiet_run "Installing Go fallback tools" \ | |
| $SUDO env DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a \ | |
| apt-get install -y -qq --no-install-recommends golang-go git | |
| fi | |
| gobin="$TOOLS_DIR/go-bin" | |
| mkdir -p "$gobin" | |
| quiet_run "Building payload-dumper-go" \ | |
| env GOBIN="$gobin" go install github.com/ssut/payload-dumper-go@latest | |
| if [ -f "$gobin/payload-dumper-go" ]; then | |
| chmod +x "$gobin/payload-dumper-go" | |
| $SUDO cp "$gobin/payload-dumper-go" /usr/local/bin/payload-dumper-go | |
| ok "payload-dumper-go installed using Go fallback" | |
| else | |
| fail "payload-dumper-go install failed" | |
| exit 1 | |
| fi | |
| } | |
| format_size() { | |
| local bytes="${1:-}" | |
| if [ -n "$bytes" ] && echo "$bytes" | grep -Eq '^[0-9]+$'; then | |
| numfmt --to=iec --suffix=B "$bytes" 2>/dev/null || echo "$bytes bytes" | |
| else | |
| echo "Unknown" | |
| fi | |
| } | |
| get_remote_size() { | |
| curl -fsIL --max-time 20 "$URL" 2>/dev/null \ | |
| | awk 'tolower($1)=="content-length:" {s=$2} END {gsub("\r","",s); print s}' | |
| } | |
| download_rom() { | |
| local remote_size | |
| remote_size="$(get_remote_size || true)" | |
| echo | |
| echo -e "${C_BOLD}ROM download${C_RESET}" | |
| echo -e "${C_GRAY}────────────────────────────────────────${C_RESET}" | |
| echo -e "File : ${C_BOLD}$OUT${C_RESET}" | |
| echo -e "Size : ${C_BOLD}$(format_size "$remote_size")${C_RESET}" | |
| echo -e "Output : ${C_BOLD}$DOWNLOAD_DIR/$OUT${C_RESET}" | |
| echo -e "Connections : ${C_BOLD}$CONNECTIONS${C_RESET}" | |
| echo -e "Splits : ${C_BOLD}$SPLITS${C_RESET}" | |
| echo -e "Verbose : ${C_BOLD}$([ "$VERBOSE" = "1" ] && echo yes || echo no)${C_RESET}" | |
| echo -e "${C_GRAY}────────────────────────────────────────${C_RESET}" | |
| echo | |
| { | |
| echo "ROM download" | |
| echo "File : $OUT" | |
| echo "Size : $(format_size "$remote_size")" | |
| echo "Output : $DOWNLOAD_DIR/$OUT" | |
| echo "Connections : $CONNECTIONS" | |
| echo "Splits : $SPLITS" | |
| } >> "$REPORT" | |
| aria2c \ | |
| --continue=true \ | |
| --max-connection-per-server="$CONNECTIONS" \ | |
| --split="$SPLITS" \ | |
| --min-split-size="$CHUNK_SIZE" \ | |
| --dir="$DOWNLOAD_DIR" \ | |
| --out="$OUT" \ | |
| --max-tries=0 \ | |
| --retry-wait=5 \ | |
| --timeout=60 \ | |
| --connect-timeout=30 \ | |
| --lowest-speed-limit=10K \ | |
| --file-allocation=none \ | |
| --allow-overwrite=false \ | |
| --auto-file-renaming=false \ | |
| --summary-interval=0 \ | |
| --console-log-level=warn \ | |
| --download-result=hide \ | |
| --show-console-readout=true \ | |
| --human-readable=true \ | |
| --enable-color=true \ | |
| "$URL" | |
| echo | |
| ok "Download completed: $DOWNLOAD_DIR/$OUT" | |
| } | |
| file_info() { | |
| local rom="$DOWNLOAD_DIR/$OUT" | |
| info "Checking downloaded file" | |
| { | |
| echo | |
| echo "Downloaded file: $rom" | |
| echo "File type:" | |
| file "$rom" || true | |
| echo "File size:" | |
| du -h "$rom" || true | |
| echo "Free disk space:" | |
| df -h . || true | |
| } >> "$REPORT" | |
| ok "File check completed" | |
| } | |
| archive_list() { | |
| local rom="$1" | |
| local list_file="$2" | |
| : > "$list_file" | |
| case "${rom,,}" in | |
| *.zip) | |
| unzip -Z1 "$rom" > "$list_file" 2>>"$SETUP_LOG" || true | |
| ;; | |
| *.tgz|*.tar.gz|*.tar|*.tar.xz|*.tar.bz2) | |
| tar -tf "$rom" > "$list_file" 2>>"$SETUP_LOG" || true | |
| ;; | |
| *.7z) | |
| 7z l -ba "$rom" | awk '{print $NF}' > "$list_file" 2>>"$SETUP_LOG" || true | |
| ;; | |
| *) | |
| 7z l -ba "$rom" | awk '{print $NF}' > "$list_file" 2>>"$SETUP_LOG" || true | |
| ;; | |
| esac | |
| } | |
| detect_rom_type() { | |
| local rom="$1" | |
| local list_file="$ARCHIVE_LIST" | |
| info "Detecting ROM type" | |
| archive_list "$rom" "$list_file" | |
| { | |
| echo | |
| echo "Archive listing sample:" | |
| head -n 80 "$list_file" || true | |
| } >> "$REPORT" | |
| if grep -Eiq '(^|/)flash_all(\.bat|\.sh)?$|(^|/)images/.*\.img$|(^|/)boot\.img$|(^|/)init_boot\.img$' "$list_file"; then | |
| ok "Detected Fastboot/direct image ROM" | |
| echo "FASTBOOT_OR_DIRECT_IMAGES" | |
| return | |
| fi | |
| if grep -Eiq '(^|/)payload\.bin$' "$list_file"; then | |
| ok "Detected Recovery/OTA payload ROM" | |
| echo "RECOVERY_PAYLOAD" | |
| return | |
| fi | |
| if grep -Eiq 'META-INF/com/google/android|payload_properties\.txt|care_map\.pb' "$list_file"; then | |
| ok "Detected Recovery/OTA-like ROM" | |
| echo "RECOVERY_OTA_NO_PAYLOAD_VISIBLE" | |
| return | |
| fi | |
| if file "$rom" | grep -Eiq 'Android sparse image|data'; then | |
| warn "ROM type is unknown or raw image-like" | |
| echo "UNKNOWN_OR_RAW_IMAGE" | |
| return | |
| fi | |
| warn "ROM type is unknown" | |
| echo "UNKNOWN" | |
| } | |
| extract_archive_full() { | |
| local rom="$1" | |
| local dest="$2" | |
| mkdir -p "$dest" | |
| info "Extracting ROM archive" | |
| if [ "$VERBOSE" = "1" ]; then | |
| case "${rom,,}" in | |
| *.zip) unzip "$rom" -d "$dest" ;; | |
| *.tgz|*.tar.gz) tar -xzf "$rom" -C "$dest" ;; | |
| *.tar.xz) tar -xJf "$rom" -C "$dest" ;; | |
| *.tar.bz2) tar -xjf "$rom" -C "$dest" ;; | |
| *.tar) tar -xf "$rom" -C "$dest" ;; | |
| *.7z) 7z x "$rom" -o"$dest" -y ;; | |
| *) 7z x "$rom" -o"$dest" -y || unzip "$rom" -d "$dest" ;; | |
| esac | |
| else | |
| case "${rom,,}" in | |
| *.zip) unzip -q "$rom" -d "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| *.tgz|*.tar.gz) tar -xzf "$rom" -C "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| *.tar.xz) tar -xJf "$rom" -C "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| *.tar.bz2) tar -xjf "$rom" -C "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| *.tar) tar -xf "$rom" -C "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| *.7z) 7z x "$rom" -o"$dest" -y >>"$SETUP_LOG" 2>&1 ;; | |
| *) 7z x "$rom" -o"$dest" -y >>"$SETUP_LOG" 2>&1 || unzip -q "$rom" -d "$dest" >>"$SETUP_LOG" 2>&1 ;; | |
| esac | |
| fi | |
| ok "Archive extracted" | |
| } | |
| decompress_known_images() { | |
| local dir="$1" | |
| local found=0 | |
| info "Checking compressed image files" | |
| while IFS= read -r -d '' f; do | |
| found=1 | |
| lz4 -df "$f" "${f%.lz4}" >>"$SETUP_LOG" 2>&1 || true | |
| done < <(find "$dir" -type f -iname "*.img.lz4" -print0 2>/dev/null) | |
| while IFS= read -r -d '' f; do | |
| found=1 | |
| zstd -df "$f" -o "${f%.zst}" >>"$SETUP_LOG" 2>&1 || true | |
| done < <(find "$dir" -type f -iname "*.img.zst" -print0 2>/dev/null) | |
| while IFS= read -r -d '' f; do | |
| found=1 | |
| brotli -df "$f" >>"$SETUP_LOG" 2>&1 || true | |
| done < <(find "$dir" -type f -iname "*.img.br" -print0 2>/dev/null) | |
| while IFS= read -r -d '' f; do | |
| found=1 | |
| gzip -dkf "$f" >>"$SETUP_LOG" 2>&1 || true | |
| done < <(find "$dir" -type f -iname "*.img.gz" -print0 2>/dev/null) | |
| if [ "$found" = "1" ]; then | |
| ok "Compressed images processed" | |
| else | |
| ok "No compressed boot images found" | |
| fi | |
| } | |
| extract_payload_selected() { | |
| local input="$1" | |
| mkdir -p "$PAYLOAD_OUT" | |
| info "Reading payload partitions" | |
| if payload-dumper-go -l "$input" > "$WORKDIR/payload_partitions.txt" 2>>"$SETUP_LOG"; then | |
| ok "Payload is readable" | |
| else | |
| warn "Payload listing failed. This may be an incremental/delta OTA." | |
| return 1 | |
| fi | |
| cat "$WORKDIR/payload_partitions.txt" >> "$REPORT" | |
| info "Extracting selected boot partitions" | |
| if [ "$VERBOSE" = "1" ]; then | |
| payload-dumper-go \ | |
| -c "$PDG_WORKERS" \ | |
| -o "$PAYLOAD_OUT" \ | |
| -p "$TARGET_PARTITIONS" \ | |
| "$input" | |
| else | |
| payload-dumper-go \ | |
| -c "$PDG_WORKERS" \ | |
| -o "$PAYLOAD_OUT" \ | |
| -p "$TARGET_PARTITIONS" \ | |
| "$input" >>"$SETUP_LOG" 2>&1 || true | |
| fi | |
| ok "Payload extraction step completed" | |
| } | |
| find_payload_input_after_extract() { | |
| find "$EXTRACT_DIR" -type f -name "payload.bin" | head -n1 || true | |
| } | |
| collect_needed_images() { | |
| info "Collecting boot images" | |
| local search_roots=("$EXTRACT_DIR" "$PAYLOAD_OUT") | |
| local copied=0 | |
| local root f base parent dest | |
| for root in "${search_roots[@]}"; do | |
| [ -d "$root" ] || continue | |
| while IFS= read -r -d '' f; do | |
| base="$(basename "$f")" | |
| case "$base" in | |
| boot.img|init_boot.img|vendor_boot.img|vendor_kernel_boot.img|dtbo.img|vbmeta.img|vbmeta_system.img|vbmeta_vendor.img|recovery.img) | |
| parent="$(basename "$(dirname "$f")")" | |
| dest="$NEEDED_DIR/$base" | |
| if [ -e "$dest" ]; then | |
| dest="$NEEDED_DIR/${parent}_${base}" | |
| fi | |
| cp -av "$f" "$dest" >>"$REPORT" 2>&1 | |
| copied=$((copied + 1)) | |
| ;; | |
| esac | |
| done < <(find "$root" -type f -print0 2>/dev/null) | |
| done | |
| if [ "$copied" -gt 0 ]; then | |
| ok "Collected $copied image file(s)" | |
| else | |
| warn "No boot-related image was found" | |
| fi | |
| } | |
| summarize_result() { | |
| echo | |
| echo -e "${C_BOLD}Result${C_RESET}" | |
| echo -e "${C_GRAY}────────────────────────────────────────${C_RESET}" | |
| echo -e "Images folder : ${C_BOLD}$NEEDED_DIR${C_RESET}" | |
| echo -e "Report : ${C_BOLD}$REPORT${C_RESET}" | |
| echo -e "Setup log : ${C_BOLD}$SETUP_LOG${C_RESET}" | |
| echo -e "${C_GRAY}────────────────────────────────────────${C_RESET}" | |
| if find "$NEEDED_DIR" -maxdepth 1 -type f | grep -q .; then | |
| echo | |
| find "$NEEDED_DIR" -maxdepth 1 -type f -printf " %f %k KB\n" | sort | |
| echo | |
| ok "Done" | |
| echo | |
| echo "To compress for download:" | |
| echo " tar -czf needed_images.tar.gz -C '$WORKDIR' needed_images" | |
| else | |
| echo | |
| warn "No boot image was extracted. Check report/log files for details." | |
| fi | |
| { | |
| echo | |
| echo "DONE" | |
| echo "Needed images folder: $NEEDED_DIR" | |
| echo "Found images:" | |
| find "$NEEDED_DIR" -maxdepth 1 -type f -printf "%f\t%k KB\n" | sort || true | |
| } >> "$REPORT" | |
| } | |
| main() { | |
| local rom rom_type payload_bin | |
| print_header | |
| install_packages | |
| install_payload_dumper_go | |
| download_rom | |
| file_info | |
| rom="$DOWNLOAD_DIR/$OUT" | |
| rom_type="$(detect_rom_type "$rom" | tail -n1)" | |
| case "$rom_type" in | |
| RECOVERY_PAYLOAD) | |
| extract_payload_selected "$rom" || { | |
| warn "Direct payload extraction failed. Extracting archive first." | |
| extract_archive_full "$rom" "$EXTRACT_DIR" | |
| payload_bin="$(find_payload_input_after_extract)" | |
| if [ -n "$payload_bin" ]; then | |
| extract_payload_selected "$payload_bin" || true | |
| fi | |
| } | |
| ;; | |
| FASTBOOT_OR_DIRECT_IMAGES) | |
| extract_archive_full "$rom" "$EXTRACT_DIR" | |
| decompress_known_images "$EXTRACT_DIR" | |
| payload_bin="$(find_payload_input_after_extract)" | |
| if [ -n "$payload_bin" ]; then | |
| extract_payload_selected "$payload_bin" || true | |
| fi | |
| ;; | |
| RECOVERY_OTA_NO_PAYLOAD_VISIBLE|UNKNOWN|UNKNOWN_OR_RAW_IMAGE) | |
| extract_archive_full "$rom" "$EXTRACT_DIR" || true | |
| decompress_known_images "$EXTRACT_DIR" | |
| payload_bin="$(find_payload_input_after_extract)" | |
| if [ -n "$payload_bin" ]; then | |
| extract_payload_selected "$payload_bin" || true | |
| fi | |
| ;; | |
| esac | |
| collect_needed_images | |
| summarize_result | |
| } | |
| main "$@" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
BootX
Fast one-command Linux script for downloading Xiaomi/Android ROMs and extracting useful boot images.
Best for GitHub Codespaces, VPS, Ubuntu, Debian, or WSL.
Extracted images
boot.imginit_boot.imgvendor_boot.imgvendor_kernel_boot.imgdtbo.imgvbmeta.imgrecovery.imgRun directly from raw Gist
Replace
GIST_RAW_BOOTX_URLwith the raw URL ofbootx.sh.Example:
Download first, then run locally
Or with
wget:Speed options
Faster:
More stable:
Verbose mode
By default, setup logs are hidden for a clean console.
Output
Final images:
Logs:
Compress the result:
Notes
init_boot.img.boot.img.