Saturday, January 24, 2015

Managing Odroid and "mlinuxguy" changes in git

Here are my notes getting a Debian Linux kernel package built for Odroid C1. I prefer to manage the Linux kernel source under its natural habitat (git) so let's clone it. I'm using the googlesource.com mirror but feel free to substitute another one.
git clone https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git linux
cd linux
Now let's add hardkernel's fork as a remote repository. I'm also adding the repository owned by mlinuxguy who has been working on improving the ethernet driver. The benefit of adding these repositories to the same clone is that they can share objects, and I can easily git-diff the changes.
git remote add hardkernel https://github.com/hardkernel/linux.git
git remote add mlinuxguy https://github.com/mlinuxguy/odroid-c1-network-driver.git
git fetch --all
Unfortunately, mlinuxguy only included the files he changed under drivers/amlogic/ethernet but not with the full path, so we need to fix up his commits before we can merge them. We'll create a new local branch and then do a filter-branch to rewrite the commits.
git checkout remotes/mlinuxguy/master -b mlinuxguy-full
git filter-branch --prune-empty --tree-filter '
    mkdir -p drivers/amlogic/ethernet/phy &&
    git ls-tree --name-only $GIT_COMMIT |
    xargs -I FILE mv FILE drivers/amlogic/ethernet/FILE'
Now let's create a branch that merges hardkernel's odroidc-3.10.y branch with the changes from mlinuxguy.
git checkout remotes/hardkernel/odroidc-3.10.y -b odroidc-3.10.y-mlinuxguy
git merge -s recursive -X theirs mlinuxguy-full
Notice: the latest odroidc-3.10.y branch has broken ethernet, but commit 764e57 + mlinuxguy works. In the local branch, git reset --hard 764e57 before the merge. It has kernel version 3.10.44.
And now we have a kernel tree ready to be built. If you have not done so, install the prerequisite build packages.
sudo apt-get install build-essential kernel-package lzop u-boot-tools initramfs-tools
The Debian make-kpkg program allows you to configure a custom kernel using an existing .config, which we generate using Odroid C1's default.
make odroidc_defconfig
The following command will build linux-image-* and linux-headers-* in the parent directory. It takes about 50 minutes on the Odroid C1 which is not bad (the kernel itself took 20 minutes, the rest are modules and packaging). It saves me the hassle of messing with cross-compilation toolchain. It also means that I get to use Debian's gcc, not some binary from an untrusted third-party.
nice time make-kpkg -j5 --rootcmd fakeroot --initrd --append-to-version=-odroidc+mlinuxguy kernel_image kernel_headers
Note that the dtbs (device tree blob) is not packaged, so if you want to update it, you could make dtbs from the Linux source and copy it to /boot manually. You should be able to just use the old one. You can then install the Debian packages using the dpkg -i command which installs the vmlinuz-* under /boot. The initramfs-tools hook will create the initrd.img-* file under /boot as well. Note however that vmlinuz and initrd.img has to be converted to uImage and uInitrd for U-Boot. Rather than making the uImage under the linux source tree, we'll generate it from /boot. I'm using the same parameters that Odroid C1 kernel uses as revealed by running mkimage -l on an existing uImage and uInitrd.
cd /boot
mkimage -A arm -O linux -T kernel -C none -a 00208000 -e 00208000 \
    -n "Linux-3.10.44" -d /boot/vmlinuz-3.10.44-odroidc+mlinuxguy \
    /boot/uImage-3.10.44-odroidc+mlinuxguy
mkimage -A arm -O linux -T ramdisk -C none \
    -n "uInitrd 3.10.44" -d /boot/initrd.img-3.10.44-odroidc+mlinuxguy \
    /boot/uInitrd-3.10.44-odroidc+mlinuxguy
(TODO: I could not get any compression working under U-Boot possibly due to version mismatch, but uncompressed works.) (TODO: you could automate this with a kernel install hook, like how update-initramfs works.)

If something fails to boot, you could boot into the original kernel in U-Boot like this:
fatload mmc 0:1 0x21000000 uImage
fatload mmc 0:1 0x21800000 meson8b_odroidc.dtb
fatload mmc 0:1 0x22000000 uInitrd
setenv bootargs "console=ttyS0,115200n8 root=/dev/mmcblk0p2 rootwait ro no_console_suspend vdaccfg=0xa000 logo=osd1,loaded,0x7900000,720p,full dmfc=3 cvbsmode=576cvbs hdmimode=720p m_bpp=32 vout=hdmi disableuhs"
bootm 0x21000000 0x22000000 0x21800000
After the build, to return the source tree back to prestine state (no littered build artifacts), run:
git clean -f -x -d