Booting Gentoo from SAR-Preinit; or Debugging the init, the Hard Way
Posted on ·Table of Contents
As you would know from my previous blog, I couldn't make the UART work for my phone. Since without a serial console, the boot-up process is no less than a black-box, I decided to use some hacky debugs for finding out what went wrong with the original preinit
. If you're not in for the process of going through it and just want to cut to the chase, jump onto this section.
Circumventing System-As-Root
So, flashing a preinit
failed for me. Again this was because of the changes in the boot-process of newer Android devices. If you have no clue about this, I would recommend reading this blog.
What we needed to change was the behaviour of our kernel to take the ramdisk
provided to it in the boot.img
as its rootfs
. @topjohnwu suggested in his infamous xda comment that it could be achieved by substituting the skip_ramdisk
string with any other. I tried doing this but it make the device boot straight up to Lineage (which we do not want).
Then I looked into what goes on under-the-hood when Magisk is flashed. It seems that Magisk hexpatches the kernel with some specfic strings which ultimately leads the kernel to take the ramdisk inside boot.img
as its rootfs
.
I double checked by cpio'ing the magiskinit64
binary into an ramdisk.cpio
incpio and then patching the kernel image using magiskboot
, in a similar fashion to that of Magisk. Then packed the stuff into a boot.img
(ofc including a bootimg.cfg).
Now remember, since we have patched the kernel, the kernel would take the magiskinit64
as its init and exec it. Then magiskinit64
would ultimately mount /system
as root and exec the /system/bin/init
thus entering the Android land.
And so we did. Lineage booted up. To cross-check, I also tried to boot using a boot.img without magiskinit64
as its init. It did not reach the Android land.
And so I adopted this approach for circumventing SAR. But using preinit
as the init inside boot.img
still did not boot Gentoo up. So we come to the debugging phase.
The Debugging Phase (skippable)
The lack of a serial console, made me come up with some ugly debugs. First I tried to access the last_kmsg
and console-ramoops-0
for getting the kernel logs from the previous reboot. But I didn't get any. I double checked my kernel defconfig whether I had the correct options enabled and yes they were.
At this point, I wan't even unhappy. Time for a new debug method. What occured to me next was that we could sleep
the init script between certain steps and time the process of my phone bootlooping. For a reference value, I recorded the time it took my phone to boot-loop without any sleep
. I prepared myself for a night of constant phone reboots. The table below describes the entire process until finally booting Gentoo with insightful comments at the end.
Attempt | Time (in sec) | Remarks | Commit |
---|---|---|---|
1 | 10 | reference | link |
2 | 20 | test sleep | link |
3 | 30 | failed to mount at /userdata | link |
4 | 41 | kernel panics | link |
5 | 41 | abandoning this approach | link |
6 | 21 | couldn't mount /dev | link |
7 | 35 | /dev is mounted | link |
8 | 60+ | Gentoo boots | link |
- At this point, I found out that the kernel could mount the userdata partition. I also realised that I was not getting last_ksmg because the kernel was not panicking and instead just
exit
ing. So I tried to get thelast_kmsg
next. - I tried to forcefully panic the kernel. And got the
last_kmsg
andconsole-ramoops-0
in the next boot. But they didnt have the parts where kernel logged the Preinit messages. So I thought that giving them a higher priority would make them get picked by thelast_kmsg
and it didn't help either. - Finally I abandoned this approach.
- Then I looked into mounting the pseudo-filesystems. I realised that the kernel could not mount /dev.
- I realised that using
tmpfs
instead ofdevtmpfs
mounts the/userdata
. What I did not know at that time that my kernel did not have the options fordevtmpfs
enabled in itsdefconfig
, this all could be avoided. /dev
mounts now, but we have to populate it as well.
I did not have just 8 attempts, the commit history would show that I forgot that my kernel was SELinux Enforcing, I had to change that among many other things. Robert Landley's blogs on initramfs helped me get to know the very basics of an initramfs.
Final comments and What to follow next
My sar-preinit repository holds the current workflow of getting a SAR-enabled device boot Gentoo in the Android based device. The Makefile is pretty self-explanatory but still, if you want to follow the process:
- Install Gentoo in you phone following this blog.
- Extract the
boot.img
from you Android phone. At the time of writing this blog, we dont have changingselinux
modes automated. Please make sure that you do that first by addingandroidboot.selinux=permissive
string at the end of the kernel commandline inbootimg.cfg
. - Rename
boot.img
toogboot.img
and place it inside the artifacts folder. - Fire up a terminal and run
make bootimg_chute
- Flash the
boot_mod.img
created inside theout
directory on your phone, preferably usingfastboot boot
, if you're not that confident.fastboot boot
somehow doesn't work for my device, but that's going off-track. - Since we haven't figured out the Android in LXC part yet, the best you could do to check your Gentoo boot, is to reboot into the recovery, fire up adb and check the
/data/gnu/var/log/
directory fordmesg
or any other logs.
I plan to merge this entire workflow into SharkBait, so that you don't have to go through the hassle of doing it all.
I should have already mentioned this somewhere, but if I didn't, I should tell the readers that all is based on the SharkBaitOS established mostly by @KireinaHoro. The preinit
I used as a template was the original one from SharkBaitOS. In order to have a better understanding about this project I would recommend the readers to have a look at KireinaHoro's Blogs as well.
In my next blog, I will discuss about getting Android 9+ to work inside a LXC-Container, in the Gentoo land. I have yet to achieve doing that myself. Hopefully we will reach there soon.
Until then, Happy Hacking !