Kjetil's Information Center: A Blog About My Projects

Linux Distribution for LOADLIN

This is a similar project to the Linux Distribution for 386SX but this with some different goals. Most importantly to boot it with LOADLIN directly from DOS and keeping the root filesystem in RAM using Cramfs. In addition, I wanted to have functioning SLIP support.

I ended up using these specific software versions:
* linux-2.4.37.11
* gcc-3.4.6
* busybox-1.19.4
* uClibc-0.9.33.2
* binutils-2.32

Get the necessary scripts, configuration and patches here to make it yourself. Or just get the completed kernel and root filesystem here.

For easy reference, here is the script to compile everything:

#!/bin/bash
set -e

TARGET="i386-linux-uclibc"
PREFIX="${HOME}/opt/gcc-${TARGET}/"
SYSROOT="${PREFIX}/${TARGET}/sysroot"

GCC_SRC="gcc-3.4.6.tar.bz2"
BINUTILS_SRC="binutils-2.32.tar.xz"
UCLIBC_SRC="uClibc-0.9.33.2.tar.xz"
LINUX_SRC="linux-2.4.37.11.tar.xz"
BUSYBOX_SRC="busybox-1.19.4.tar.bz2"

export PATH="${PREFIX}bin:$PATH"

# Prepare Prefix and System Root
if [ -d "$SYSROOT" ]; then
  echo "Old system root directory detected, please remove it."
  exit 1
else
  mkdir -p "$SYSROOT/usr"
fi

# Prepare Build Directories:
if [ -d build ]; then
  echo "Old build directory detected, please remove it."
  exit 1
else
  mkdir -p build/binutils
  mkdir -p build/gcc-stage1
  mkdir -p build/gcc-stage2
  mkdir -p build/uclibc
  mkdir -p build/linux
  mkdir -p build/busybox
fi

# Unpack Sources:
if [ -d source ]; then
  cd source
  tar -xvjf "$GCC_SRC"
  tar -xvJf "$BINUTILS_SRC"
  tar -xvJf "$UCLIBC_SRC" -C ../build/uclibc
  tar -xvJf "$LINUX_SRC" -C ../build/linux
  tar -xvjf "$BUSYBOX_SRC" -C ../build/busybox
  cd -
else
  echo "No source directory, please download sources."
  exit 1
fi

# Patch gcc-3.4.6:
cd "source/gcc-3.4.6/gcc/config/i386/"
if ! fgrep --silent "inhibit_libc" linux.h; then
  patch -p 0 < ../../../../../gcc-3.4.6-linux.h.patch
fi
cd -

# Patch linux-2.4.37.11:
cd "build/linux/linux-2.4.37.11/include/linux/"
if ! fgrep --silent "<linux/types.h>" filter.h; then
  patch -p 0 < ../../../../../linux-2.4.37.11-filter.h.patch
fi
cd -

# Install Linux 2.4 Headers:
cd build/linux/linux-*
make ARCH=i386 mrproper
make ARCH=i386 include/linux/version.h
make ARCH=i386 symlinks
mkdir -p "$SYSROOT/usr/include/asm"
cp -v -R -H include/asm "$SYSROOT/usr/include"
cp -v -R include/asm-generic "$SYSROOT/usr/include"
cp -v -R include/linux "$SYSROOT/usr/include"
touch "${SYSROOT}/usr/include/linux/autoconf.h"
cd -

# Build binutils:
cd build/binutils
../../source/binutils-*/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot="$SYSROOT" --disable-werror --enable-languages=c,c++ --enable-shared --without-newlib --disable-libgomp --enable-fast-install=N/A
make all-{binutils,gas,ld}
make install-{binutils,ld,gas}
cd -

# Build Stage 1 GCC3:
cd build/gcc-stage1
../../source/gcc-3*/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot="$SYSROOT" --with-cpu=i386 --disable-fast-install --disable-werror --disable-multilib --enable-languages=c --without-headers --disable-shared --disable-libssp --disable-libmudflap --with-newlib --disable-c99 --disable-libgomp --disable-threads
make all-gcc
make install-gcc
cd -

# Install uClibc Headers:
cd build/uclibc/uClibc-*
cp -v ../../../config-uclibc .config
sed -i -e "s%KERNEL_HEADERS=.*%KERNEL_HEADERS=\"$SYSROOT/usr/include/\"%" .config
make ARCH=i386 PREFIX="$SYSROOT" install_headers
cd -

# Build uClibc:
cd build/uclibc/uClibc-*
make ARCH=i386 PREFIX="$SYSROOT"
make ARCH=i386 PREFIX="$SYSROOT" install
cd -

# Build Stage 2 GCC3:
cd build/gcc-stage2
../../source/gcc-3*/configure --target="$TARGET" --prefix="$PREFIX" --with-sysroot="$SYSROOT" --with-cpu=i386 --enable-fast-install=N/A --disable-werror --enable-languages=c,c++ --disable-shared --without-newlib --disable-libgomp --disable-threads
make all-gcc
make install-gcc
cd -

# Build Linux 2.4:
cd build/linux/linux-*
cp -v ../../../config-linux .config
make ARCH=i386 CROSS_COMPILE=i386-linux-uclibc- oldconfig
make ARCH=i386 CROSS_COMPILE=i386-linux-uclibc- dep
make ARCH=i386 CROSS_COMPILE=i386-linux-uclibc- bzImage
cd -

# Build Busybox:
cd build/busybox/busybox-*
cp -v ../../../config-busybox .config
make CROSS_COMPILE=i386-linux-uclibc-
cd -
          


And here is the script to make the root filesystem:

#!/bin/bash
set -e

ROOTFS="`pwd`/rootfs/"

TARGET="i386-linux-uclibc"
PREFIX="${HOME}/opt/gcc-${TARGET}/"
SYSROOT="${PREFIX}/${TARGET}/sysroot"

export PATH="${PREFIX}bin:$PATH"

if [ -d "$ROOTFS" ]; then
  echo "Old root FS directory detected, please remove it."
  exit 1
fi
mkdir -p "$ROOTFS"

# Install Busybox:
cd build/busybox/busybox-*
make CROSS_COMPILE=i386-linux-uclibc- CONFIG_PREFIX="$ROOTFS" install
cd -

# Create some essential directories
cd "$ROOTFS"
mkdir etc
mkdir etc/init.d
mkdir lib
mkdir proc
mkdir sys
mkdir tmp
mkdir root
mkdir dev
mkdir dev/pts
cd -

# Initial rc.S:
cat > rcS <<EOF
#!/bin/sh
mount -t proc /proc /proc
mount -t devpts /dev/pts /dev/pts
mount -t tmpfs /tmp /tmp
loadkmap < /etc/no-latin1.bmap
hostname busybox
EOF
mv -v rcS "$ROOTFS/etc/init.d/"

# Initial inittab:
cat > inittab <<EOF
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::restart:/sbin/init
EOF
mv -v inittab "$ROOTFS/etc/"

# Copy this system's keymap:
loadkeys -b /usr/share/kbd/keymaps/i386/qwerty/no-latin1.map.gz > "$ROOTFS/etc/no-latin1.bmap"

# Make everything root user:
sudo chown -R root:root "$ROOTFS"

# Create some critical devices:
sudo mknod "$ROOTFS/dev/tty" c 5 0
sudo mknod "$ROOTFS/dev/console" c 5 1
sudo mknod -m 0666 "$ROOTFS/dev/null" c 1 3

# Create some useful devices:
sudo mknod "$ROOTFS/dev/rtc" c 10 135
sudo mknod "$ROOTFS/dev/tty0" c 4 0
sudo mknod "$ROOTFS/dev/tty1" c 4 1
sudo mknod "$ROOTFS/dev/tty2" c 4 2
sudo mknod "$ROOTFS/dev/tty3" c 4 3
sudo mknod "$ROOTFS/dev/ttyS0" c 4 64
sudo mknod "$ROOTFS/dev/ttyS1" c 4 65
sudo mknod "$ROOTFS/dev/fd0" b 2 0
sudo mknod "$ROOTFS/dev/fd1" b 2 1
sudo mknod "$ROOTFS/dev/root" b 4 0
sudo mknod "$ROOTFS/dev/lp0" c 6 0

# SetUID on busybox binary:
sudo chmod +s "$ROOTFS/bin/busybox"

# Make rcS executable:
sudo chmod +x "$ROOTFS/etc/init.d/rcS"

# Make Compressed ROM archive:
mkfs.cramfs rootfs rootfs.cramfs
          


Instead of using LOADLIN, it is actually easy to start this with QEMU as well, like so:

qemu-system-i386 -kernel bzImage -initrd rootfs.cramfs
          


Topic: Configuration, by Kjetil @ 12/09-2020, Article Link