Skip to content

Spin42/kobo_firmware

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KoboFirmware

Mix tasks to automate the one-time setup and installation of Nerves firmware on Kobo e-readers. After the initial install, the standard mix firmware + mix upload workflow handles ongoing development.

How it works

Stock Kobo e-readers run Linux from an internal eMMC. This package automates three things:

  1. Blob extraction — proprietary binaries for e-ink and WiFi are copied from the running Kobo over SSH and baked into the Nerves rootfs overlay at build time, so the firmware image is self-contained.

  2. Partition backup — the stock OS partition is streamed to the host machine via dd over SSH, giving you a recovery image in case anything goes wrong.

  3. Init replacement — a small shell script (init-nerves) replaces /bin/init on the Kobo. At boot it waits 10 seconds for a touchscreen tap; if detected, it loop-mounts the Nerves image from the onboard FAT32 storage, loads squashfs.ko and f2fs.ko, and pivot_roots into Nerves. If no tap is detected, the stock Kobo OS boots normally.

Supported devices

Each Kobo model is identified by a codename. Built-in devices:

Codename Model SoC Kernel
spa_colour Kobo Clara Colour MT8113 4.9.77

Contributions of new device manifests are welcome.

Prerequisites

  • A Kobo e-reader with SSH access (e.g. via a KoboRoot.tgz hack that installs dropbear)
  • The Kobo connected to the same network as the build machine
  • A Nerves project with a matching system for the device
  • sshpass installed if using password authentication
  • fwup installed for firmware image generation

Installation

Add kobo_firmware to your list of dependencies in mix.exs:

def deps do
  [
    {:kobo_firmware, github: "Spin42/kobo_firmware"}
  ]
end

Workflow

1. Setup (one-time)

Extracts proprietary blobs from the stock Kobo into rootfs_overlay/ and builds the initial firmware image:

MIX_TARGET=nerves_system_kobo_clara_colour \
  mix kobo.setup --host 192.168.1.42 --device spa_colour

Options:

Flag Description Default
--host Kobo hostname or IP (required)
--device Device codename (required)
--password Root password for SSH key-based auth
--skip-blobs Skip blob extraction (reuse existing) false
--image-name Output image filename nerves-kobo.img
--overlay-dir Path to rootfs overlay directory rootfs_overlay

This produces a nerves-kobo.img file ready for deployment.

2. Install (one-time)

Backs up the Kobo's OS partition, uploads the firmware image and kernel modules, and installs init-nerves as /bin/init:

MIX_TARGET=nerves_system_kobo_clara_colour \
  mix kobo.install --host 192.168.1.42 --device spa_colour

Options:

Flag Description Default
--host Kobo hostname or IP (required)
--device Device codename (required)
--password Root password for SSH key-based auth
--image-name Firmware image filename nerves-kobo.img
--backup-dir Local directory for partition backups backups
--skip-backup Skip the partition backup step false
--skip-modules Skip uploading kernel modules false

After installation, reboot the Kobo:

ssh root@192.168.1.42 reboot

Tap the touchscreen within 10 seconds of boot when the led is blinking to start Nerves. Without a tap, the stock Kobo OS boots normally.

3. Ongoing development

Once Nerves is running on the device, use the standard workflow:

mix firmware    # build a new .fw file
mix upload      # push to the running device via nerves_ssh

No need to run mix kobo.setup or mix kobo.install again.

Overriding the device manifest

If the built-in manifest for your device is incomplete or wrong, you can override it from your project's config. Any keys you provide are merged on top of the built-in defaults for that codename:

# config/config.exs
config :kobo_firmware, :device, %{
  codename: "spa_colour",
  entries: [
    %{remote: "/usr/bin/mdpd", overlay: "usr/bin/mdpd", type: :file},
    %{remote: "/lib/my_custom_blob.so", overlay: "lib/my_custom_blob.so", type: :file}
    # ...
  ]
}

To add a completely new device that isn't built-in, provide the full device map:

config :kobo_firmware, :device, %{
  codename: "my_kobo",
  name: "Kobo Something",
  kernel_version: "5.4.0",
  root_partition: "/dev/mmcblk0p10",
  onboard_partition: "/dev/mmcblk0p12",
  touch_device: "/dev/input/event1",
  kernel_modules: [
    {"squashfs", "kernel/fs/squashfs/squashfs.ko"},
    {"f2fs", "kernel/fs/f2fs/f2fs.ko"}
  ],
  nerves_system: "nerves_system_my_kobo",
  entries: [
    %{remote: "/usr/bin/mdpd", overlay: "usr/bin/mdpd", type: :file}
    # ...
  ]
}

What gets extracted (spa_colour)

The built-in spa_colour manifest extracts these files:

E-ink display:

  • /usr/bin/mdpd
  • /sbin/nvram_daemon
  • /lib/libnvram.so
  • /lib/libnvram_custom.so

WiFi:

  • /lib/firmware/* (wireless firmware blobs)
  • /usr/bin/wmt_loader
  • /usr/bin/wmt_launcher
  • /etc/Wireless/
  • /etc/*wmt*, /etc/*WMT* (WMT configuration)

On-device layout

Everything deployed to the Kobo lives on the onboard FAT32 storage (mounted at /mnt/onboard) under a .nerves/ directory:

/mnt/onboard/.nerves/
├── nerves-kobo.img                      # firmware image (loop-mounted at boot)
└── modules/<kernel-version>/kernel/fs/
    ├── squashfs/squashfs.ko
    └── f2fs/f2fs.ko

Recovery

The partition backup created by mix kobo.install is saved to backups/ on the host machine (timestamped, e.g. mmcblk0p10_20260309_143012.img). This can be flashed back via fastboot if the device is bricked.

The stock /bin/init is also preserved as /bin/init.stock on the Kobo during installation.

License

MIT

About

Helper tasks to prepare a Kobo Nerves firmware

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors