Create small and adaptable Linux initramfs' mainly intended for embedded (e.g. Android) devices.
Create a config.custom.sh
, tweak options defined in config.sh
as you please & simply run the build.sh
script:
$ ./build.sh
For e.g. scripting you can additionally add the -N
flag to avoid interactive actions (or -c alternate_config.sh
to override config.sh
defaults).
- An easily configurable environment based around Buildroot & BusyBox
- Kernel module support
- Shell script hook system with ordering and early/late triggers
- Execution order is decided by the numbering of the hook filenames
- Early triggers run as soon as the initramfs is reached
- Late triggers run after a rootfs is mounted and right before
switch_root
- Optionally extra hooks can be added and triggered manually via kernel cmdline
- Produced
cpio
archives can be compressed with eithergzip
orlz4
- Optional PPM image splash screens (or even boot animations with some limitations)
- Ideally boots any OS (distro) using the Linux kernel
A bunch of the initramfs features can be configured via kernel cmdline using the following options:
Option | Example values | Comment |
---|---|---|
rd.rootfs |
/dev/sde21 , nbd:rootfs:512 |
Rootfs location (mandatory!) |
rd.extra_hooks |
late/extra-hook , a,b,c |
Additional hooks to run in initramfs |
rd.mass_storage_rw |
0 (default) or 1 |
Mount all mass storage devices as read-write |
rd.silent_boot |
0 (default) or 1 |
Silence logs from kernel and initramfs, implied on when splash image set |
rd.no_clear |
0 (default) or 1 |
Don't clear console on initramfs enter |
rd.no_fwdcon |
0 (default) or 1 |
Don't forward kernel messages to tty8 while starting |
- Block device:
rd.rootfs=/dev/sde21
- Block device by UUID: e.g.
rd.rootfs=uuid:abcd-1234
orrd.rootfs=uuid:abcd-1234/rootfs.img
- Block device by label: e.g.
rd.rootfs=label:system
orrd.rootfs=label:system/rootfs.img
1 - Image on a block device:
rd.rootfs=/dev/sda13/rootfs.img
- Directory on a block device:
rd.rootfs=/dev/sda13/rootfs_dir
- Network Block Device (NBD):
rd.rootfs=nbd
or e.g.rd.rootfs=nbd:rootfs:512
2- A default export name of
rootfs
is assumed unless specified otherwise after the first colon (:
) - A default block-size of
512
is assumed (choices:512
,1024
,2048
or4096
) unless specified otherwise after the second colon (:
)
- A default export name of
- Dynpart under Android super partition:
rd.rootfs=super:system_a
3
1 NOTE: Filesystem labels containing /
aren't supported!
2 WARNING: Make sure you don't (re)configure USB ConfigFS from userspace, or the network connection will cut out!
3 NOTE: Remember to add BR2_CONFIGS+=",super_par_mount"
to your config to build the required extra utilities!
Here is an example tree of a NBD server setup I've used successfully:
├── allowed_clients
├── nbd_config
└── rootfs.img
allowed_clients
:
# subnet of initramfs RNDIS connection
172.16.42.0/24
nbd_config
:
[generic]
authfile = allowed_clients
copyonwrite = false
allowlist = true
max_threads = 16
maxconnections = 1
timeout = 5
[rootfs]
exportname = <absolute-path-to-rootfs.img-here>
With those files in place you can start a server with nbd-server -C nbd_config
, confirm output of nbd-client -l 127.0.0.1
and test network-booting a target device!
Core
CONFIG_RD_GZIP=y
(if usinggzip
compression)CONFIG_RD_LZ4=y
(if usinglz4
compression)CONFIG_DEVTMPFS=y
(populate/dev
automatically whendevtmpfs
is mounted)
Booting
CONFIG_BLK_DEV_LOOP=m
(booting from loopback images)CONFIG_BLK_DEV_NBD=m
(NBD rootfs booting)
USB
CONFIG_USB_GADGET=y
(UDC core driver)CONFIG_USB_CONFIGFS=m
(configure USB via ConfigFS)CONFIG_USB_CONFIGFS_RNDIS=y
(enable RNDIS access)CONFIG_USB_CONFIGFS_MASS_STORAGE=y
(enable Mass Storage access)
If you have a working virtual console, you should have logs visible on the display itself.
Otherwise assuming the configfs
, rndis
and telnet
hooks are on the initramfs, you should be able to use telnet 172.16.42.1
to gain an ash shell on the target device.
To view the boot console (display) from telnet, you can use conspy
.
Adding console=tty2 vt.global_cursor_default=0
to kernel cmdline appears to have helped with Void & Arch Linux at least and allowed the boot splash to show up without issues.
Keep in mind if disabling global VT cursor you should re-enable it on a per-rootfs basis with the following:
# setterm -cursor on >> /etc/issue
Adding audit=0
might also help especially on distros using systemd init.
All code in this repository is licensed under a GPL-3.0-only
license.
- Fix
list_pars()
to work with eMMC partitions - Minimal BusyBox config
- Recursive hook depdendencies
- Booting from a block devices based on UUID?
- Booting from subpartitions (e.g. stock postmarketOS setup) via e.g.
rd.rootfs.subpars
- Booting LVM/LUKS2 encrypted root?
- Mount options for root via e.g.
rd.mount_opts
- x86 support?