Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First chunk of mkroot README. Still missing a lot.
- Loading branch information
Showing
1 changed file
with
206 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
mkroot - simple linux system builder | ||
|
||
Compiles a toybox-based root filesystem and kernel that can boot under qemu. | ||
|
||
Prebuilt binaries available from http://landley.net/bin/mkroot/latest | ||
launched via ./run-qemu.sh (which assumes you have QEMU installed, KVM | ||
works in a pinch), and then run "exit" to shut down the emulated system. | ||
|
||
This project is a successor to https://landley.net/aboriginal/about.html | ||
and shares most of the same goals, with a much simpler implementation. | ||
|
||
--- Quick Start | ||
|
||
To install the build prerequisites: download toybox source, linux kernel source, | ||
and one or more musl cross compiler toolchain(s) in the "ccc" directory: | ||
|
||
$ cd toybox | ||
$ git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux | ||
$ wget https://landley.net/bin/toolchains/latest/i686-linux-musl-cross.tar.xz | ||
$ mkdir ccc | ||
$ tar xvJCf ccc i686-linux-musl-cross-tar.xz | ||
|
||
Then invoke mkroot like: | ||
|
||
$ mkroot/mkroot.sh CROSS=i686 LINUX=linux | ||
$ root/i686/run-qemu.sh | ||
|
||
This project is a successor to https://landley.net/aboriginal/about.html | ||
and shares most of the same goals, with a much simpler implementation. | ||
|
||
--- Building without a cross compiler (warning: glibc sucks) | ||
|
||
Running ./mkroot.sh with no arguments and no $CROSS_COMPILE environment | ||
variable builds a statically linked root filesystem with the host's compiler. | ||
|
||
$ mkroot/mkroot.sh | ||
|
||
You can then chroot into it like this: | ||
|
||
$ sudo chroot output/host/root /init | ||
$ ls -l | ||
$ exit | ||
|
||
Unfortunately, glibc doesn't properly support static linking, so if your host | ||
Linux uses glibc the build will spit out a bunch of warnings indicating | ||
all sorts of glibc features won't work (DNS lookups always fail, ls -l can't | ||
read names out of /etc/password, etc). This is a known problem with glibc, | ||
because ex-maintainer Ulrich Drepper had a strong personal dislike of static | ||
linking and actively sabotaged it. | ||
|
||
If building on a non-glibc system, such as Alpine Linux, you're fine. | ||
Otherwise, you'll probably want to cross compile with a musl-libc toolchain | ||
to avoid glibc's very long list of static linking bugs. (The resulting root | ||
filesystem is also significantly smaller: a stripped statically linked | ||
"hello world" binary for x86-64 is 5420 bytes with musl-libc, and 682,696 bytes | ||
with glibc.)</p> | ||
|
||
--- Building with a cross compiler. | ||
|
||
The variable $CROSS_COMPILE indicates the toolchain prefix to apply to | ||
commands such as "cc" and "ld". Since prefixed cross compiler names tend | ||
to look like "armv5l-cc" this prefix tends to end with a dash. | ||
|
||
$ mkroot/mkroot.sh CROSS_COMPILE=armv5l- | ||
|
||
If you haven't added the cross compiler to your $PATH, you can specify | ||
a path as part of the prefix: | ||
|
||
$ mkroot/mkroot.sh CROSS_COMPILE=~/x86_64-linux-musl-cross/bin/x86_64-linux-musl-cross- | ||
|
||
Don't forget the trailing dash. | ||
|
||
Alternately, the variable $CROSS (as used in the Quick Start above) tells | ||
mkroot to look in the "ccc" directory for a cross compiler starting with | ||
a short name: | ||
|
||
$ mkroot/mkroot.sh CROSS=s390x | ||
|
||
That would look (using wildcards) for ccc/s390x-*cross/bin/s390x*-cc and | ||
if found, work out the appropriate $CROSS_COMPILER prefix to use for the | ||
corresponding other tools. Use "CROSS=help" to see the list of cross compilers | ||
currently available in the ccc directory. | ||
|
||
You only need to set one of $CROSS or $CROSS_COMPILE, the other gets derived | ||
from the one you provided. | ||
|
||
The downloadable toolchains were built with toybox's scripts/mcm-buildall.sh | ||
running in a fresh checkout of https://github.com/richfelker/musl-cross-make | ||
and are available as prebuilt binaries from https://landley.net/bin/toolchains | ||
(The "native" compilers run _on_ the target system, as well as producing | ||
binaries for them. Those are packaged as squashfs filesystems, to be loopback | ||
mounted within qemu.) | ||
|
||
--- Adding a kernel | ||
|
||
On the mkroot command line add LINUX= pointing to a kernel source directory: | ||
|
||
$ mkroot/mkroot.sh CROSS=sh4 LINUX=~/linux | ||
|
||
This will build a kernel for the appropriate target, package the filesystem | ||
as cpio.gz for use by initramfs, and create a run-qemu.sh script to invoke | ||
qemu. This results in the following files under root/$CROSS: | ||
|
||
initramfs.cpio.gz - the "fs" dir packaged for initramfs, plus any $MODULES | ||
linux-kernel - the compiled kernel | ||
linux.dtb - The device tree binary (if this target requires one) | ||
run-qemu.sh - the qemu invocation to run it all | ||
|
||
And also: | ||
|
||
fs/ - the generated root filesystem (you can chroot here) | ||
docs/ - Additional information not needed to run qemu. | ||
|
||
The run-qemu.sh script will connect together the appropriate -kernel, -initrd, | ||
and -dtb arguments to consume the provided files, as well as -m board and | ||
-append "kernel command line arguments". The KARGS environment variable is | ||
added to the kernel command line arguments, and any additional arguments | ||
provided to the script are passed through to qemu, so you can do: | ||
|
||
$ KARGS="rdinit=/bin/sh" ./run-qemu.sh -hda blah.img | ||
|
||
Running the script should boot the kernel to a command prompt, with the | ||
serial console connected to stdin and stdout of the qemu process so you can | ||
just type into it and see the output. The generated kernel config should | ||
provide basic NAT network support (as if behind a router) and block device | ||
support. | ||
|
||
--- Environment variables | ||
|
||
Any "name=value" argument provided on the mkroot.sh command line will set | ||
an environment variable, and any string that without an = indicates a package | ||
script to run before building toybox (explained below). This is why CROSS= | ||
CROSS_COMPILE= and LINUX= were all set on the command line above. | ||
|
||
For portability reasons, mkroot.sh clears all environment variables at the | ||
start of its run, with the following exceptions: | ||
|
||
LINUX - Linux kernel source directory. | ||
CROSS_COMPILE - Cross compiler prefix (sets $CROSS from prefix before first -) | ||
CROSS - Short target name (sets $CROSS_COMPILE from ccc) | ||
HOME - Absolute path to user's home directory. | ||
PATH - Executable path to find binaries. | ||
NOCLEAR - Don't clear environment variables. (Can't set on command line.) | ||
|
||
Other interesting variables to set on the command line include: | ||
|
||
NOAIRLOCK - don't do a hermetic build, just use the $PATH's tools. | ||
NOLOGPATH - don't use the command line recording wrapper | ||
NOLOG - don't record build output to root/build/log/$CROSS.[yn] | ||
NOTOYBOX - don't build toybox | ||
PENDING - extra commands to enable out of toys/pending | ||
KEXTRA - Additional kernel symbols to enable (in short CSV format) | ||
MODULES - Kernel modules to build (in short CSV format) | ||
|
||
--- Adding build modules | ||
|
||
You can run additional build scripts from the mkroot/packages directory by | ||
listing them on the command line: | ||
|
||
$ mkroot/mkroot.sh dropbear overlay OVERLAY=~/blah | ||
|
||
Any "name=value" argument provided on the command line will set an environment | ||
variable in mkroot (explained above), and any string that without an = | ||
indicates a package script to run before building toybox. | ||
|
||
The provided build scripts mostly download source tarballs, cross compile them, | ||
and install them into the root filesystem. Additional package build instructions | ||
are available from the "Linux From Scratch" (http://linuxfromscratch.org/lfs) | ||
and "Beyond Linux From Scratch" (http://linuxfromscratch.org/blfs) projects. | ||
|
||
If you specify any packages, the "plumbing" package is automatically read first | ||
to provide the download, setupfor, and cleanup shell functions to fetch and | ||
manage source tarballs, and set the $DOWNLOAD variable (defaulting to store | ||
downloaded tarballs in "./root_download"). | ||
|
||
The "overlay" script copies the $OVERLAY directory (default "./overlay") | ||
into the root filesystem, so you can add arbitrary additional files. | ||
|
||
The "dynamic" script attempts to copy dynamic libraries out of the | ||
toolchain, to allow a dynamically linked root filesystem. It's a work in | ||
progress. (A debian host toolchain can have multiple gigabytes of shared | ||
libraries.) | ||
|
||
The "tests" script copies the toybox test suite into the new filesystem, | ||
downloads some test files, and adds some test modules to the kernel build. | ||
|
||
--- Creating new build modules | ||
|
||
Build scripts run after creating the directory layout and writing | ||
the the init script and etc files (resolv.conf/passwd/group), but before | ||
building toybox. | ||
|
||
These scripts are sourced, not run, so environment variables you set remain | ||
in force. The following variables can affect the remaining mkroot.sh build: | ||
|
||
NOTOYBOX - if set, toybox will not be installed into the new root filesystem | ||
KEXTRA - additional kernel symbols to enable (in same CSV format as $KCONF) | ||
QEMU_MORE - Additional qemu command line arguments added to run-qemu.sh | ||
|
||
To append instead of replacing (in case they're already set), you can use | ||
QEMU_MORE="$QEMU_MORE --blah" and KEXTRA="${KEXTRA+$KEXTRA,}"BLAH,BLAH,BLAH | ||
|
||
If you check your own build scripts into mkroot/packages without touching | ||
any existing files, you should be able to "git pull --ff" to update your tree | ||
without conflicts. Alternately, you can add your script directory to the start | ||
of the $PATH and bash's "source" command will fall back to looking there next. |