Transformer: Booting Android experiment

This is Experimental stuff! and under further modifications. (Normal Android system upgrade is not possible)

This follows from:

  1. run Debian on Android.
  2. install Debian Linux on Transformer TF701.
  3. Debian united on Transformer.

Then, I have the intention to put the Debian rootfs in a separate partition. (instead of using the loop file)

So, is it possible to create a new partition on Transformer TF701 ?

It seems that the device does not use any standard partition table.

The closest one that makes it seems possible is the nvflash tool that comes with the Linux for Tegra 4.

Instruction on how to use nvflash on Transformer TF101, but looks impossible to get it working without knowing the Secure Boot Key.

For ref, see The inner workings of Secure Boot key and Nvflash.

The next choice is to use an existing partition. The system partition is 2G , so it is the best choice.

So, we will need to move the system partition files out to the data partition, but still mount it to the /system path.

What about converting it to a loop file, and then mount it to /system ?

This is possible, we need to modify the /fstab.macallan and /init.macallan.rc on the Android root.

In fstab.macallan , comment off the line to mount the /system (partition name is APP)

1     #/dev/block/platform/sdhci-tegra.3/by-name/APP      /system     ext4    ro      wait

In addition, the filesystem check is done by /system/bin/e2fsck , and since the /system is now mounted last, the check cannot be performed, so the check flag in fstab.macallan can be removed as well.

In init.macallan.rc , add the "mount ext4 loop@/image_path .. " after the "mount_all /fstab.macallan" line (below, assumes the loop file is /data/media/system.img):

1     mount_all /fstab.macallan
2 mount ext4 loop@/data/media/system.img /system ro

We need to modify the boot.img that contains both the Android kernel and the initrd ramdisk which contains these files on the Android root filesystem.

This Android boot.img is the data in the boot partition LNX .

For ref, see TF701 Partition information / Unbricking thread by lpdunwell

On Android, one can check which partition names map to which partition number with:

1     ls -l /dev/block/platform/sdhci-tegra.3/by-name/
2 ..
3 lrwxrwxrwx. 1 root root 20 Jan 15 11:13 APP -> /dev/block/mmcblk0p4
4 lrwxrwxrwx. 1 root root 20 Jan 15 11:13 LNX -> /dev/block/mmcblk0p3
5 lrwxrwxrwx. 1 root root 20 Jan 15 11:13 SOS -> /dev/block/mmcblk0p1

The other boot partition of interest is SOS, which contains the recovery image. This is now used to boot the Debian Linux instead.

The tool abootimg can be used to extract the current image from the boot partition, and to update an image to the boot partition. Instead of using Android fastboot flash to update the boot partition from another computer, we can update it directly on the device with abootimg.

side note: dd can also be used to read/write from partition: eg. to save the current recovery.img
dd if=/dev/mmcblk0p1 of=./recovery.img

As root user, to install abootimg, enter (after # prompt)

1     # apt-get install abootimg

Note: on Linux, the mmc partition 1 is represented as /dev/mmcblk0p1 whereas on Android, it is /dev/block/mmcblk0p1

Below, I will be working on Linux.

abootimg -i can tell us whether the partition contains an Android boot.img

 1     # abootimg -i /dev/mmcblk0p3
3 Android Boot Image Info:
5 * file name = /dev/mmcblk0p3 [block device]
7 * image size = 8388608 bytes (8.00 MB)
8 page size = 2048 bytes
10 * Boot Name = ""
12 * kernel size = 5769776 bytes (5.50 MB)
13 ramdisk size = 672771 bytes (0.64 MB)
15 * load addresses:
16 kernel: 0x10008000
17 ramdisk: 0x11000000
18 tags: 0x10000100
20 * empty cmdline
21 * id = 0x703510a5 0xe6488333 0xb6759ede 0xbb518b25 0xc499d158 0x00000000 0x00000000 0x00000000
1     # abootimg -i /dev/mmcblk0p2
3 /dev/mmcblk0p2: no Android Magic Value
4 /dev/mmcblk0p2: not a valid Android Boot Image.

To extract the image from the LNX partition,

1     # abootimg -x /dev/mmcblk0p3
2 writing boot image config in bootimg.cfg
3 extracting kernel in zImage
4 extracting ramdisk in initrd.img
6 # ls
7 bootimg.cfg initrd.img zImage

To extract the ramdisk initrd.img in subdir rd ,

1     # mkdir rd
2 # cd rd
3 # gzip -dc ../initrd.img | cpio -imd

Ref: cpio manual

Proceed to modify the fstab.macallan and init.macallan.rc (in rd dir).

To rebuild a new ramdisk newinitrd.img from the updated files ,

1     # find . | cpio -o -H newc | gzip -9 > ../newinitrd.img

To update the boot partition with the new image ,

1     # cd ..
2 # abootimg -u /dev/mmcblk0p3 -f bootimg.cfg -k zImage -r newinitrd.img

To create the system loop file in /data/media/system.img ,

1     # cd /data/media
2 # dd if=/dev/zero of=./system.img bs=1048576 count=1492
3 # /sbin/mke2fs -i 131072 -t ext4 -F -L system system.img

To copy the files from the system partition, assume it is mounted at /mnt/system

1     # mount system.img /mnt1
2 # cd /mnt1
3 # cp -r --preserve=all /mnt/system/* .
5 # cd ..
6 # umount /mnt1

Once we reboot into Android, we can test whether it works.

Well, Android hangs in the Android boot screen.

Checking the /proc/last_kmsg , Android kernel boots up fine. Even debian-kit runs fine.

So, what is wrong ??

The Android logcat output points to SurfaceFlinger crash! The SurfaceFlinger is like the Linux X server. So, when it crash, the rest of Android framework which uses the display cannot start as well. (This is not the same as boot loop)

1     I/SurfaceFlinger(  650): SurfaceFlinger is starting
2 I/SurfaceFlinger( 650): SurfaceFlinger's main thread ready to run. Initializing graphics H/W...
3 D/libEGL ( 650): loaded /system/lib/egl/
4 E/libEGL ( 650): can't find eglGetProcAddress() in /system/lib/egl/
5 F/libc ( 650): Fatal signal 11 (SIGSEGV) at 0x00000000 (code=1), thread 650 (surfaceflinger)

I try mounting system.img as rw, disabling debian-kit, but the same problem rules!

Looking at the Android init/builtins.c source, it seems to suggest mount bind should work. (No harm trying)

In init.macallan.rc , replace the "mount ext4 loop@/image_path .. " after the "mount_all /fstab.macallan" line with :

1     mount_all /fstab.macallan
2 mount none /data/.system /system bind ro

The "mount none /data/.system /system bind ro" should bind the /data/.system to the /system path.

The system.img can be removed, since it is not working.

To copy the files from the system partition to /data/.system/

1     # cd /data
2 # mkdir .system
3 # cd .system
4 # cp -r --preserve=all /mnt/system/* .

Then again, rebuild a new ramdisk newinitrd.img from the updated files, and update the boot partition with the new image.

After rebooting into Android, this actually works! The solution looks simple? ^_^

As can be seen from mount, the /system also comes from the data partition.

1     $ mount | grep /dev/block/mmc
3 /dev/block/mmcblk0p7 on /ADF type ext4 (rw,relatime,seclabel,data=ordered)
4 /dev/block/mmcblk0p10 on /persist type ext4 (ro,relatime,seclabel,data=ordered)
5 /dev/block/mmcblk0p14 on /data type ext4 (rw,nosuid,nodev,noatime,seclabel,discard,noauto_da_alloc,errors=panic,data=ordered)
6 /dev/block/mmcblk0p5 on /cache type ext4 (rw,nosuid,nodev,noatime,seclabel,discard,errors=panic,data=ordered)
7 /dev/block/mmcblk0p14 on /system type ext4 (rw,nosuid,nodev,noatime,seclabel,discard,noauto_da_alloc,errors=panic,data=ordered)

In the next post, Transformer: Booting Debian experiment, I will move the Debian rootfs into the system partition.


blog comments powered by Disqus