Saturday 22 December 2012

Hackberry A10 - Booting Android from an SD Card

Having spent many hours attempting to get a custom kernel booting for the factory Android image, I found that is was easier to first create an factory Android image that would boot from an SD card. The main advantage is that it removes the arduous steps of packaging a complete image and then re-flashing to Nand for each small change.  It also opens up the possibility of booting other Android distributions from an SD card.

To start with I created a mirror image of the nand paritition on an SD card, to do this requires a linux installation. The nand partitions range from A-K as are covered in more detail here. I used gparted to create the partitions with the correct sizes as below, it is important that you leave 16MB free at the start of the SD card for uboot (shown by 'unallocated' partition) .  You need to create an extended partition (shown by /dev/sdc4) in order to create more than 4 partitions.



You need to create an additional partition on the SD card to represent the extrernal sd card /mnt/extsd, I created a FAT32 partition which becomes /dev/sdc13 (mmcblk0p13).

Next step is to copy across all the nand partitions from the hackberry. This can be done by booting the hackberry with a linux distro and using the linux dd command to copy the partitions to files. I copied the partitions on to a usb stick (needs to be at least 4GB) as below:

   dd if =/dev/block/nanda of=nanda
   dd if =/dev/block/nandb of=nandb
   dd if=/dev/block/nandc  of=nandc
   ...
   ...
   dd if=/dev/block/nandk  of=nandk

Once all the nand files are created we can 'dd' the files to the SD card. The boot partition file nandc is not copied because we need to extract the rootfs from it and create a ext4 partition. The bootloader  file nanda is also not copied as we create our uboot on FAT16 partition (/dev/sdc1). Assuming the SD card shows up as /dev/sdc I executed the following (amend /dev/sdc with correct device name for your SD card).

   
   sudo dd if=nandb of=/dev/sdc2
   sudo dd if=nandd of=/dev/sdc5 bs=1M
   sudo dd if=nande of=/dev/sdc6
   sudo dd if=nandf of=/dev/sdc7
   sudo dd if=nandg of=/dev/sdc8
   sudo dd if=nandh of=/dev/sdc9
   sudo dd if=nandi of=/dev/sdc10
   sudo dd if=nandj of=/dev/sdc11
   sudo dd if=nandk of=/dev/sdc12 bs=1M
   sudo sync

Next I extracted the ramdisk rootfs from the nandc file, fortunately I have done this for you. Download the file android_sd.tar.gz, it contains  all the additional files required to create a bootable sd card. If your interested how I extract the kernel and rootfs I used the split_bootimg.pl utility, further info here.  I also fixed the files init.sun4i.rc and ueventd.sun4i.rc so that they refer to the sdcard paritions /dev/ /dev/mmcblk0pX instead of /dev/nandX.

The mapping between nand and mmcblk0p are shown below

   nanda -> mmcblk0p1  
   nandb -> mmcblk0p2
   nandc -> mmcblk0p3       
            mmcblk0p4              
   nandd -> mmcblk0p5       
   nande -> mmcblk0p6       
   nandf -> mmcblk0p7       
   nandg -> mmcblk0p8       
   nandh -> mmcblk0p9       
   nandi -> mmcblk0p10      
   nandj -> mmcblk0p11      
   nandk -> mmcblk0p12    

Take the nandc file from the zip file and dd it to the correct SD card parition, in my example it is /dev/sdc eg:

   sudo dd if=nandc of=/dev/sdc3


I then changed all references in the script files on the system partition (/dev/sdc5 in my example) from /dev/nandX to /dev/mmcblk0pX.  The files to amend are:

   ./etc/vold.fstab
   ./bin/preinstall.sh
   ./bin/sop.sh

You need to edit ./etc/vold.fstab and replace the /mnt/extsd  with the following:

dev_mount extsd   /mnt/extsd   auto  /devices/virtual/block/mmcblk0p13

Next I converted the extracted kernel from the nandc file to be uboot compatible, again in the download zip there is a pre-built file (uImage). If your interested, I used the following command to convert the kernel:

    mkimage -A ARM -C none -T kernel -O linux  -a 40008000 -e 40008000 -d nandc-kernel uImage

Copy the uImage file to first partition on the SD card (this is bootloader FAT16 partition which is empty ). Also copy the uboot config files uEnv.txt and boot.scr to the first partition.

Finally I copied the Hackberry uboot files sunxi-spl.bin and u-boot.bin to the SD card to make it bootable. This is the reason for the leaving 16MB free at the start of the SD card.

    sudo dd if=sunxi-spl.bin of=/dev/[drive] bs=1024 seek=8
    sudo dd if=u-boot.bin of=/dev/[drive] bs=1024 seek=32
    sudo sync

I suggest you delete everything of the data partition (eg /dev/sdc6), this will ensure the correct device partitions are found and recorded on the first boot. It would be prudent to hook up a serial console to the Hackberry to monitor boot progress in case of failures. Insert the SD card into the Hackberry and power up.

Once you have Android booting, turn off media scanning for the SD card. This option is in Setting->Storage>"Enable media scanning on SD".

If want to try deploy another kernel (assuming the kernel and modules are compatible with the Android image) then:

  1. Copy the newly built uImage file to the first partition of the SD card.
  2. Copy the modules to the /vendor/modules on the system partition of the SD card.

11 comments:

  1. Hi, first of all...thanks for your posts!

    I'm trying to follow this one, which gparted version did you use?
    I tested the latest live (0.14) but it wouldn't boot and the previous I have (live 0.12) it blocks on the first unknown partition.
    Another way to format the sd card?

    Thanks, kind regards.

    ReplyDelete
    Replies
    1. Hi, I've listed the partition structure in this thread if that helps : https://www.miniand.com/forums/forums/development--3/topics/booting-android-from-an-sd-card#post-5544.

      You can use fdsk to create the partitions using. I found it easier to use GParted (on Ubuntu 12.10).

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Well, the linux kernel boots, and the "Android" splash screen is displayed, but zygote is crashing. It appears to be looking for the /mnt/sdcard mounted from vold.fstab, but it's not getting mounted (I changed the /mnt/extsd entry to /mnt/sdcard, but that had no effect). There aren't any mmcblk0p... entries in /sys/devices/virtual/block, either. I tried both the kernel from my own HB and the one you uploaded to android_sd.tar.gz.

    Any ideas?

    ReplyDelete
    Replies
    1. In vold.fstab I have the following:

      dev_mount sdcard /mnt/sdcard auto /devices/virtual/block/mmcblk0p12
      dev_mount extsd /mnt/extsd auto /devices/virtual/block/mmcblk0p13

      Delete
    2. I still don't have any mmcblk0... devices showing up in /sys/devices/virtual/block; they do show up in /dev, but they're not what's used by vold.fstab.

      Delete
  4. Hi. I am trying to build and make work CyanoGenMod for Hackberry, starting with instructions here - http://linux-sunxi.org/Instruction_to_build_jellybean_for_cubieboard . After some hacking around realtek wifi, I've noticed that in the image obtained I have internal usb hub disabled - only bottom usb is ok.
    (In SD card with linaro all usb ports work).
    May be you know how to fix it?

    ReplyDelete
    Replies
    1. Hi, Great work on Cyanogenmod! It is most likely the script.bin/evb.bin you are using is the wrong one. You need to use the one from the Hackberry.

      Delete
  5. Thanks Jas, for this comprehensive tutorial. It's almost as fast as from NAND - though with a Class 10 card. Partitioning worked with gparted 0.11
    I took your http://dl.miniand.com/jas-hacks/uboot/512mb/sunxi-spl.bin and http://dl.miniand.com/jas-hacks/uboot/512mb/u-boot.bin for my 512 MB RAM tablet.
    Maybe you should also mention that you have to put script.bin on sdc1 beside the kernel.
    First I had an "Encryption Unsuccessful" message. After some reading I found that this might have to do with the /data or /sdcard partition. After zeroing sdc6 it worked fine. So why dd nande anyway?
    Unfortunately WiFi is also not turning on though rtl8150 is loaded. (Don't know why 'Gary' commented out so many modules.) Fortunately with usbnet I can use my USB to Ethernet adapter which works more or less.

    Worst is that /sdcard and /extsd aren't mounted correctly, somewhat like what Pat mentions. Everything that is written from PC is nowhere to be found, everything written from Android is written in the /data partition I think ... In "Storage" it only shows 0.98 GB. Still I can't find the exact point where it is written.
    My /etc/vold.fstab looks like this:
    #dev_mount sdcard /mnt/sdcard auto /devices/virtual/block/nandi
    dev_mount sdcard /mnt/sdcard auto /devices/virtual/block/mmcblk0p12
    #dev_mount extsd /mnt/extsd auto /devices/platform/sunxi-mmc.1/mmc_host /devices/platform/sunxi-mmc.0/mmc_host
    dev_mount extsd /mnt/extsd auto /devices/virtual/block/mmcblk0p13
    Also, I don't have a /bin/sop.sh

    ReplyDelete
  6. hi jas. i've got problem while copying nande and nandk from hackberry to flashdisk. may i ask you a copy of nande and nandk? if you have them, can you pls send me them to maijesty@gmail.com thank you in advance

    ReplyDelete
  7. hello Jasbir

    (i'm noobs in android/linux) I have a question;
    I see your instructions are very clear; but i want to do the same for Android Tablet having ICS n kernel 3.0.8;

    What I want to do is.... boot Ubantu from SD card with 3.0.26 or higher kernel while retaining present ICS with 3.0.8 kernel ;

    So that I can use both Android and Ubantu with different kernels
    Can this be achieved by your instructions?

    Thanks in advance:)

    ReplyDelete