Overview
The Ohmni Kernel lets you recompile your kernel if you need to add specific device driver support to your
Kernel level changes
The main repo is here: https://github.com/ohmnilabs/ohmni-pdk-kernel
Ohmni's kernel is based off the Android-x86 kernel, which in turn is based off a standard Linux kernel (currently 4.9) plus a number of modifications to make it boot and run Android properly.
If you're doing deeper kernel hacking on Ohmni then you may want to follow development there: https://sourceforge.net/p/android-x86/kernel/ci/kernel-4.9/tree/
Our goal is to keep it as close to standard Linux as possible (i.e. no mysterious device tree or arch-specific stuff) to maximize familiarity and ease of modification.
Downloading and compiling
build instructions tested on Ubuntu 14.04
First, clone this repo.
git clone https://github.com/ohmnilabs/ohmni-pdk-kernel.git
Next, get the AOSP prebuilts. This is important as it ensures every kernel build is using the exact same toolchain.
git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6 prebuilts-x86_64-linux-glibc2.11-4.6
The kernel config file for Ohmni is arch/x86/configs/android-x86_64_defconfig. If you need to add more modules or drivers, you can go ahead and edit this file.
First step is to generate the .config from the Ohmni defconfig. Note that we are using the path to the prebuilts directory we checked out so that it uses that toolchain:
cd ohmni-pdk-kernel
make O=./build ARCH=x86_64 CROSS_COMPILE=/absolute/path/to/your/prebuilts-x86_64-linux-glibc2.11-4.6/bin/x86_64-linux- android-x86_64_defconfig
Next, we compile everything (note, use the same ARCH and CROSS_COMPILE args for every call to make):
make O=./build ARCH=x86_64 CROSS_COMPILE=/absolute/path/to/your/prebuilts-x86_64-linux-glibc2.11-4.6/bin/x86_64-linux- -j4 bzImage
Now, the resulting kernel ends up in ohmni-pdk-kernel/build/arch/x86/boot/bzImage. Compiled modules end up in their respective directories under ohmni-pdk-kernel/build. \
Deploying your new kernel to Ohmni
Now that you have a new kernel and/or additional modules, you can deploy them to Ohmni. To push them, first put your Ohmni into developer mode and enable adb via the Ohmni settings menu. Then connect to Ohmni over adb and start a shell.
Go into su mode and mount the main partition:
su
cd /data/local/tmp
mkdir -p mnt
mount /dev/block/mmcblk0p2 mnt
It's a good idea to make a backup of the original running kernel before you make any changes:
cp mnt/android-*/kernel mnt/android-*/kernel.origworking
Now adb push the new bzImage from your local machine over to /data/local/tmp/bzImage on Ohmni. Copy/rename it into place follows:
cp bzImage mnt/android-*/kernel
Note the reason for the android-* in the above commands is the build date in the above path changes based on the current version of the Ohmni platform software.
BE CAREFUL - if you change the kernel config file and rebuild, the kernel's internal version ID will be different. If you push only the kernel to a unit, it will no longer boot. You will need the copy over the modules as well. The kernel and modules MUST MATCH exactly.
Backup the current modules directory
mv /lib/modules/4.9.31-android-x86_64 /lib/modules/4.9.31-android-x86_64-backup
Push the new modules directory to Ohmni and copy them over the current modules directory
ohmni_up:/data/local/tmp # mv new-modules/4.9.31-android-x86_64 /lib/modules/
Then you can just unmount and reboot:
sync
unmount /data/local/tmp/mnt
svc power reboot
Enjoy! If you add drivers for any interesting robot hardware please consider sending us pull requests. We can help clean things up if needed and would love to make your changes available to all other Ohmni developers.
Deploying new kernel modules to Ohmni
When deploying modules, you don't need to mount the boot partition. Simply go into the developer superuser shell on Ohmni via adb.
Next, push/copy the new .ko files into the appropriate paths under: /lib/modules/4.9.31-android-x86_64/kernel.
Now to register with the system run:
depmod -a
Now you can just reboot the system:
svc power reboot
Make change to Android file system
As with most Android systems, the files under / is all from a ramdisk and mounted read-only. So even if you go and modify the files, it doesn't stick. The most important things here are /init.rc and /init.*.rc, which contains all the startup logic and service definitions, etc. If you want to execute certain operation upon start up, for example, to create a tmpfs mount during boot, or to create a directory with appropriate permissions (i.e. /dev/libcamera or something), you can do those in init.
To modify these on a running system, you have to first mount the boot partition as shown above:
ohmni_up:/ $ su
ohmni_up:/ # cd /data/local/tmp
ohmni_up:/data/local/tmp # mkdir -p mnt
ohmni_up:/data/local/tmp # mount /dev/block/mmcblk0p2 mnt
ohmni_up:/data/local/tmp # cd mnt
ohmni_up:/data/local/tmp/mnt # ls
android-2018-04-19 lost+found
ohmni_up:/data/local/tmp/mnt # cd android-2018-04-19/
ohmni_up:/data/local/tmp/mnt/android-2018-04-19 # ls
data initrd.img kernel ramdisk.img system
ramdisk.img is a gzipped archive file containing the init file that we need to modify. We need to unpack it to a temp directory to make changes. The key files are init.rc and all of the init.*.rc which are dynamically loaded on boot. The syntax for these files is: https://android.googlesource.com/platform/system/core/+/master/init/README.md Generally, most changes we make should be to /init.ohmni_up.rc for the purpose of cleanliness.
mkdir ramdisk
cd ramdisk
cat ../mnt/android-*/ramdisk.img | gunzip | cpio -vid
make any changes you want here to the files, clean up any *~ generated by mg
find . | cpio -o | gzip > ../newramdisk.img
cp ../newramdisk.img ../mnt/android-*/ramdisk.img
umount ../mnt
Now, you can just reboot the system to test your change:
svc power reboot