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