Home > Android, Linux > You are telling me that you can’t compile and replace Ubuntu’s kernel?

You are telling me that you can’t compile and replace Ubuntu’s kernel?

During testing of my drivers I often notice that users are generally unwilling to compile their own kernel.
I have nothing against that, but just want to tell you how easy is that, comparing to my quest of installing my own kernel on my own android tablet.
(Note that I still didn’t get fully working kernel that boots Android, but just a shell prompt)

Morning workout:

Unlike PCs, embedded devices, category my tablet of course falls into, don’t have a BIOS that lets you run any code from your hard disk, usb stick, live cd, etc…
It also doesn’t have a hard disk, so you can’t even yank it out to replace its boot sector. Its software is stored inside a soldered flash chip, which its really very hard to unsolder manually.
So to change its contents you must have bootable system. One failure and you got a brick.

So my first quest wasn’t even about compiling a kernel. It was about finding out where the kernel + initrd are stored in the flash and find a way to change it with some fallback ability. If you don’t know initrd is small tarball that contains minimal set of programs and libraries. It is loaded by bootloader and usually used to allow complex ways of booting the system.
In android though initrd isn’t discarded. Instead, onto empty folders that are present in it, other filesystems are mounted, such as /system, /data /nand, and of course well known virtual filesystems such as /proc /sys.

First thing that I found was that device had a ‘recovery mode’ that is activated by holding volume+ key during boot).
It shows simple screen that accepts so-called update.zip on the sd card with instructions on how to reflash the device.

Needless to say that first I need to root the phone, because unlike your ubuntu box, you can’t just ‘sudo’ to became one. Looking around the web, gave me many very dangerous guides that revolve around replacing the device root filesystem with a ‘mod’, using that recovery mode. That is very dangerous due to reasons I stated above.

Instead, I found out small, nice exploit called z4root, and it gave me the root.
The next step was to dump the nand chip, and that gave me very good results.
I found that it has 2 relevant partitions, ‘boot’ and ‘recovery’. Both later found out to contain both a kernel and initrd! So I now can replace the ‘recovery’ kernel and boot into it, without risk of bricking the device.
(Assuming I won’t need that recovery feature, so yet I should be very careful).

Now lets compile the kernel…. Wait the device is made by no-name firm, and thus I don’t have the source.
Using vanilla kernel or Ubuntu kernel is really not an option, it is 100% chance that vendor customized the kernel and didn’t give anything back.

OK, some pokes around the device reveal that it is based on Telechips chipset, and they did (recently) released the kernel sources. Still no guarantee that end vendor didn’t customize kernel further (hint: it did).

OK, configured and compiled it (that’s is the task of compiling Ubuntu kernel…).

From now on I will call the recovery nand/flash partition, by its name mtd6.

Now I need a way to put both kernel and initrd into mtd6. I opened it in a hex editor and found that it consists of 3 parts,
a header, followed by kernel, and then initrd. I also found that normal boot mtd partition and mtd6 have same kernel but different initrd.
After some googling, a lot of trial and error, I found that this header is standard and produced by a tool present in android source code.
Very good explanation of this can be found here

Now after more hours of trial and error, I found out that my own kernel only shows signs of life (a logo on the screen) If I boot without framebuffer console,
(it allows you to see kernel log on the device’s screen).
I even managed to make it start ‘recovery’ application, an application that is started by default when you boot into recovery mode.

Knowing that, I hacked my own version of that recovery application, in such way that it would print kernel log onto the screen line after line.
Of course I had no input, because device keys didn’t work, touchscreen is useless, and for a reason I will describe later I couldn’t use USB connection.
I took at look at it, found out that mmc doesn’t work (so no wifi of course because its connected to same bus).

Take a deep breath and lets attack from a different angle.
I captured the kernel log (dmesg) from working kernel.
Using it and some probes around /sys, I found which device drivers aren’t included in Telechips released kernel.

For the purposes of booting the system I foucused on i2c devices and found 3 such devices:

1. EM78153S – an embedded 8-bit microcontroller.
Believe me or not, but later analysts shows that it is used as an i2c rom, and
it just contains the device wifi’s MAC.

2. BMA020 – 3 axis accelerometer. It has datasheet, so its pure fun to write a driver for it.
I don’t need it now.

3. AXP192 – a power managment chip. It does have a datasheet, but it is in Chinese ,-(

Later I disassembled the kernel, and using /proc/kallsyms info, restored names of each and every function.
It was not fun, and I had to learn ARM assembly, but I managed to understand how drivers for AXP192 and EM78153S
work. I also understood that keypad driver is different and uses a set of GPIO lines to detect key presses.

I also managed to translate the datasheet, and that wasn’t easy. Its PDF and too large for Google translate, and attempts to split it up just gave me text without formation whatsoever.
To do so I had first to convert the PDF to .DOC then use this service which works only in windows.

Then I had a week of fun reading it, I wrote small program to read its settings, control few features etc.
I added this code to the ‘recovery’ app, so now I could use my kernel with confidence that it won’t burn the device due to wrong PMU settings
(There was one such setting, the voltage on the sound chip, it was 3V instead of 1.8V)

I also found a settings that allows me to control how much current it draws from USB port.
But default it just draws as much as it can. That costed me an USB port that is now burned.
(Thats why I said earlier that I don’t use usb cable to connect the tablet to my notebook…)

Now knowing how to restore that limit and after few hours of figuring out how to start a shell via adb
(I had to put bash in correct place in the initrd, I got a shell on my compiled kernel.)

From now on my goal it to make sd/mmc slot work.
I know why it doesn’t work, it doesn’t work because it is connected partially via GPIO lines
and the end vendor customized them.

Honestly, I could write another blog post of this length or even greater about this.
I omitted many things, like what I had to go through to compile applications for this device aka cross-compiling,
the fun I had with the PMU, and device’s battery indicator that was totally wrong, etc, etc,etc…

Thanks for reading.

Advertisements
Categories: Android, Linux Tags: , ,
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: