It's relatively simple to add very basic support for devices (like a tablets or smartphones) in Linux.
This article will give some tips on how to do that, as there are some knowledge specific to Android smartphones and tablets that are worth mentioning.
If you already did that kind of things, this article might still be interesting because it mention how to work around smartphone specific issues we are aware of.
Newer devices with a device trees in a vendor kernel¶
Some newer devices that already have a devicetree. In that case you probably need to find out which drivers are already supported by upstream Linux and which are not.
This can be found by looking for the values of the compatible property in the device tree.
In addition, things can change between vendor kernels and upstream Linux.
A strategy could be to trim the vendor devicetree down to a minimal version, and make sure that everything is right, and then import the rest step by step, testing it as you go.
Older devices without device trees in vendor kernels¶
Older devices that don't already have a device tree typically have the exact same information in the vendor kernel. Before the devicetree, ARM computers used C files to describe what hardware they had, like the gta02.c file for the OpenMoko GTA02 smartphone.
For the basic support, you probably don't need require much programming skills as you don't need to be able to write C code, but you still need to understand it a bit as the information you need in file like gta02.c.
Keeping the device in a good state¶
First, you probably don't want to break your device while doing that kind of work, especially if you have only one.To avoid any issues:
- Make sure you have a working USB cable and that you know how to recover your device. If you are not able to recover your device for some reason(for instance if the data part of the cable doesn't work), it might still be possible to do it (someone managed to do that for a Galaxy Note 2) but it could be way more time consuming and risky.
- It might be a good idea to keep a working recovery in the recovery partition: if something goes wrong, you could more easily recover the device. Having the recovery in the recovery partition and not in the boot/kernel partition is also a good idea as if something goes wrong you can make it boot to the recovery, whereas you have no button combinations to force a boot on the boot/kernel partition: when something goes wrong, it might try to boot on the recovery partition even if you press only the power button.
- Make sure that the battery is charged before trying to boot the kernel you are working on: On some devices, you need to write or configure the charging driver to make the device charge. When the battery is discharged it will probably try to boot to charge it more, but if it boots on your kernel that doesn't enable charging, you could be stuck in some reboot loop.
eMMC corruption issues¶
Vendors kernels have patches for various eMMC corruption bugs.
See the EMMCFirmwareBugs article for more details.
Upstream Linux is incompatible with several bootloaders found on smartphones and tablets.
If you're unsure you could still do the workarounds to make sure your device is not stuck very early in the boot.
In addition, if you need to pass certain arguments to the kernel, you could hardcode them in the kenrel itself with configuration like CONFIG_CMDLINE and CONFIG_CMDLINE_FORCE to make sure that they are really passed to the kernel, as bootloaders often ignore this or that way to pass the kenrel command line to the kenrel. The BootloaderInterfaces also has some information on that.
Validating that your code runs¶There are various ways to get some feedback:
- UART: see UART and BootloaderInterfaces for more details. Note that just getting an UART shell in the bootloader is not always enough, as you might need to change configuration in that bootloader for it to keep it on for Linux.
- Simple FB: You can probably get the address of the framebuffer from the kernel command line arguments (in /proc/cmdline). Note that within the same model (GT-P3100), the address might differ from device to device. TODO: ask mighty17 for how to do it.
- RAM console? (TODO: see if it's available upstream)
- If you have GNU/Linux installed on an internal partition or microSD partition, you could configure it to save logs.
In addition you might also be able to play with the kernel command line arguments and delays to understand what is going on. For instance if the device doesn't find the rootfs, assuming that you can make the device reboot, adding
panic=1 rootdelay=60 in one boot and
panic=1 rootdelay=120 in the next boot can help you detect why the device is rebooting: if the second boot takes 60 more seconds to reboot, then it probably didn't find its rootfs and rebooted. You could also play with panic values like
panic=60 in the first boot and
panic=120 in the second boot: if there it waits 60 seconds more in the second boot to reboot, then it's probably due to a kernel panic.
If you have access to the bootloader through UART, you could also try to use its interface (which is documented a bit in BootloaderInterfaces) to dump the memory and retrieve a kernel log (like with dmesg). More information on that method is also available in the Debugging by printing wiki page on elinux.org. It would be best to check if that works fine with a stock kernel first, and then proceed with the upstream kernel. Beware that the offsets can and did change over time.
Replicant's Freedom Privacy and Security article¶
If you're not familiar with smartphones hardware architecture, Replicant's Freedom Privacy and Security article is a good introduction.
Device Tree for dummies, 2014¶
There seems to be some good introduction on the device tree by Bootlin.