| bootstrap | ||
| libodin | ||
| minit | ||
| staging | ||
| .gitignore | ||
| Makefile | ||
| README.md | ||
This repository contains the fruits of my decision to explore Linux in a barebones environment. It exists here primarily for redundancy, but you're more than welcome to poke around with it.
Here are the big moving parts. I'll briefly cover each in its own section.
- the Linux kernel: I'm using 6.12.63 (LTS) as of the creation of this README; not included in the repo due to size
qemu-system-x86_64: probably available from your package manager; seeMakefilefor flags usedbootstrap: a basic init program for the initramfs environmentminit: a minimal PID 1 init that's started after switching to the persistent rootfstoybox: modern busybox; it does a lot of heavy lifting right now by way of providing shell utilitieslibodin: a WIP quasi-libc thing; mostly for convenience procs/wrappers I want available across programsmusl: used to avoid shipping glibc into the imageroot.img: not included due to size; 2GB image file with an ext4 filesystem on it; passed to qemu as/dev/sda
Linux LTS Kernel
As stated above, I'm using 6.12.63 as it was the latest LTS at the time of writing.
If you want to build this project yourself, it expects the kernel image to live at
$PROJECT_ROOT/linux-6.12.63/arch/x86_64/boot/bzImage, or you can adjust the path in
the Makefile accordingly.
My version is built with the default options. Nothing fancy here.
bootstrap
Bootstrap's job is to serve as a sort of "pre-init" while the system is still operating from the
initial ramdisk image.
It starts by mounting several special filesystems such as devtmpfs, proc, and sysfs.
After that it mounts the root filesystem on /dev/sda1 to /mnt/newroot and copies directories
from the ramdisk to the new root, skipping any existing files.
Once that's done, it performs execve to replace itself with toybox's switch_root command.
This pivots the root filesystem from the ram disk to /dev/sda1.
minit
This is the "real init", aka PID 1. It mounts devpts, then enters a loop.
It forks and opens tty1 before spawning a bash shell attached to it.
It then loops forever and reaps any orphaned PIDs.
There is plumbing there for graceful reboots but this does not yet work
inside this environment.
toybox
Toybox is a BusyBox alternative. Mostly chosen because when I tried to go get BusyBox, the site wouldn't load. You can read more about it here.
libodin
I'd like to eventually build libodin out into a libc replacement for Odin, but that is currently
outside the scope of this project.
For now its job is to provide reusable procs for various system tasks such as mounting a filesystem,
reading the mounts table, or opening a tty.
musl
It's musl. Not much to say here. Find it here.
root.img
The virtual hard disk I'm using was created manually (because learning is fun). Below is a rough overview (not a tutorial) of the steps I used to create it.
fallocateto create the empty 2GB filefdiskto partition the filefdiskagain to find the byte offset of the start of the first partitionlosetupto attach that partition (unmounted) as a loop devicemkfs.ext4to format the partitionlosetupagain to detach the loop device
After that, you have essentially a bare hard disk image that can be passed to qemu.