Building a Linux 5.17-rc7 kernel for sparc32 for fun

Most of the files mentioned are available at: dashie/sparc32: Dashie’s various sparc32 things – sparc32 – Dashie’s gitea

This git repository also contains a bootable gentoo-sparc-2005.0-20050413.tftpboot with a 2.x kernel, the rootfs contained into that tftpboot file has been extracted to gentoo-sparc-2005.0-20050413.initrd that you can use, without any kernel modules or newer busybox because of space restriction, but it does have an init and dropbear and more tools than juste a busybox.

So you can uses it as your root.img file, and skipping the kernel modules.

This guide has been useful for the creation of the rootfs.


This guide has been written and tested on Ubuntu 20.04.4 LTS.


# Global
sudo apt install git build-essential
# For crosstool-ng toolchain
sudo apt install flex texinfo unzip help2man gawk libtool libtool-bin libncurses-dev bison bc

Building elftoaout, needed to convert the kernel elf to a a.out file

mkdir linux
cd linux


# Extract archives
tar xvf sparc-utils_1.9.orig.tar.gz
gunzip sparc-utils_1.9-4.diff.gz

# Apply various patches
patch -p0 < sparc-utils_1.9-4.diff
cd sparc-utils-1.9.orig
patch -p1 < ../sparc-utils-1.9-no-implicit.patch
patch -p1 < ../elftoaout-2.3-64bit_fixes-1.patch

# Build and install
cd elftoaout-2.3
sudo cp elftoaout /usr/local/bin
sudo cp elftoaout.1 /usr/share/man/man1/elftoaout.1

# Ensure it runs
elftoaout --help
# returns:
# Usage: elftoaout [-o output] [-c|-b] [-V] input

Building a GCC toolchain

We will uses the crosstool-ng project to build a sparc-unknown-linux-gnu toolchain.

First to install crosstool-ng utility:

cd ~
# get wanted version
export VERSION=1.25.0-rc1
git clone -b crosstool-ng-$VERSION
cd crosstool-ng
./configure --prefix=/opt/crosstool
sudo make install
# To use the tools you need to update your path, example for bash:
echo 'export PATH=${PATH}:/opt/crosstool/bin' >> $HOME/.bashrc
source $HOME/.bashrc
# Check path
echo $PATH
# Example:
# /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/crosstool/bin
# Test crosstool-ng util:
ct-ng --version
# returns
# GNU Make 4.2.1
# Built for x86_64-pc-linux-gnu
# ...

Then we make a toolchain:

cd ~/linux
# this will create a sample ".config" in the current (~/linux) directory for the toolchain
ct-ng sparc-unknown-linux-gnu
# now to build the toolchain, this took ~1h30 on my virtual machine
ct-ng build
# And the toolchain is now built:
dashie@asperge:~$ ls ~/x-tools/sparc-unknown-linux-gnu/bin/
sparc-unknown-linux-gnu-addr2line  sparc-unknown-linux-gnu-cpp           sparc-unknown-linux-gnu-gcc-ar      sparc-unknown-linux-gnu-gcov-tool  sparc-unknown-linux-gnu-lto-dump  sparc-unknown-linux-gnu-ranlib
sparc-unknown-linux-gnu-ar         sparc-unknown-linux-gnu-ct-ng.config  sparc-unknown-linux-gnu-gcc-nm      sparc-unknown-linux-gnu-gprof      sparc-unknown-linux-gnu-nm        sparc-unknown-linux-gnu-readelf
sparc-unknown-linux-gnu-as         sparc-unknown-linux-gnu-elfedit       sparc-unknown-linux-gnu-gcc-ranlib  sparc-unknown-linux-gnu-ld         sparc-unknown-linux-gnu-objcopy   sparc-unknown-linux-gnu-size
sparc-unknown-linux-gnu-c++filt    sparc-unknown-linux-gnu-gcc           sparc-unknown-linux-gnu-gcov        sparc-unknown-linux-gnu-ld.bfd     sparc-unknown-linux-gnu-objdump   sparc-unknown-linux-gnu-strings
sparc-unknown-linux-gnu-cc         sparc-unknown-linux-gnu-gcc-11.2.0    sparc-unknown-linux-gnu-gcov-dump   sparc-unknown-linux-gnu-ldd        sparc-unknown-linux-gnu-populate  sparc-unknown-linux-gnu-strip
dashie@asperge:~$ ~/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu-gcc --version
sparc-unknown-linux-gnu-gcc (crosstool-NG 1.25.0_rc1) 11.2.0

Summary of actions

  • configure kernel
  • build kernel
  • generate a rootfs with a busybox
  • install kernel modules in the rootfs
  • unmount the rootfs and compress its image
  • generate the kernel tftpboot.img (which uses the hardcoded /usr/src/root.img rootfs)
  • enjoy

Building the kernel

# Wanted version from
export VERSION=5.17-rc7
cd ~/linux
git clone --depth=1 -b v$VERSION linux-$VERSION
cd linux-$VERSION

# Generate a default config
ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make sparc32_defconfig

# Then launch menuconfig to edit it
ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make menuconfig

# And set:
# General Setup
#  Compiler optimization level (set to -Os)
# Device Drivers
#  Generic Driver Options (enable thoses two)
#    [*] Maintain a devtmpfs filesystem to mount at /dev
#    [*]   Automount devtmpfs at /dev, after the kernel mounted the rootfs
# It will takes the size down to ~4.9M (optimization) and enable auto population of /dev without having to manually create the nodes

# Build the kernel
ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make

Generating the rootfs (root.img) and finalizing the kernel image

# Create a 4M file, there is some restrictions of size with the OpenBoot PROM and >4M seems to make it burp
sudo dd if=/dev/zero of=/usr/src/root.img bs=1M count=4

# Format in EXT2
sudo mkfs.ext2 /usr/src/root.img

# Mount the file partition
sudo mount -o loop /usr/src/root.img /mnt/
cd /mnt/

# Create some required files
sudo mkdir -p bin dev dev/pts etc sbin usr/bin usr/sbin tmp proc sys
sudo cp ~/linux/busybox-sparc bin/busybox
sudo chmod +x bin/busybox
cd bin
# This will create a bunch of symbolic links for busybox
for i in $(busybox --list)
   sudo ln -s busybox $i
# Proc mount
cd ..
echo "proc                    /proc    proc            defaults               0 0" | sudo tee etc/fstab

cd ~/linux/linux-$VERSION
# Install the kernel modules
sudo ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make modules_install INSTALL_MOD_PATH=/mnt/

# Unmount the rootfs
sudo umount /mnt

cd /usr/src

# Create the root filesystem
# I choose a gzip, but you can do either a xz or gzip, as you wish
# To create a "xz" rootfs:
sudo xz --check=none --lzma2=dict=1MiB root.img
sudo mv root.img.xz root.img
# To create a "gzip" one:
sudo gzip -v9 root.img
sudo mv root.img.gz root.img
# Your rootfs is now ready at /usr/src/root.img

# Note: if you want to update the modules in your rootfs:
cd /usr/src
sudo mv root.img root.img.xz
sudo xz -d root.img.xz
sudo mount -o loop /usr/src/root.img /mnt/
cd ~/linux/linux-$VERSION
sudo ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make modules_install INSTALL_MOD_PATH=/mnt/
sudo umount /mnt
cd /usr/src
sudo xz --check=none --lzma2=dict=1MiB root.img
sudo mv root.img.xz root.img

# Then you can finish making your final "tftpboot.img" file
cd ~/linux/linux-$VERSION
ARCH=sparc CROSS_COMPILE=$HOME/x-tools/sparc-unknown-linux-gnu/bin/sparc-unknown-linux-gnu- make tftpboot.img
# You can now put arch/sparc/boot/tftpboot.img in your TFTP root directory

Booting on sparc32

On my OpenBoot PROM I booted it with, where is my TFTP/RARP server:

boot net-aui:,tftpboot.img                                                                         

You can specify a kernel command line too:

boot net-aui:,tftpboot.img init=/bin/sh                                                            

For TFTP/RARP setup you can refer to this tutorial by me.


PROMLIB: obio_ranges 1
PROMLIB: Sun Boot Prom Version 3 Revision 2
Linux version 5.17.0-rc7 (dashie@aubergine) (sparc-unknown-linux-gnu-gcc (crosstool-NG 1.25.0_rc1) 11.2.0, GNU ld (crosstool-NG 1.25.0_rc1) 2.38) #1 Sun Mar 13 11:14:00 CET 2022
printk: bootconsole [earlyprom0] enabled
TYPE: Sun4m SparcStation10/20
/ # uname -a
Linux (none) 5.17.0-rc7 #1 Sun Mar 13 11:14:00 CET 2022 sparc GNU/Linux

Tags: ,

About: dashie

a squeaky otter

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.