Odroid U2 Debian GNU/Linux Installation Instructions

This document describes how to get Debian GNU/Linux (armhf) onto a Hardkernel
Odroid U2 device.  Fastboot or other insane Android tools were not needed,
neither strictly speaking was a JTAG or Serial port.

The breakthrough instructions which helped make this happen are here:
Kali Custom Odroid Kernel

Additional instructions for getting Debian root filesystems onto Android were
used here:
Debian on Android

Firstly a Debian root filesystem was obtained, and placed onto a Micro
SD Card.  The instructions for formatting the MicroSD Card on Kali's site
were not initially followed, so the card had to be reformatted!
From a Debian GNU/Linux PC (substituting /dev/sdb for the correct MicroSD
card), the following was executed:

    parted /dev/sdb --script -- mklabel msdos
    parted /dev/sdb --script -- mkpart primary fat32 4096s 266239s
    parted /dev/sdb --script -- mkpart primary ext4 266240s 100%
    mkfs.vfat /dev/sdb1
    mkfs.ext4 -L sdroot /dev/sdb2

Then, after mounting /dev/sdb2 the Debian root filesystem was installed
(debootstrap would suffice, although i cheated and used one for the
Mele A1000 armhf root filesystem that someone else had prepared!)

After booting into Android, a terminal was fired up and root enabled with
"su -".  Following whiteboard's advice, the following script /data/init2
was created:

    #!/system/bin/busybox ash
    mount /dev/block/mmcblk1p2 /root
    mkdir -p /root/boot
    mount /dev/block/mmcblk1p1 /root/boot
    export PATH=/sbin:/usr/sbin:/bin:/usr/bin:/system/bin
    busybox chroot /root /debootstrap/debootstrap --second-stage
    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

Chmod 0755 that script and execute it: congratulations, you should be into a
basic Debian system, where the fun can begin.  For convenience, the
following can be done:

    /etc/init.d/rcS (press ctrl-c if advised about udev)
    apt-get update
    apt-get install openssh-server
    /etc/init.d/ssh start

This at least allowed ssh to run, which allowed a remote login and the chance
to walk away from a rather sad looking Android screen.

The next phase was to download and compile up the kernel... natively on the
device!  There's a Debian system, there's a compiler, it's a Quad-Core
system with 2Gb of RAM so why not!

Remember to use the "make menuconfig" as a way to switch off debug build
symbols, otherwise you end up with 600mbyte of symbols and risk running
the SDCard partition out of space!  Also, note below that the mali config
was used in order to be able to use the Mali XF86 driver (noted on the
kali instructions):

    apt-get build-essential git ncurses-dev
    mkdir -p kernel
    cd kernel
    git clone --depth 1 \
        https://github.com/hardkernel/linux.git -b odroid-3.0.y odroid
    cd odroid
    make odroidu2_ubuntu_mali_defconfig
    make menuconfig
    make -j6
    make modules_install
    cp arch/arm/boot/zImage /boot

This should only take about 10-15 minutes, which is not bad.  Then, create an
initramfs - again this is native!

    apt-get install initramfs-tools uboot-mkimage
    cd /
    # Change the example "3.0.72" to your current odroid kernel revision
    mkinitramfs -c gzip -o ./initramfs 3.0.72
    mkimage -A arm -O linux -T ramdisk -C none -a 0 -e 0 \
            -n initramfs -d ./initramfs /boot/uInitrd
    rm initramfs

Now create a boot.txt file.  Note that the label "sdroot" matches up with
the ext4 label when the SDCard's ext4 filesystem was initially created.
Neat, but important!

    cat << EOF > /boot/boot.txt
    setenv initrd_high "0xffffffff"
    setenv fdt_high "0xffffffff"
    setenv bootcmd "fatload mmc 0:1 0x40008000 zImage; fatload mmc 0:1 0x42000000 uInitrd; bootm 0x40008000 0x42000000"
    setenv bootargs "console=tty1 console=ttySAC1,115200n8 root=LABEL=sdroot rootwait ro mem=2047M"
    boot
    EOF

Now create a boot.scr - again, this is all still native in the Debian Android
chroot:

    mkimage -A arm -T script -C none -n "Boot.scr for odroid-u2" \
        -d /boot/boot.txt /boot/boot.scr

Unfortunately - and this is the objectionable bit as far as Software Freedom
is concerned, you CANNOT just do signing of your own bootloader or u-boot
image, you have to ask hardkernel to sign it because they've put their key
into the Exynos4412 processor.  bastards.  Anyway if you're happy with that
you can just download the standard odroid u-boot and run the script to
put it onto the SD Card:

    cd
    wget http://www.mdrjr.net/odroid/mirror/BSPs/Alpha4/unpacked/boot.tar.gz
    tar zxpf boot.tar.gz
    cd boot
    # edit sd_fusing.sh and remove the reference to "sudo" before executing
    sh sd_fusing.sh /dev/block/mmcblk1

Congratulations, you now have an SDCard which should natively boot.
If you've bought the 8 Gbyte NAND Flash module and have been running from
that, power down and pop it off: you should now be able to just power
on and boot up with the SDCard still in.  Ping around on your network:
you should find that it's there, and that you can ssh in (assuming you
set a root password that you know.  If not, power down, pop the NAND Flash
back on, boot back into Android, run /data/init2 and then set the root
password).

At this point you know that, because you can now always boot from the SD Card,
you are free and clear to wipe the NAND partition.  However as a precaution
you may wish to simply copy the files from the root filesystem *onto* the
existing Android /data partition (which is 2GByte in size), and try booting
with that as the root partition, first.  Check for yourself: you should find
that there are no clashes between the Android subdirectories and the Debian
root subdirectory names.

What was discovered was that it's not possible to pop the NAND Flash back
on after an SDCard boot, so it is necessary to go through the following
procedure:

* Boot back into Android
* Modify /data/init2 to mount the FAT32 NAND (/dev/block/mmcblk0p1) as /boot
* copy the boot.txt, boot.scr, uInitrd and zImage to it
* run /data/init2 to get into the chroot
* re-run sd_fusing.sh but this time specify /dev/block/mmcblk0 instead
* reboot, leaving the NAND module down.

This time, although u-boot's default script will do a fatload off of the
NAND FAT32 partition, as no modifications have been made to boot.txt or
boot.scr, it will still boot with the Debian root partition off the SDCard.

This Is Good!  It's What You Want.

Thus, now, not only is the root filesystem on the SDCard but the NAND Card
should be up and accessible - check in /dev/ to see if there is mmcblk0
as well as mmcblk1.  You should see 4 mmcblk0pN partitions and two
mmcblk1pN partitions (NAND and SD Card respectively).  It may be the
other way round - get the right one!

Now that the NAND is accessible, it can be reformatted using the exact
same parted commands above (MAKE SURE YOU GET THE RIGHT ONE - DON'T WIPE
THE SDCARD!) except this time modify the ext4 label to something like
"nandroot".

Then, copy over the two partitions from the SD Card - rsync is a good way
to copy the root filesystem.  Substitute the correct mmcblkN number for
NAND, below!

    mount /dev/mmcblk0p2 /mnt
    rsync -HPavzx --exclude=/dev/* --exclude=/sys/* --exclude=/proc/* \
                  --exclude=/mnt/* /* /mnt
    sync
    umount /mnt

The boot partition is easier, but remember to edit /mnt/boot.txt.
Substitute the correct mmcblkN number for NAND, below!

    mount /dev/mmcblk0p1 /mnt
    cp /boot/* /mnt
    # edit /mnt/boot.txt, substitute nandboot for sdroot in LABEL
    vi /mnt/boot.txt
    sync
    umount /mnt

Then, re-run sd_fusing.sh this time specifying the NAND device (/dev/mmcblkN)

After that, you can double-check it's all good by powering down, popping
out the SD/MMC Card and booting up.

non-free Xorg MALI on ODroid-U2 under Debian GNU/Linux

If that all works, you're ready to make the mali x11 driver work:

    cat << EOF > root/etc/X11/xorg.conf
    # X.Org X server configuration file for xfree86-video-mali

    Section "Device"
        Identifier "Mali-Fbdev"
    #   Driver  "mali"
        Option  "fbdev"           "/dev/fb6"
        Option  "DRI2"            "true"
        Option  "DRI2_PAGE_FLIP"  "true"
        Option  "DRI2_WAIT_VSYNC" "true"
        Option  "UMP_CACHED"      "true"
        Option  "UMP_LOCK"        "false"
    EndSection

    Section "Screen"
        Identifier   "Mali-Screen"
        Device       "Mali-Fbdev"
        DefaultDepth 16
    EndSection

    Section "DRI"
        Mode 0666
    EndSection
    EOF

Then, follow these compile instructions:

    # http://malideveloper.arm.com/develop-for-mali/drivers/open-source-mali-gpus-linux-exadri2-and-x11-display-drivers/
    apt-get install build-essential autoconf automake make libtool xorg xorg-dev xutils-dev libdrm-dev
    wget http://malideveloper.arm.com/downloads/drivers/DX910/r3p2-01rel0/DX910-SW-99003-r3p2-01rel0.tgz
    wget http://malideveloper.arm.com/downloads/drivers/DX910/r3p2-01rel0/DX910-SW-99006-r3p2-01rel0.tgz
    wget --no-check-certificate \
            https://dl.dropbox.com/u/65312725/mali_opengl_hf_lib.tgz

    tar -xzvf mali_opengl_hf_lib.tgz
    cp mali_opengl_hf_lib/* /usr/lib/

    tar -xzvf DX910-SW-99003-r3p2-01rel0.tgz
    tar -xzvf DX910-SW-99006-r3p2-01rel0.tgz
    cd DX910-SW-99003-r3p2-01rel0/x11/xf86-video-mali-0.0.1/
    ./autogen.sh
    chmod +x configure

    CFLAGS="-O3 -Wall -W -Wextra -I/usr/include/libdrm \
            -IDX910-SW-99006-r3p2-01rel0/driver/src/ump/include" \
            LDFLAGS="-L/usr/lib -lMali -lUMP -lpthread" \
            ./configure --prefix=/usr --x-includes=/usr/include \
                        --x-libraries=/usr/lib
    cp -rf ../../../DX910-SW-99006-r3p2-01rel0/driver/src/ump/include/ump src/
    mkdir -p umplock
    cd umplock
    wget http://service.i-onik.de/a10_source_1.5/lichee/linux-3.0/modules/mali/DX910-SW-99002-r3p0-04rel0/driver/src/devicedrv/umplock/umplock_ioctl.h
    cd ..

    make
    make install

Congratulations, if you now run startx you should be presented with an
X Server, running at the beautiful hard-coded resolution of 1280x720 because
the Samsung Developers couldn't possibly imagine that anyone would want to
run any Operating System other than the fuckup known as Android on their
hardware which easily outperforms much more expensive systems for both
price and power requirements.

Given that this system is being provided to someone who is older, and the
resolution of 1280x720 on a large 19in HDMI Monitor is actually quite good
for them, this wasn't a problem.

Conclusion

There are lots of little quirks in this system: unplugging Ethernet was
problematic, and Android crashed several times when copying files over the
Ethernet.  However this appears to be Android-related: once booted into
Debian, doing "apt-get --install-recommends task-xfce-desktop" took 3
minutes to download 480mbytes (ran the Virgin Fibre Broadband up to its
2.5MBytes/sec limit) and it all installed perfectly.

There's no console yet, and the RS232 converter puts out garbage, possibly
because the ODroid PSU is a bit dicey (not earthed) so may be spiking the
FTDI chip.  With no console, it's hard to see what's going on, but luckily
everything worked so it wasn't needed.  Having the Android OS there initially
to be able to boot into the chroot and edit things made it unnecessary.

My friend now has a great system which boots up in under 10 seconds,
starts up LibreOffice in 7 seconds, and Firefox in 5.  It's a full Debian
GNU/Linux Desktop system consuming under 5 watts, it's the fastest
computer he's ever owned, and it's 1/50th the size.  Amazing.