Files
claude-os/docs/cpio.md
AI 3d5fb4c267 Add CPIO initial ramdisk with build infrastructure and parser (AI)
Build system changes:
- scripts/gen_initrd.sh packs all files from apps/ into a newc-format
  CPIO archive at build/isodir/boot/initrd.cpio.
- CMakeLists.txt adds 'initrd' target as ISO dependency. GRUB loads the
  archive as a Multiboot2 module via 'module2 /boot/initrd.cpio'.
- apps/README added as placeholder file for initial ramdisk content.

Kernel changes:
- kernel.c scans Multiboot2 tags for MULTIBOOT_TAG_TYPE_MODULE to find
  the initrd's physical address range, then passes it to cpio_init().
- cpio.c/h implements a parser for the SVR4/newc CPIO format:
  - cpio_init(): lists archive contents on startup
  - cpio_find(): look up a file by name (handles ./ prefix)
  - cpio_next(): iterate through all entries
  - cpio_count(): count files in archive
- The initrd lives in identity-mapped physical memory, so no additional
  mapping is needed to access it.

Verified in QEMU: GRUB loads the module at 0x0014A000, CPIO parser
finds the README file (38 bytes). All existing functionality (Ring 3
processes, syscalls) continues to work.
2026-02-23 12:16:24 +00:00

2.0 KiB

CPIO Initial Ramdisk

Overview

The initial ramdisk (initrd) provides files to the kernel at boot time before any filesystem drivers are available. It is a CPIO archive in SVR4/newc format, loaded by GRUB as a Multiboot2 module.

Build Process

During the build, the script scripts/gen_initrd.sh packs all files from the apps/ directory into a CPIO archive:

apps/
├── README          (placeholder)
├── hello-world     (future: flat binary)
└── sh              (future: shell binary)

The archive is placed at build/isodir/boot/initrd.cpio and included in the ISO image. GRUB loads it as a module via:

module2 /boot/initrd.cpio

CPIO Format

The newc (SVR4) CPIO format uses 110-byte headers with hex ASCII fields:

Offset  Size  Field
0       6     Magic ("070701")
6       8     Inode
14      8     Mode
22      8     UID
30      8     GID
38      8     Nlink
46      8     Mtime
54      8     Filesize
62      8     Devmajor
70      8     Devminor
78      8     Rdevmajor
86      8     Rdevminor
94      8     Namesize
102     8     Check

After the header: filename (namesize bytes, padded to 4-byte boundary), then file data (filesize bytes, padded to 4-byte boundary). The archive ends with a TRAILER!!! entry.

Kernel Interface

The kernel finds the initrd by scanning Multiboot2 boot information for MULTIBOOT_TAG_TYPE_MODULE (type 3). The module's physical memory range is identity-mapped, so it can be read directly.

#include "cpio.h"

// Find a file
cpio_entry_t entry;
if (cpio_find("hello-world", &entry) == 0) {
    // entry.data = pointer to file contents
    // entry.datasize = file size
}

// Iterate all files
uint32_t offset = 0;
while (cpio_next(&offset, &entry) == 0) {
    // entry.name, entry.data, entry.datasize
}

Files

  • scripts/gen_initrd.sh — Build script to generate CPIO archive
  • src/cpio.h / src/cpio.c — CPIO parser (find, iterate, count)
  • CMakeLists.txtinitrd target and module2 in grub.cfg