Manoj Rao bio photo

Manoj Rao

Your Average Common Man

Email Twitter Github

adb, fastboot and a rooted device with SD card slot

SDCARD or DATA partition preparation

Create partitions

Use a 32-GB SD Card and partition into two: One with 4GB of VFAT (FAT32) type with initramfs/boot partition. The other with remaining storage as an ext4 partition. I used gparted to create partitions. After creating partitions mount the card on Android device. Now we need to bring Ubuntu filesystem on SDCARD.

Output of mount shows this:
# mount
none /data/ubuntu/dev/pts devpts rw,seclabel,relatime,mode=600 0 0
none /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
/dev/block/vold/179:129 /mnt/media_rw/sdcard1 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/block/vold/179:129 /mnt/secure/asec vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1023,gid=1023,fmask=0007,dmask=0007,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro 0 0
/dev/fuse /storage/sdcard1 fuse rw,nosuid,nodev,noexec,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
root@nexus:/ # ls -l /dev/block/

Notice the 179:129 index for /dev/block/vold..

Now we have to find out the corresponding block device name from /dev/block

ls -l /dev/block
brw-rw---- root     system   179,  64 2017-05-02 10:18 mmcblk0boot1
brw------- root     root     179,   1 2017-05-02 10:18 mmcblk0p1
brw------- root     root     179,  10 2017-05-02 10:18 mmcblk0p10
brw------- root     root     179,  11 2017-05-02 10:18 mmcblk0p11
brw------- root     root     179,  12 2017-05-02 10:18 mmcblk0p12
brw------- root     root     179,  13 2017-05-02 10:18 mmcblk0p13
brw------- root     root     179,  14 2017-05-02 10:18 mmcblk0p14
brw------- root     root     179,  15 2017-05-02 10:18 mmcblk0p15
brw------- root     root     179,  16 2017-05-02 10:18 mmcblk0p16
brw------- root     root     179,  17 2017-05-02 10:18 mmcblk0p17
brw------- root     root     179,  18 2017-05-02 10:18 mmcblk0p18
brw------- root     root     179,   2 2017-05-02 10:18 mmcblk0p2
brw------- root     root     179,   3 2017-05-02 10:18 mmcblk0p3
brw------- root     root     179,   4 2017-05-02 10:18 mmcblk0p4
brw------- root     root     179,   5 2017-05-02 10:18 mmcblk0p5
brw------- root     root     179,   6 2017-05-02 10:18 mmcblk0p6
brw------- root     root     179,   7 2017-05-02 10:18 mmcblk0p7
brw------- root     root     179,   8 2017-05-02 10:18 mmcblk0p8
brw------- root     root     179,   9 2017-05-02 10:18 mmcblk0p9
brw-rw---- root     system   179,  96 2017-05-02 10:18 mmcblk0rpmb
brw------- root     root     179, 128 2017-05-02 12:25 mmcblk1
brw------- root     root     179, 129 2017-05-02 12:25 mmcblk1p1
brw------- root     root     179, 130 2017-05-02 12:25 mmcblk1p2
drwxr-xr-x root     root              2017-05-02 10:18 platform
drwx------ root     root              2017-05-02 12:25 vold
brw------- root     root     254,   0 2017-05-02 10:18 zram0

As we can see the 4GB partition on SDCARD corresponds to mmcblk1p1, therefore the other block device under the same major device 28GB EXT4 partition enumerated as mmcblk1p2 device (179:130).

Debootstrap steps

Commands for debootstrap and installing the debian/ubuntu file system on the SDCARD

First, you will need to install debootstrap on your desktop

sudo apt-get install debootstrap

After this, you can run debootstrap to download the first stage images of xenial (or other Ubuntu release of your choice)

apt conf modification

Configuring parameters such as environment variables etc to get Ubuntu up and running..

Bonus points: Re-route X11 display to the screen

A nice-to-have feature

UBUNTU on SDCARD: Writing the initramfs on /init

#!/sbin/busybox sh

# initamfs pre-boot init script

# Mount the /proc and /sys filesytems
/sbin/busybox mount -t proc none /proc
/sbin/busybox mount -t sysfs none /sys
/sbin/busybox mount -t tmpfs none /dev

# Allow them to rest a little 
/sbin/busybox sleep 1

# Populate /dev
/sbin/busybox mdev -s

# Mount the root filesystem, second partition on micro SDCARD
/sbin/busybox mount -t ext4 -o noatime,nodiratime,errors=panic /dev/mmcblk1p2 /mnt/root

# Clean up
/sbin/busybox umount /proc
/sbin/busybox umount /sys
/sbin/busybox umount /dev

#Transfer root to SDCARD
exec /sbin/busybox switch_root /mnt/root /etc/init

The file system of this initramfs is very minimalistic and only contains the /sbin/busybox and the mount points /proc, /sys, /dev and /mnt/root. Or to be on the safe side, use the original initamfs and just add /sbin/busybox, a mount point /mnt/root and replace init with the script above.

We will need the system’s base address i.e., where the RAM begins. To get it from your original kernel zImage, check for /proc/config.gz in your running kernel or use the extrace-ikconfig script on the kernel binary (??). This script is included in the kernel source under kernel/scriptsextract-ikconfig

extrace-ikconfig zImage | grep PHYS_OFFSET


Look for "System RAM" under /proc/iomem 
This will only give a hint, not the actual address. Ex: 0x40000000

In the Android code base:

# At your desktop computer

# mkdir my-initramfs
# cd my-initramfs
# mkdir -p proc sys dev mnt/root sbin
# cp /my/arm/busybox sbin/busybox
# cp /above/init init
# chmod a+x init sbin/busybox
# find . | cpio --quiet -H newc -o | gzip > ../initramfs.cpio.gz
# cd ..

# mkbootimg --base 0x00200000 --kernel zImage --ramdisk initramfs.cpio.gz -o my-boot.img 

# Do not flash this image yet..

Creating an Ubunut root file system

Mount your SDcard, if not already mounted. I assume you’ve mounted it as /mnt/debian. If you prefer Ubuntu or some other Debian based distribution, the steps are the same. Replace the mirrors accordingly.

Chose a Debian mirror close to you, and begin to create the Debian root filesystem.

At your desktop computer

apt-get install debootstrap
mkdir /mnt/debian
mount -t ext4 /dev/sdf2 /mnt/debian
debootstrap --verbose --arch armel --foreign squeeze /mnt/debian
umount /mnt/debian

On your Android device

mount /dev/block/mmcblk1p2 /root
export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin
busybox chroot /root /debootstrap/debootstrap --second-stage
echo 'deb xenial main' >/root/etc/apt/sources.list
mount -t proc none /root/proc
mount -t sysfs none /root/sys
mount -o bind /dev /root/dev
mount -t devpts none /root/dev/pts
export TMPDIR=/tmp
busybox chroot /root /bin/bash
apt-get update

# Now shutdown your device and remove the SDcard.

UBUNTU on SDCARD:: Problems faced with apt-get update

I looked a little further into this and it’s really baffling to me. I enabled the debug flags for apt commands and looked at the output, turns out if you provide a hostname in the sources list the command fails during getaddinfo() and if I provide an IP address instead the command fails with the following: Err:3 xenial Release Could not create a socket for (f=2 t=1 p=6) - socket (13: Permission denied)


The difference, as far as I can tell thus far, seems to be in that the ‘_apt’ user cannot read the ‘pubring.gpg’ file that is being created in a temporary directory, which means that gpgv cannot access it when it runs;

[pid 10149] stat("/etc/apt/trusted.gpg", {st_mode=S_IFREG|0644, st_size=12255, …}) = 0
[pid 10149] faccessat(AT_FDCWD, "/etc/apt/trusted.gpg", R_OK) = 0
[pid 10149] open("*tmp/tmp.OcaWlGuT32/pubring.gpg", O_WRONLY|O_CREAT|O_APPEND, 0666) = -1 EACCES (Permission denied)
[pid 10149] write(2, "/usr/bin/apt-key: 309: /usr/bin*"…, 41) = 41
[pid 10149] write(2, "cannot create /tmp/tmp.OcaWlGuT3"…, 64) = 64

This problem does not occur when root is the sandbox user, set via ‘APT::Sandbox::User “root”;’ in ‘/etc/apt/apt.conf’. It’s the only setting present. Disable that setting and the problem returns, while running the same thing interactively works without any issues.

I’m a bit stumped, at this point, pausing my investigation for now, but logging it here in case someone else runs into this.

The warning we’re seeing looks as follows;

== W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: https://apt-cache.domain.example/cache/ xenial InRelease: Unknown error executing apt-key `=

UBUNTU on SDCARD: Add details to the following solutions before putting them up on the wiki

I also installed the debian package called android-permissions.deb Here’s my new apt.conf

// Options for the downloading routines
  Queue-Mode "host";       // host|access
  ForceIPv4 "true";
  Retries "0";
  Source-Symlinks "true";
  ForceHash "sha256"; // hashmethod used for expected hash: sha256, sha1 or md5ssum
  PDiffs "true";     // try to get the IndexFile diffs
  PDiffs::FileLimit "4"; // don't use diffs if we would need more than 4 diffs
  PDiffs::SizeLimit "50"; // don't use diffs if size of all patches excess
                          // 50% of the size of the original file

  Check-Valid-Until "true";
  Max-ValidTime "864000"; // 10 days
  Max-ValidTime::Debian-Security "604800"; // 7 days, label specific configuratii on

  // HTTP method configuration
    // Proxy "";
    // "DIRECT";  // Specific per-host setting
    Timeout "120";
    Pipeline-Depth "5";
    AllowRedirect  "true";

    // Cache Control. Note these do not work with Squid 2.0.2
    No-Cache "false";
    Max-Age "86400";     // 1 Day age on index files
    No-Store "false";    // Prevent the cache from storing archives
    Dl-Limit "7";        // 7Kb/sec maximum download rate
    User-Agent "Debian APT-HTTP/1.3";

  pkgProblemResolver "true";
  pkgProblemResolver::ShowScores "true";
  pkgDepCache::AutoInstall "true"; // what packages apt install to satify depenn dencies
  pkgDepCache::Marker "true";
  pkgCacheGen "true";
  pkgAcquire "true";
  pkgAcquire::Worker "true";
  pkgAcquire::Auth "true";
  pkgDPkgPM "true";
  pkgDPkgProgressReporting "true";
  pkgOrderList "true";
  pkgPackageManager "true"; // OrderList/Configure debugging
  pkgAutoRemove "true";   // show information about automatic removes
  BuildDeps "true";
  pkgInitialize "true";   // This one will dump the configuration space
  NoLocking "true";
  Acquire::Ftp "true";    // Show ftp command traffic
  Acquire::Http "true";   // Show http command traffic
  Acquire::Https "true";   // Show https debug
  Acquire::gpgv "true";   // Show the gpgv traffic
  Acquire::cdrom "true";   // Show cdrom debug output
  aptcdrom "true";        // Show found package files
  IdentCdrom "true";
  acquire::netrc "true";  // netrc parser
  RunScripts "true";      // debug invocation of external scripts

Dir "/"
  // Location of the state dir
  State "var/lib/apt/"
     Lists "lists/";
     status "/var/lib/dpkg/status";
     extended_states "extended_states";


Acquire::Connect::AddrConfig "true";

// This line being the most important of them all in terms of getting
// apt to work in chroot systems
// This adds root to all the relevant groups that are important
APT::Sandbox::User "root";

Bring Your Own Cause

If you think any info here has remotely helped you consider dropping a penny for this cause, just click me . You can visit Unfortunately, there are plenty of sad things happening all over the world, if you have a different cause or charity you'd rather support please do. And if you did make a donation, please drop a note to me (annotated) or leave a comment here (anonymous is OK!) and I will use that as motivation to write more useful content here.

If you like topics such as this then please consider subscribing to my podcast. I talk to some of the stalwarts in tech and ask them what their favorite productivity hacks are:

Available on iTunes Podcast

Visit Void Star Podcast’s page on iTunes Podcast Portal. Please Click ‘Subscribe’, leave a comment.

Get it iTunes