Cross-compilation is a viable option when one needs to build a custom kernel for an ARM device such as the Odroid C2 on an alternate system with a different architecture, such as your commodity PC.
Reasons for cross-compilation may be that: (a). The user's target device lacks sufficient storage to carry out the cross-compilation. (b). The user's preference to speed relative to the target device outweighs the need for a native compilation. (c). The user in question may not be having the target device in hand to test a native compilation on, and as such, a cross-compilation offers the user both a development platform and a (faster, in many cases) build toolkit.
You will need to install required packages before you start to build the Linux kernel on your Ubuntu desktop.
sudo apt-get update
sudo apt-get install git lzop build-essential gcc libncurses5-dev libc6-i386
Download the tool-chain from here. (Note that newer versions may be available as of the time of writing).
Update: You will find current versions of the toolkit here. See notes below on the current module file written against the latest release.
Once the download is done, extract the tarball for version 7.2.1 to /apps/gcc-linaro-toolchain/7.2.1
(as is on my system).
sudo mkdir -p /apps/gcc-linaro-toolchain/7.2.1
sudo tar Jxvf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz -C /apps/gcc-linaro-toolchain/7.2.1
For the latest version (7.2.1), do this to fetch the tarball with wget and deploy it:
wget -v https://releases.linaro.org/components/toolchain/binaries/latest/aarch64-linux-gnu/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz
sudo tar Jxvf gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu.tar.xz -C /apps/gcc-linaro-toolchain/6.1.1
We will now write an environment module that can load the required environment variables on demand (via the environment-modules system) without having to muck around with the local ~/.bashrc
as so many cross-compilation tool-kits dictate. Keeps the system lean and clean.
Here are the environment variables that the environment module will be exporting when loaded, given as a guide on how the environment module will be generated. Note that I'm using the full path on my system, modify as needed:
For version 7.2.1:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export PATH=/apps/gcc-linaro-toolchain/7.2.1/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/bin:/apps/gcc-linaro-toolchain/7.2.1/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-linux-gnu/aarch64-linux-gnu/include
Now I'll generate a module file for version 7.2.1 that you can adapt to your environment as needed:
#%Module1.0#####################################################################
##
## modules compilers/gcc-linaro-toolchain
##
## modulefiles/compilers/gcc-linaro-toolchain. Written by Dennis Mungai
##
proc ModulesHelp { } {
global version modroot
puts stderr "This is the linaro toolchain, use it for cross-compilations (ARM)"
}
module-whatis "Sets the environment for using the linaro toolchain (C, Fortran)"
set topdir /apps/gcc-linaro-toolchain/4.9/gcc-linaro-aarch64-linux-gnu-7.2.1-2017.11_linux
set version 7.2.1
conflict gcc
setenv CC $topdir/bin/aarch64-linux-gnu-gcc
setenv GCC $topdir/bin/aarch64-linux-gnu-gcc
setenv FC $topdir/bin/aarch64-linux-gnu-gfortran
setenv F77 $topdir/bin/aarch64-linux-gnu-gfortran
setenv F90 $topdir/bin/aarch64-linux-gnu-gfortran
setenv ARCH arm64
setenv CROSS_COMPILE aarch64-linux-gnu-
prepend-path PATH $topdir/aarch64-linux-gnu/include
prepend-path PATH $topdir/bin
prepend-path MANPATH $topdir/share/doc/gcc-linaro-aarch64-linux-gnu/man
prepend-path LD_LIBRARY_PATH $topdir/aarch64-linux-gnu/lib:$topdir/lib
Now, you can load the module above (after deployment) as follows:
module load gcc-linaro-toolchain/7.1.1
Change to the name under which you saved the module file under. That name used above is what it looks like on my workstation.
You can check if the tool chain installed above works properly while checking it's version. If you can find gcc version 4.9.2 20140904 (prerelease) at the end of the line, the toolchain is well installed.
$ aarch64-linux-gnu-gcc -v
Checkout
You can check out the Linux kernel source tree from Hardkernel's Github repositories.Please note that HardKernel distributes the Linux kernel in different branches for Android and other Linux distributions.
Android:
$ git clone --depth 1 https://github.com/hardkernel/linux.git -b odroidc2-3.16.y-android
$ cd linux
Linux:
$ git clone --depth 1 https://github.com/hardkernel/linux.git -b odroidc2-3.16.y
$ cd linux
Compile:
Note:
If you want to download & build only the Android Linux kernel source code without another Android BSP, you will face the error message as below:
drivers/amlogic/wifi/Kconfig:26: can't open file “../hardware/wifi/realtek/drivers/8192cu/rtl8xxx_CU/Kconfig”
Please delete the last line below in drivers/amlogic/wifi/Kconfig
file if you will only build the Android Linux kernel.
source “../hardware/wifi/realtek/drivers/8192cu/rtl8xxx_CU/Kconfig”
You must do a kernel configuration step for ODROID-C2 prior to building it. We use nproc to automatically assign all online processors to the make command:
$ make -j$(nproc) odroidc2_defconfig
$ make -j$(nproc) Image dtbs modules
That will build the Linux kernel (Image), the device tree file (.dtb) and kernel modules (.ko).
Custom Kernel Build
If you have some kernel drivers that you wish to include for your custom build, you can select the drivers easily in the Linux kernel tree. Running make menuconfig will show you an ncurses-based menu that will help you to select kernel drivers.
$ make -j$(nproc) menuconfig
Once you're done selecting the drivers, exit from the menu screen. Then you can start kernel build with make again.
$ make -j$(nproc) Image modules
When you exit from the kernel menu screen, you will have a .config file in the current directory with the changes set for your custom build. You can optionally back up this as a file, my_kernel.config for example, or even make a patch if you manage your own git repository:
$ cp .config arch/arm64/configs/odroidc2_defconfig
$ git add arch/arm64/configs/odroidc2_defconfig
$ git commit -s -m "Change the kernel config file for ODROID-C2"
$ git push
Installation
There are different installation routes to both the Linux kernel image and the device tree for Android and Linux. Since Android loads both from a boot partition, we have to use fastboot to install into the dedicated partition. Please refer the partition table from here. In contrast, Linux boots by the instructions described in boot.ini , the first FAT partition.
Android:
This details the installation process used to install the kernel image to the boot partition on the target device:
$ fastboot flash boot <path/of/your/Image>
Next, install a device tree file, meson64_odroidc2.dtb.
$ fastboot flash dtb <path/of/your/meson64_odroidc2.dtb>
Linux:
This explanation assumes that your USB memory CARD reader (and/or the eMMC reader, if applicable) is assigned at /dev/sde
. Change as appropriate.You may use lsblk to see which entry it appears under on your system.
-
Plug the Boot-Device (eMMC or SD) into the USB memory CARD reader and connect the USB memory CARD reader to your build host (the Linux PC).
-
Copy the Image and the Device Tree file (hereby named meson64_odroidc2.dtb) to the FAT partition (1st partition) in the Boot-Device.
mkdir -p mount sudo mount /dev/sde1 ./mount sudo cp arch/arm64/boot/Image arch/arm64/boot/dts/meson64_odroidc2.dtb ./mount sync sudo umount ./mount
-
Copy the driver modules to the EXT4 partition(2nd partition) in the Boot-Device.
sudo mount /dev/sde2 ./mount sudo make modules_install ARCH=arm64 INSTALL_MOD_PATH=./mount sync sudo umount ./mount rm -rf mount
And that should be all for the cross-compilation of the Linux kernel for the Odroid C2 on Linux.
Just a heads up, the latest release of linaro is available here:
https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz
Not sure if it'll work just the same, I'm currently downloading it and am going to be testing with it.