I decided to write this because I could not find a decent guide on how to flash a recent firmware on a modern (and by modern I mean the last 5 years) Samsung phone under linux. Normally to flash a new firmware on most android phones you’ll just use fastboot but on Samsung branded phones you can’t, they use a proprietary protocol but the process is similar, just reboot the phone into their fastboot version called “Download Mode” and use a compatible software to flash the necesary partitions on the device, on linux that compatible software is heimdall.

What you need:

  • A firmware package, can be downloaded using something like Samloader.
  • Heimdall-grimler, a working fork can be downloaded here.

The firmware is just a big zip file with five *.tar.md5 files inside it. The heimdall version linked above is a fork that is currently maintened of the original code, this is needed because it fixes flashing large partitions (ex: super.img) among other things.

Workflow:

  • Unpack the main firmware zip file.
  • Unpack the BL, AP, and CP tar files, then choose to unpack either the CSC (factory reset) or HOME_CSC (keep data) tar file.
  • Extract the .pit file located inside the CSC tar file.
  • Uncompress all the lz4 compressed images.
  • Use the extracted pit file to generate the partition’s names with their respective images to flash.
  • Use heimdall to flash all the extracted and decompressed images to the phone.

Here’s a bash script that does all that automatically:

#!/bin/bash
# inspired by: https://gist.github.com/Linux4/243e4aab83867e2b3f4322c2a0eb5a3e
# req: bash, unzip, sed, heimdall, lz4, tar

# file selection
if [[ $1 == *.zip ]] && [ -f "$1" ]; then
	# decompress main firmware zip
	echo -e "\033[1mUnpacking main firmware...\033[0m"
	unzip $1
else
	echo -e "\033[1mUsage:\033[0m heimdall.sh filename.zip"
	exit
fi

# hidden option, use -w to force wipe data
if [ "$2" ] && [ "$2" == "-w" ]; then
	CSC="CSC"
	echo -e "\n\033[1mFirwmare should wipe data.\033[0m"
else
	CSC="HOME"
	echo -e "\n\033[1mFirwmare should not wipe data.\033[0m"
fi

# extract pit file from CSC tar
echo -e "\n\033[1mExtracting pit file...\033[0m"
tar --wildcards --exclude='*/*' -xvf CSC*.md5 '*.pit'

# decompress the main tar files
for PART in BL AP CP "$CSC"; do
	echo -e "\n\033[1mUnpacking $PART...\033[0m"
	tar --wildcards --exclude='*/*' -xvf "${PART}"*.md5 '*.lz4'
	rm "${PART}"*.md5
done

# remove the unused CSC folder
if [ "$CSC" == "HOME" ]; then
	rm CSC*.md5
else
	rm HOME*.md5
fi

# unpack lz4
echo -e "\n\033[1mLZ4 Decoding...\033[0m"
for LZ4 in *.lz4; do
	unlz4 "$LZ4"
	rm -f "$LZ4"
done

# generate heimdall flash command
echo -e "\n\033[1mFlashing command:\n\033[0m"
echo -e "heimdall flash "$(heimdall print-pit --file *.pit | grep -e "Partition Name" -e "Flash Filename" | sed -e '1~2s/.*: /--/' -e '2~2s/.*: //' | sed '$!N;/--.*\n$/d;P;D' | tr -s '\n' ' ')
printf "\n"

Right before the script ends it’ll echo something similar to this:

heimdall flash --bootloader preloader.img --md5hdr md5.img --efs efs.img --sec_efs sec_efs.img --steady steady.bin --spmfw spmfw-verified.img --scp1 scp-verified.img --sspm_1 sspm-verified.img --uh uh.bin --tee1 tee-verified.img --tzar tzar.img --gz1 gz-verified.img --lk lk-verified.img --dpm_1 dpm-verified.img --audio_dsp audio_dsp-verified.img --mcupm_1 mcupm-verified.img --dtbo dtbo.img --vbmeta vbmeta.img --misc misc.bin --metadata metadata.img --md1img md1img.img --pi_img pi_img-verified.img --cam_vpu1 cam_vpu1-verified.img --cam_vpu2 cam_vpu2-verified.img --cam_vpu3 cam_vpu3-verified.img --param param.bin --up_param up_param.bin --boot boot.img --vendor_boot vendor_boot.img --init_boot init_boot.img --recovery recovery.img --vbmeta_system vbmeta_system.img --vbmeta_vendor vbmeta_vendor.img --efuse efuse.img --super super.img --prism prism.img --optics optics.img --cache cache.img --omr omr.img --userdata userdata.img

Take a good look at it because there’s a good chance that, even while the original .pit file is being used to generate the output command, the actual firmware package may not contain all the images listed in it.
Remove all the missing images from the generated output and you have a ready to go command to flash the firmware.

Set the phone to Download Mode (this is model dependant), in my case after powering it off I had to hold Vol-down+Power for ~7 seconds or use adb with adb reboot download.
Connect the phone to the computer and run the generated heimdall flash command.

Good luck.