Star date: 2014.138
Flashing custom kernels can break your device. If something goes wrong it's not my fault. I guarantee nothing. Also note that this will likely trips warranty flags like the Knox feature that detects when you have flashed any custom images.
I prefer to flash kernels, roms, recoveries etc. with Odin, but I'm sure that if you know what you're doing you can use other methods. My setup is that I have the android device plugged into a Windows desktop, and then I run a Linux virtual machine where I do the actual work. I use VirtualBox with a shared directory so they can easily access the same files. Generally when I say to run a command or something I mean on the Linux VM, but any reference to Odin or Kies assumes it is running on Windows.
I am assuming that your android device is already rooted.
As part of my effort to turn a Galaxy Note Pro into a Linux laptop
I compiled a custom kernel that allows SELinux (or SE for Android as it is called in the device settings) mode to be
changed to permissive. In the interest of making the minimum possible changes I did not completely disable SELinux or
change the default mode. Instead I just disabled the flag that stops you from switching between enforcing and
permissive modes. In Android 4.4 Google started using enforcing mode which actually enforces the SELinux policy
(ie: if you do something that the policy does not want you to do you get a permission error even if you are root
user) instead of permissive. In permissive mode you can violate the SELinux policy all you want and the system just
writes logs instead of giving permission errors. Samsung's recent devices build upon that with some of their own security
features, including a flag that makes it so you cannot switch the SELinux policy without rebuilding the kernel. There
is a command called setenforce
which toggles modes, and there are some apps on the Google Play store which do the
same thing, but none of them will work until we modify the kernel.
This process has specifically been done on a Galaxy Note Pro SM-P900 but it may work on other devices as well.
Since the Linux kernel is GPL software, Samsung legally has to release the kernel source to their devices. That means you can simply go to opensource.samsung.com and search for "SM-P900" and then choose your specific device version. Even though Linux kernels aren't very big the download will be gigantic because it includes a lot more in it than just the kernel. While you're waiting for the download you can move on to the next step.
Since you are probably on an x86 environment but compiling for ARM you need a cross compiler. The easiest way to set that
up is to download the Android NDK which exists precisely for
this purpose. On my system, I extracted the ndk to ~/android/ndk
.
Once your download from opensource.samsung.com is complete, you can extract the kernel directory to ~/android/kernel
.
There should also be a file called README_Kernel.txt
. I recommend you also copy that to ~/android
as it has some
concise and useful info in it.
Open up ~/android/kernel/security/selinux/Makefile
and you will see a line near the top that looks like this:
EXTRA_CFLAGS += -DCONFIG_ALWAYS_ENFORCE=true
All you have to do is change true
to false
.
We got a cross compiler when we extracted the NDK, we just need to specify precisely where it is before we compile. To
do that we need to create an environment variable called CROSS_COMPILE
.
export CROSS_COMPILE=~/android/ndk/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
Notice that the path just ends part way through a file name. This is intentional. CROSS_COMPILE
should indicate the
prefix of a group of files in that directory. There are other versions of arm-linux-androideabi-* but from my tests
4.6 is the only one that works. Not suprisingly, the forementioned README says to use 4.6. That's why you should RTFM.
There are about a hundred billion settings that you can choose from when building a linux kernel, so Samsung provides the exact config that you need to use so that the kernel will work on your device. To apply the config run this command:
cd ~/android/kernel
make ARCH=arm v1awifi_00_defconfig
This should create a file called .config
. For our purposes we don't need to change this file, but if you do have some
tweaks you want to make then you can edit .config
directly, but there is a better way. Normally you want to edit it
by running make menuconfig
. Menuconfig requires that you have libncurses in addition to standard build tools. If you
are doing this on a different device then v1awifi_00_defconfig
probably does not exist. This is just the name of a
template config file stored in arch/arm/configs
so you can always check in that directory.
Now you're ready to actually compile. Just run this command from ~/android/kernel
:
make ARCH=arm -jN
Replace the N
in -jN
with the number of processors you have plus one. For example, if you have 4 cores then enter 5.
I'm not really sure if it's better to consider hyperthreaded cores as 1 or 2. I'll leave that for you to experiment,
it only affects performance. If it succeeds then the last line of the output should look like:
Kernel: arch/arm/boot/zImage is ready
If you did not get an error, but you don't see that message it likely means that you actually did get an error but since
there were parallel build processes the error wound up somewhere further up on the screen. You can just scroll up or
rebuild with -j1
.
The zImage
file is your kernel blob, but you can't just directly flash that do your device. The boot partition actually
expects two things: a kernel zImage, and a ramdisk that is used to initialize the system. Instead of making our own
ramdisk it is much easier to extract the one that already exists in the stock boot.img. To do this we're going to need
the tools to pack/unpack boot.img files, and we'll need the stock boot.img.
CNexus generously posted a zip file on xda-developers in
this thread called bootimg_tools_7.8.13.zip
. You can
simply extract those files to ~/bin
(assuming ~/bin
is in your path).
If you already have a stock rom for your device you can usually just open the archive and there will be a file called
boot.img. If you don't have one you can try telling Kies to install an emergency recovery and it will download the stock
rom to your %temp%
directory, then decrypt it as a ~2GB zip file in the same directory. If you quickly copy that zip
file to any other directory before Kies deletes it then you can open it up and grab the boot.img.
If you don't have access to a stock rom, then you can just extract the boot.img from your device. The trick is finding
out where to get it. On my device I knew that it had to be one of the block devices in /dev/block/mmcblk0p*
so I just
wrote a script to try every single one of them until the data looked right. It turns out the on my version of the
SM-P900 it is /dev/block/mmcblk0p9
so I was able to extract it to my SD card by running this command locally on the
tablet as the root user:
dd if=/dev/block/mmcblk0p9 of=/sdcard/stock_boot.img
Once you have gotten the stock boot.img off your device, you can copy it to ~/android/stock/boot.img
. Then run the
following commands:
cd ~/android/stock
umkbootimg boot.img
mkdir ~/android/custom
cd ~/android/custom
cp ../stock/initramfs.cpio.gz .
cp ~/android/kernel/arch/arm/boot/zImage .
mkbootimg --kernel zImage --ramdisk initramfs.cpio.gz --output boot.img
tar -cf my_custom_kernel.tar boot.img
That last command creates the tar file that you can flash with Odin.
If you use Odin (I had success with Odin 3.07 my SM-P900) then do the following:
my_custom_kernel.tar
.If all went well the device should restart. If you go to Settings -> About Device then the kernel version section you should see your_username@your_linux_computer_name which indicates that the custom kernel has been applied. Below that there is a section that says "SE for Android status" which should still say "Enforcing". Now just open a terminal (I use JuiceSSH) and run the following:
su
setenforce 0
Go back to settings and navigate away from "About Device" and back again to force it to refresh and it should now say "Permissive". Horay!
I noticed that on my device any time I flash a custom compiled kernel (even if I make no changes to the source or
configuration) the wifi gets a little screwy. After a lot of searching I found that this happens on some other Samsung
devices as well. The problem was not super obvious at first as the wifi seemed to work, but it takes way longer to
connect, it doesn't remember any passwords when your reboot the device, and when you try to switch between networks it
sometimes stops working entirely until you restore the stock kernel. Luckily, it doesn't seem to be an actual driver
issue but something related to their secure password storage functionality. If you simply open up /system/build.prop
and change ro.securestore.support
from true
to false
everything seems to function fine after a reboot.