-
-
Save Keyaku/e9252e8a1f134a0fab635074a567920a to your computer and use it in GitHub Desktop.
Flash Samsung factory image packages on Linux
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 | |
# Flash Samsung factory image packages on Linux | |
# Original Author: Linux4 (https://github.com/Linux4) | |
# Original Gist: https://gist.github.com/Linux4/243e4aab83867e2b3f4322c2a0eb5a3e | |
readonly SCRIPT="$(realpath "$0")" | |
readonly SCRIPT_NAME=$(basename "$SCRIPT") | |
readonly usage=( | |
"Usage: $SCRIPT_NAME [OPTIONS] <zip>" | |
"Flash Samsung factory image packages on Linux" | |
"Example: $SCRIPT_NAME SM-G960F_OXM_G960FXXU9FUE3.zip" | |
"Arguments:" | |
" [-h|--help] : Show this help message" | |
" [-f|--file] <zip> : Path to the factory image package" | |
" [-c|--clean] : Clean working directory" | |
" [-w|--wipe] : Wipe data partition" | |
) | |
### Functions | |
# Checks if file is a valid zip archive | |
function is_zip { | |
local -r zipfile="$(realpath "$1" 2>/dev/null)" | |
[[ -f "$zipfile" ]] && [[ "$zipfile" == *.zip ]] && file "$zipfile" | \grep -q "Zip archive data" | |
} | |
# Checks if given commands are installed | |
function command-has { | |
## function logic | |
local retval=0 | |
local -a non_installed=() | |
while (( $# )); do | |
## If command is not installed, add to non_installed array | |
if ! command -v "$1" &>/dev/null; then | |
non_installed+=("$1") | |
fi | |
shift | |
done | |
## If any command is not installed, return 1 | |
if (( ${#non_installed[@]} )); then | |
>&2 echo "Error: Please install the following packages:" | |
>&2 printf "\t%s\n" "${non_installed[*]}" | |
retval=1 | |
fi | |
return $retval | |
} | |
# Get partition name from PIT file | |
function get_partition { | |
local -r pit="$1" | |
local -r part="$2" | |
./firmware-update/tools/pithelper/get-pit-partition "$pit" "$part" | |
} | |
### Main | |
# Check for required commands | |
typeset -a REQUIREMENTS=(git g++ heimdall lz4 make unzip) | |
command-has "${REQUIREMENTS[@]}" || exit 1 | |
# Argument parsing | |
VALID_ARGS=$(getopt -o chwf: --long clean,help,wipe,file: -- "$@") | |
eval set -- ${VALID_ARGS} | |
(( ! $# )) && echo "${usage[0]}" && exit 1 | |
while (( $# )); do | |
case "$1" in | |
-h|--help) | |
b_help=y | |
break | |
;; | |
-f|--file) | |
shift | |
if is_zip "$1"; then | |
ZIP="$(realpath "$1")" | |
else | |
>&2 echo "Invalid zip file: '$1'" | |
fi | |
;; | |
-w|--wipe) | |
b_wipe=y | |
;; | |
-c|--clean) | |
# Clean working directory | |
b_clean=y | |
;; | |
# Positional arguments | |
--) : # shift; break | |
;; | |
*) | |
if is_zip "$1"; then | |
ZIP="$(realpath "$1")" | |
else | |
>&2 echo "Invalid argument: '$1'" | |
fi | |
;; | |
esac | |
shift | |
done | |
# Argument validation | |
if [[ -z "$ZIP" ]] || [[ "$b_help" =~ y(es)? ]]; then | |
[[ -z "$ZIP" ]] && >&2 echo "Error: No zip file specified" | |
>&2 printf "%s\n" "${usage[@]}" | |
[[ "$b_help" =~ y(es)? ]]; exit $? | |
fi | |
# Set working directory | |
workdir="${ZIP%.*}" | |
[[ "$b_clean" =~ y(es)? ]] && rm -rf "$workdir" | |
[[ ! -d "$workdir" ]] && mkdir "$workdir" | |
cd "$workdir" | |
# Unpack the zip file and respective tar files | |
[[ "$b_wipe" =~ y(es)? ]] && CSC="CSC" || CSC="HOME_CSC" | |
for fw_part in BL AP CP "$CSC"; do | |
echo "Unpacking $fw_part" | |
unzip "$ZIP" "${fw_part}*" | |
tar xf "${fw_part}"*.md5 | |
rm "${fw_part}"*.md5 | |
done | |
# Extract PIT which is only in regular CSC package, not HOME_CSC | |
[[ "$b_wipe" =~ y(es)? ]] || unzip -p "$ZIP" "CSC*" | tar xf - --wildcards "*.pit" | |
for LZ4 in *.lz4; do | |
lz4 -d "$LZ4" | |
rm -f "$LZ4" | |
done | |
PIT="$(ls *.pit)" | |
echo "Using PIT $PIT" | |
[[ ! -d firmware-update ]] && git clone https://github.com/Linux4/firmware-update | |
make -C firmware-update/tools/pithelper | |
typeset -a HEIMDALL_CMD | |
for fw_part in *; do | |
[[ ! -f "$fw_part" ]] && continue | |
[[ "$fw_part" == "$PIT" ]] && continue | |
fw_partname="$(basename $fw_part)" | |
[[ "$b_wipe" =~ n(o)? ]] && [[ "$fw_partname" == "userdata.img" ]] && continue | |
PARTITION="$(get_partition $PIT $fw_partname)" | |
[[ -z "$PARTITION" ]] && echo "Error: $fw_part not assigned to any partition" && exit 1 | |
HEIMDALL_CMD+=(--${PARTITION} ${fw_part}) | |
done | |
heimdall flash --verbose ${HEIMDALL_CMD[@]} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment