Booting Gentoo from SAR-Preinit; or Debugging the init, the Hard WayPosted 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.
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
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
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|
|3||30||failed to mount at ||link|
|5||41||abandoning this approach||link|
|6||21||couldn't mount ||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
exiting. So I tried to get the
- I tried to forcefully panic the kernel. And got the
console-ramoops-0in 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 the
last_kmsgand 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
/userdata. What I did not know at that time that my kernel did not have the options for
devtmpfsenabled in its
defconfig, this all could be avoided.
/devmounts 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.imgfrom you Android phone. At the time of writing this blog, we dont have changing
selinuxmodes automated. Please make sure that you do that first by adding
androidboot.selinux=permissivestring at the end of the kernel commandline in
ogboot.imgand place it inside the artifacts folder.
- Fire up a terminal and run
- Flash the
boot_mod.imgcreated inside the
outdirectory on your phone, preferably using
fastboot boot, if you're not that confident.
fastboot bootsomehow 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
dmesgor 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 !