What is Filesystem Images Using Device Tables-Free Embedded Linux Course online

Filesystem Images Using Device Tables

Build device nodes into an image as a non-root user in this free linux device drivers course

free linux device drivers course free linux kernel development course device table gen_init_cpio filesystem image

Creating device nodes normally requires the mknod system call, which needs root privileges — a problem the moment your build pipeline runs as an unprivileged CI user, which is standard practice today. This lecture in our free linux kernel development course covers device tables: a plain-text format understood by several Linux filesystem image builders that lets you describe device nodes, ownership, and permissions declaratively, so the tool creates them inside the image without ever needing root on the build host.

What You Will Learn

Why device tables exist and the problem they solve The device table file format field by field Using gen_init_cpio to build an initramfs image The same pattern applied to jffs2, ubifs, and ext2 A worked example with a small multi-node device table

Prerequisites

This lecture assumes you have a staged rootfs directory from earlier in this free embedded systems course, and are comfortable with basic device node concepts (major/minor numbers, node types) from the device-node lecture earlier in this chapter.

The Root Problem: mknod Needs root

If you try to bake device nodes directly into a filesystem image as an ordinary CI user, mknod fails outright — creating a character or block special file is a privileged operation by design, since it lets a process grant itself arbitrary access to physical devices or kernel interfaces. Historically this forced build systems to either run parts of the build as root inside a container, or use fakeroot-style wrapping. Device tables sidestep the problem entirely: instead of creating nodes on the host filesystem at all, you describe them in a text file, and a purpose-built tool bakes the corresponding entries directly into the output image format, with no privileged syscall required on the build host.

The Device Table Format

A device table is a plain text file, one line per entry, with this field layout:

<name> <type> <mode> <uid> <gid> <major> <minor> <start> <inc> <count>
FieldMeaning
namePath of the entry relative to the image root
typef (file), d (directory), c (char device), b (block device), p (FIFO)
modeOctal permission bits
uid / gidNumeric owner and group to assign in the image
major / minorDevice major/minor number (character or block types only)
start / inc / countOptional fields for generating a numbered range of nodes, e.g. tty0..tty7

Fields that do not apply to a given type (major/minor for a plain file, for instance) are simply written as -.

A Worked Example

Here is a small, original device table covering a handful of common nodes plus a numbered range for serial ports:

# ep_device_table - example device table for a minimal rootfs
# name          type mode  uid  gid  major minor start inc count
/dev            d    755   0    0    -     -     -     -   -
/dev/console    c    600   0    0    5     1     -     -   -
/dev/null       c    666   0    0    1     3     -     -   -
/dev/zero       c    666   0    0    1     5     -     -   -
/dev/ttyS       c    660   0    0    4     64    0     1   4

The last line generates four nodes in one entry — ttyS0 through ttyS3 — with minor numbers starting at 64 and incrementing by 1 for each, which is far less error-prone than writing four separate lines by hand.

Building an initramfs with gen_init_cpio

The Linux kernel source tree ships a small standalone tool, gen_init_cpio, specifically for turning a device table (plus a file list) into a cpio archive suitable for use as an initramfs. It lives under usr/ in the kernel source and can be built independently of a full kernel build:

$ gcc -O2 -o gen_init_cpio linux/usr/gen_init_cpio.c
$ ./gen_init_cpio ep_device_table.txt > rootfs.cpio

gen_init_cpio also accepts file and dir lines in the same table so you can describe your entire image — regular files pulled from the staging tree, directories, and device nodes — in one declarative document, all without touching a privileged syscall:

dir  /bin      755 0 0
file /bin/busybox staging/bin/busybox 755 0 0
dir  /dev      755 0 0
nod  /dev/console 600 0 0 c 5 1
Device Table to Filesystem Image
ep_device_table.txt (plain text, no root needed) | v gen_init_cpio / mkfs.jffs2 / mkfs.ubifs / genext2fs | v Image file with correctly-typed device nodes baked in | v Flashed or booted with nodes present from first boot, no mdev/devtmpfs population needed for these entries

The Same Pattern for Other Filesystem Formats

gen_init_cpio is not unique — the same device-table concept has been adopted by the image builders for the other filesystem formats commonly used on embedded flash storage and disk:

FilesystemToolTypical Use
cpio (initramfs)gen_init_cpioEmbedded into the kernel image or used standalone
jffs2mkfs.jffs2Raw NOR/NAND flash, no separate flash translation layer
ubifsmkfs.ubifs (with ubinize)NAND flash on top of UBI
ext2genext2fsDisk images, eMMC, SD card storage

Each of these tools accepts a device table via a -D flag (the exact flag name varies slightly by tool) and applies the same field layout described above. We cover jffs2 and ubifs in depth later in this course when we look at flash storage strategies; genext2fs follows the identical device table syntax for building disk-based images.

Common Mistakes and Troubleshooting

  • Mismatched major/minor numbers — a device table entry with the wrong major/minor creates a node that looks correct with ls -l but talks to the wrong driver, or none at all.
  • Forgetting the type column entirely — a missing or malformed type field causes most tools to reject the whole table rather than skip one bad line.
  • Using device tables for devices that should be dynamic — baking hotplug-capable devices (USB, SD card readers) into a static table defeats the point of devtmpfs/mdev covered earlier in this chapter; reserve device tables for nodes that genuinely never change.
  • Path mismatches between the table and the staged files list — when combining file and device entries in one table, a typo in a source path fails the whole build, not just that one line.

Best Practices

Keep device tables under version control next to the rest of your rootfs build scripts, and comment each line with the device it corresponds to — the field-only format is not self-explanatory months later. Prefer device tables only for genuinely static, always-present nodes (console, null, zero); leave hotplug-capable hardware to devtmpfs and mdev from the earlier lecture in this chapter.

Summary and Key Takeaways

Device tables let you describe device nodes declaratively in plain text and have a build tool create them inside a filesystem image, entirely avoiding the need for root privileges on the build host. The same field format is shared across gen_init_cpio, mkfs.jffs2, mkfs.ubifs, and genext2fs, making it a single skill that applies across nearly every embedded filesystem format.

Conclusion

Device tables are a small, easily overlooked tool, but they solve a real and common build-pipeline problem cleanly. Once you understand the field layout, the same technique carries across every major embedded filesystem format covered in this free linux kernel development course, from a simple initramfs to a production jffs2 or ext2 image.

Frequently Asked Questions

Why can’t I just run mknod as part of my build script?

mknod requires root privileges, which most modern CI/build pipelines deliberately avoid granting. Device tables let the image-building tool create the nodes internally instead.

Is the device table format the same across gen_init_cpio, mkfs.jffs2, and genext2fs?

The core field layout is shared, though the exact command-line flag to pass the table file varies slightly between tools — check each tool’s help output.

Can a device table create regular files and directories, not just device nodes?

Yes, most of these tools accept file and dir entries alongside device node entries in the same table, letting you describe an entire image in one document.

What do the start, inc, and count fields do?

They generate a numbered range of nodes from a single line — for example four serial ports ttyS0 through ttyS3 with sequential minor numbers.

Should hotplug devices like USB drives go in a device table?

No, device tables are for static, always-present nodes. Hotplug-capable devices should be left to devtmpfs and mdev, covered earlier in this chapter.

Where does gen_init_cpio come from?

It ships as source inside the Linux kernel tree under usr/gen_init_cpio.c and can be compiled as a small standalone host tool.

Continue the Free Linux Kernel Development Course

Explore the rest of this chapter on building a root filesystem, or move ahead to flash storage strategies with jffs2 and ubifs.

Next Lecture Browse the Full Course

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *