Patching a Samsung device with a custom Kernel
In my last tutorial, I’ve explained step by step how to compile a custom Samsung Kernel, I highly recommend you go through that guide before you read this one, as it has some important steps on how to prepare your environment. Now, in this guide, I will be covering how to flash the kernel that we have already compiled.
Disclaimer: Flashing a custom image on your phone, either by following this tutorial or by rooting your phone will void your warranty by irreversibly blowing an eFuse on the device.
Preparing the environment
For this guide, I assume that you have your target device both unlocked and rooted. If not, this guide will help you accomplish that. You will download both a cache.img file and a recovery.img file during this process, which I advise you to keep, as you will need it to flash your device without having to factory reset it.
So, in order for us to be able to flash the kernel we’ve just compiled, we’re going to need to get the device’s boot image, inside which resides the kernel zImage, which we can overwrite. This will also help if we want to restore the boot image to factory defaults.
There are two possible ways of achieving this:
- Backup the device’s image using a custom recovery.
- Dump the device’s boot image using “dd”.
We’ll only explore the second option, since for the first one there are already many tutorials. But first, we need to make sure we have everything ready.
First, make sure that both ADB and Heimdall are installed in your VM. These tools will help interact with the device remotely after boot and in download mode respectively.
sudo apt-get install heimdall-flash adb
A useful thing to do on our hypervisor (if possible) is to set it so it connects our target device to our VM automatically, which will save us a lot of time.
If you want to do this on VMware Fusion, go to Virtual Machine -> USB & Bluetooth -> USB & Bluetooth settings, and change the “Plug in action” for our target device so it connects to our linux machine. Of course for this, the device has to be connected. You will have to do this twice, once for adb (Once you have enabled the USB debugging) and once for Heimdall (on download mode).
Now, we need to enable USB debugging and OEM unlock our phone. In your device, go to “Settings” -> “About phone” -> “Software Information” and then touch 7 times on the “Build number”, which will enable the developer mode. After this, go back to the settings, open the “Developer options” and enable both the “OEM unlock” and the “USB debugging” options.
Make sure that the OEM unlock is always enabled, otherwise your phone won’t boot.
Disconnect and reconnect the USB cable on your device, authorize the ADB connection on it, and then when you run “adb devices” on a terminal you should see this:
We can also shell into the device, by using “adb shell”:
After enabling ADB, we need to make sure that Heimdall is working properly. For this you need to reboot your device into “download mode” which can be easily accomplished with ADB by executing “adb reboot download”. Otherwise, a button combination during boot will achieve the same goal. In the case of the S7, you need to hold center+power+volume down.
If everything went correctly, you should see something like this when you run “hemidall detect” and then “heimdall print-pit”:
Your device will reboot each time you use Heimdall, you can avoid this by using the switch “--no-reboot” however this is not advised, as Heimdall won’t work until you reboot your device, regardless of which functionality you used.
Acquiring the boot image
This is by far the easiest and quickest way to get our boot image, since it relies on tools that are available for us by default. We’re going to be using the “dd” tool.
First, shell into the device and elevate yourself using supersu:
Then, we need to get the correct mounting point. In order to do this, go to /dev/block/platform/ and list the contents, find the correct virtual folder inside (in my case it’s “155a0000.ufs”) and inside of it list the contents of the folder “by-name”, which should give you all the mappings between each partition and the mounting points.
As you can see, there’s an entry which is named “BOOT” and points to, in my case, /dev/block/sda5. We are going to dump it using the following command:
dd if=[mounting/point] of=[output/file.img]
Which in my case would be:
dd if=/dev/block/sda5 of=/sdcard/Download/boot.img
And then, we can easily download it with “adb pull”
adb pull /sdcard/Download/boot.img .
Unpacking, overwriting, packing, flashing
Now that we have the boot image and our kernel, we have to unpack the boot image, overwrite the zImage, which contains the kernel with the one we have compiled, repack the boot image and flash it with Heimdall.
Unpack: To do this, we are going to use a tool called Android Image Kitchen or AIK. Which can be obtained from this thread. After downloading the file, we uncompress it somewhere, and we copy inside the boot image we have acquired from the device. Then we run “unpackimg.sh” against “boot.img”, and it will unpack it.
Overwrite: You will notice that two new folders have been created. “ramdisk” and “split_img“. The first contains the contents of what is going to be the root of the file system for our device once it boots, and the second contains other contents, including the kernel image. Go inside the split_img folder and find the file that ends with “zImage”, and overwrite it with the “Image” file we created when we compiled our kernel.
Repack: Once the kernel image is in place, we’ll need to repack it to flash it back to our device. For this, we’ll go back to the root of AIK-Linux and run “./repackimg.sh”, which will automatically create a file called “image-new.img” which will be our new boot image.
Flash: Now that we have our new image, we can go ahead and flash it to our device. To do this, we need to put it on download mode, and use heimdall to flash it. However, it’s highly recommended that you also flash the recovery and cache imgs that you acquired during the rooting process, otherwise it’s likely that you will need to factory reset your device.
I wrote this little script which will accomplish all four steps at once:
cp ../samsung-kernel/arch/arm64/boot/Image split_img/boot.img-zImage
adb reboot download
heimdall flash --BOOT image-new.img --RECOVERY ../Downloads/recovery.img --CACHE ../Downloads/cache.img
This of course assumes that you are executing it on the AIK folder and that both the recovery.img and the cache.img are in your Downloads folder. Take notice that the partition names (“BOOT”, “RECOVERY” and “CACHE”) are both capitalized and case-sensitive.
Your device will reboot a couple of times, and after we shell into it, if you do “uname -a” you’ll see the follwing:
As you can see, we have successfully flashed our custom Kernel!
What could go wrong?
So, you’ve just finished flashing your new kernel, and you’ve run into problems. These are a few things that I’ve had trouble with, and how to solve them:
- Stuck in a boot loop. After flashing your boot image, your device is stuck in a boot loop, try doing a factory reset via the recovery mode. This can be accessed in different ways in each device. In my case, you have to hold power + volume up + home button until you get an android screen, and then repeatedly press volume up until you get the recovery screen.
- The device got stuck on the boot sequence. Have you tried turning it off and on again? :D
- If nothing works, you can check the kmsg log on /proc/last_kmsg. For this, I recommend flashing a TWRP recovery rom, booting into it, and copying it out.