Skip to content

caramelli/higfxback

Repository files navigation

HiGFXback (History of graphics backends) is a Linux from scratch distribution designed to preserve and maintain historical graphics backends on Linux systems.

This Linux distribution has a set of characteristics that make it unique.

First, by its construction: HiGFXback is a fully source-based distribution (system built entirely from source code) that relies on the C library of your choice (glibc, musl, …).

Second, it is possible with HiGFXback to run components natively based on the following graphics backends:

Other characteristics specific to HiGFXback are also detailed in the installation and usage procedure that follows.

Bootstrapping

The initial steps consist of creating and booting a minimal system that provides a shell environment for ordinary Unix-like tasks, in particular downloading and compiling source code.

Current versions of the GNU C compiler are written in C++, which means that a C++ compiler (typically g++) is needed to build gcc from source. The GNU Compiler Collection GCC 4.7 is the last version that can be built with only a C compiler (even a simple one such as tcc, the Tiny C compiler), thus it is used in the bootstrap process.

On the host system, enter the bootstrap directory, and optionally set MAKEFLAGS environment variable to speed up compilation:

$ cd bootstrap
$ export MAKEFLAGS=-j$(nproc)

The host system is used to build a cross-toolchain for the target system:

$ make toolchain

A single cross-toolchain capable of supporting multiple C libraries (glibc, musl, …) and based on Binutils, GCC (C compiler only), the Linux headers, is generated in a staging directory.

The same cross-compiler is thus used to build the various C libraries, each placed in a dedicated directory within the staging directory:

	  .                                          .                                         .
	  |                                          |                                         |
	  |-- bin                                    |-- glibc                                 |-- musl
	  |    |-- x86_64-unknown-linux-as                |-- bin                                   |-- bin
	  |    |-- x86_64-unknown-linux-gcc               |    |-- getconf                          |    |-- getconf
	  |    |-- x86_64-unknown-linux-ld                |    |-- ldd                              |    |-- ldd
	  |    |-- ...                                    |    |-- ...                              |    |-- ...
	  |                                               |                                         |
	  |--  include                                    |-- include                               |-- include
	  |    |-- asm                                    |    |-- math.h                           |    |-- math.h
	  |    |-- linux                                  |    |-- stdio.h                          |    |-- stdio.h
	  |    |-- ...                                    |    |-- ...                              |    |-- ...
	  |                                               |                                         |
	  |-- lib                                         |-- lib                                   |-- lib
	       |-- gcc                                         |-- crt1.o                                |-- crt1.o
	            |-- x86_64-unknown-linux                   |-- ld-linux-x86-64.so.2                  |-- ld-musl-x86_64.so.1
	                 |-- 4.7.4                             |-- libc.so                               |-- libc.so
	                      |-- cc1                          |-- libc.so.6                             |-- libc.so.6
	                      |-- crtbegin.o                   |-- libpthread.so                         |-- libpthread.so
	                      |-- crtend.o                     |-- ...                                   |-- ...
	                      |-- libgcc.a
	                      |-- ...
	                      |-- include
	                           |-- float.h
	                           |-- stddef.h
	                           |-- ...

Selecting which C library the cross-compiler will use is done with the stow command, which makes the headers and libraries of the chosen C library appear in the sysroot directory of the toolchain.

With the toolchain in place, cross-compile a minimal set of software required for an ISO image and for the minimal system installed on the target hardware.

For a minimal glibc-based system:

$ make initrd-glibc
$ make rootfs-glibc

For a minimal musl-based system:

$ make initrd-musl
$ make rootfs-musl

The initrd serves as an installer (and optionally as a rescue disk) for the distribution, and is composed of:

  • busybox, which combines lightweight versions of many Unix utilities
  • syslinux, with its EXTLINUX bootloader
  • the C library (glibc or musl), runtime files only (no development files)

The generated root filesystem contains only:

  • linux, the operating system kernel
  • busybox, providing the shell environment with standard Unix-like commands (same binary as in the initrd)
  • binutils, providing, among other tools, the assembler and linker used by the C compiler
  • gcc, the GNU C compiler
  • pkg-config, a tool typically invoked when compiling applications and libraries, but whose usage is extended to manage packages and their dependencies on the system
  • the C library (glibc or musl), both the runtime and development files

Since a common cross-compiler is used to build the source code regardless of the target C library, all binaries in the minimal system have the same dynamic linker/loader ld-linux.so.2 in the PT_INTERP ELF segment. But note that the compiler present in this minimal root filesystem, and used to build and install packages that will replace the initial minimal system binaries, compiles source code by setting the PT_INTERP ELF segment to the dynamic linker/loader name corresponding to the selected C library (i.e. ld-linux.so.2 for glibc or ld-musl-x86_64.so.1 for musl).

Next, generate the ISO image used for installation:

$ make iso-glibc

or :

$ make iso-musl

The target machine can now boot from the ISO image.

To test it on a virtual machine with QEMU, first create a disk image, then boot the VM, for example from the glibc-based ISO image, by attaching the created disk image to an ATA disk over a SATA AHCI controller:

$ qemu-img create disk-glibc-x86_64.img 64G
$ qemu-system-x86_64 -boot d -cdrom bootstrap-glibc-x86_64.iso -device ahci -drive id=disk,file=disk-glibc-x86_64.img,format=raw,if=none -device ide-hd,drive=disk

Or from the musl-based ISO image:

$ qemu-img create disk-musl-x86_64.img 64G
$ qemu-system-x86_64 -boot d -cdrom bootstrap-musl-x86_64.iso -device ahci -drive id=disk,file=disk-musl-x86_64.img,format=raw,if=none -device ide-hd,drive=disk

Once the VM has started, perform the installation from the guest system’s shell prompt:

# setup

The VM can now boot on the freshly installed minimal system (located on the disk image).

Installing packages

The package installation process relies on a specific tool named pkg-build, which starts by downloading the package source code from the Internet (if it has not already been downloaded).

When testing with a QEMU virtual machine, set up a virtual network interface on the host system (a TAP interface) to allow the VM to connect to the real network:

$ sudo ip tuntap add dev tap0 mode tap
$ sudo ip addr add 192.168.0.1/24 dev tap0
$ sudo ip link set tap0 up

If the dnsmasq DHCP server is not installed on the host system, install it and edit its /etc/dnsmasq.conf configuration file to include the following settings, then restart dnsmasq:

port=5353
interface=tap0
dhcp-option=option:dns-server,8.8.8.8
dhcp-range=192.168.0.101,192.168.0.200

As a final step on the host system, enable IP forwarding and configure NAT so that traffic from the VM is passed to the Internet and replies from the Internet can reach the VM:

$ sudo sh -c 'echo 1 > /proc/sys/net/ipv4/ip_forward'
$ sudo iptables -t nat -A POSTROUTING -o $(ip -o link show up | awk -F': ' '{print $2}' | grep -E '^(en|eth|wl)' | head -n1) -j MASQUERADE

With the host system network fully configured, launch the VM, for example, the glibc-based VM:

$ qemu-system-x86_64 -monitor stdio -enable-kvm -cpu host -smp 8 -m 8G -device ahci -drive id=disk,file=disk-glibc-x86_64.img,format=raw,if=none -device ide-hd,drive=disk -netdev tap,id=net0,ifname=tap0,script=no -device e1000,netdev=net0 -usb -device usb-tablet -device intel-hda -device hda-duplex

Or the musl-based VM:

$ qemu-system-x86_64 -monitor stdio -enable-kvm -cpu host -smp 8 -m 8G -device ahci -drive id=disk,file=disk-musl-x86_64.img,format=raw,if=none -device ide-hd,drive=disk -netdev tap,id=net0,ifname=tap0,script=no -device e1000,netdev=net0 -usb -device usb-tablet -device intel-hda -device hda-duplex

QEMU options used:

  • -monitor stdio to redirect the QEMU monitor to the host console.
  • -enable-kvm -cpu host to enable KVM acceleration with the host CPU exposed to the guest system.
  • `-smp 8 -m 8G_ to set 8 CPUs and 8 GiB of RAM.
  • -netdev tap,id=net0,ifname=tap0,script=no -device e1000,netdev=net0 to add an Intel e1000 network device connected to the host networking via the TAP interface.
  • -usb -device usb-tablet to add a USB controller with a USB tablet pointing device.
  • -device intel-hda -device hda-duplex to add an Intel High Definition Audio controller with microphone and speakers devices.

The VM is by default launched with a VGA-compatible display device, allowing the vesafb guest driver to expose a Linux Framebuffer device interface (/dev/fb0). To enable a KMS/DRM device interface (/dev/dri/card0), launch the VM with a VirtIO display device by adding the -device virtio-vga option to the QEMU command line, which is handled by the virtio_gpu guest driver.

Once the VM has started, run the DHCP client from the guest system’s shell prompt to automatically configure its network interface:

# udhcpc eth0

Then, enter the sources directory to begin installing packages, and optionally set the MAKEFLAGS environment variable to speed up compilations launched by the pkg-build tool:

# cd sources
# export MAKEFLAGS=-j$(nproc)

Installing core system components packages

Most packages are built using a build system such as Autoconf, Meson, or CMake.

The Autoconf build system is partly written in the M4 and Perl languages, the perl package itself depending on the bzip2 and zlib compression libraries. The m4 package, as well as the bzip2 and zlib packages, are built using the make utility, which is therefore the first package added to the system:

# pkg-build make

Once make is available:

# pkg-build m4
# pkg-build bzip2 zlib
# pkg-build perl
# pkg-build autotools-wrappers-ac autotools-wrappers-am mawk autotools-wrappers-lt

Note that building autotools-wrappers-lt requires mawk, as an awk-based script named inline-source, involved in the generation of libtoolize, fails when executed with busybox awk.

It is often convenient to have mouse support in virtual consoles to allow copy-and-paste operations instead of typing everything by hand, which is provided by the gpm daemon:

# pkg-build byacc gpm
# gpm -m /dev/input/event2 -t usbtablet

The Meson build system is written in Python 3 language and relies by default on ninja, an utility written in C++ which controls the generation of non-source files from source files (like the make utility). If ninja is missing on the system, meson fallback to samurai, a ninja-compatible implementation written in C that is installed to avoid a dependancy with g++ and libstdc++ packages:

# pkg-build expat python3
# pkg-build samurai
# pkg-build meson

The CMake build system is written in C++ language so depends on the availibility of g++ and libstdc++ packages. These are not required for installing and starting core graphics components, but if C++ compiler is needed by other components:

# pkg-build gmp mpfr mpc g++ libstdc++

Then, if the CMake build system is required to build a package:

# pkg-build curl
# pkg-build expat lz4 xz zstd libarchive
# pkg-build libuv
# pkg-build rhash
# pkg-build jsoncpp cmake3

Note that the CMake build system has support for both make (used by default) and ninja/samurai as non-source files generators from source files.

If the C++ compiler is available on the system, ninja can easiy be installed to replace samurai:

# pkg-build ninja

When launching the VM with the default VGA-compatible display device, the guest can also expose a KMS/DRM device interface (/dev/dri/card0) if the Linux kernel includes support for the simpledrm driver. Since the simpledrm driver is only available in Linux kernels requiring a gcc version newer than 4.7 (and therefore Linux kernels more recent than the one used in the bootstrap), this introduces an indirect dependency of the Linux kernel on g++ and libstdc++ packages. Assuming these packages are present, the following command can be used to update the Linux kernel:

# pkg-build byacc flex bison diffutils findutils elfutils openssl ncurses linux

Note that building linux requires diff command from diffutils package, as it is invoked with the -I option, which is not supported by busybox diff, and find command from findutils package, as it is invoked with the -printf option, which is not supported by busybox find.

Installing core graphics components packages

For the Linux Framebuffer graphics backend:

# pkg-build byacc flex bison fbset
# pkg-build util-macros libfontenc freetype mkfontscale mkfontdir
# pkg-build ttf-bitstream-vera
# pkg-build fb/ft2tf fb/fbpad

For the KMS/DRM graphics backend graphics backend:

# pkg-build libdrm
# pkg-build byacc flex bison
# pkg-build util-macros xkeyboard-config libxkbcommon
# pkg-build libudev-zero libtsm kmscon

For the DirectFB graphics backend:

# pkg-build dfb/directfb2 dfb/directfb2-tools
# pkg-build dfb/lite dfb/dfbterm

For the X11 graphics backend:

# pkg-build util-macros x11/xproto x11/libxau
# pkg-build x11/xtrans
# pkg-build libfontenc freetype
# pkg-build x11/fontsproto x11/libxfont
# pkg-build x11/bigreqsproto x11/inputproto x11/kbproto x11/xcmiscproto
# pkg-build x11/renderproto x11/videoproto x11/xextproto x11/fixesproto x11/damageproto x11/randrproto
# pkg-build libmd pixman xkeyboard-config x11/libpciaccess x11/xorg-server
# pkg-build x11/xf86-video-fbdev x11/xf86-input-evdev
# pkg-build x11/libx11
# pkg-build x11/libxkbfile x11/xkbcomp
# pkg-build x11/libxext
# pkg-build x11/libxrender x11/xdpyinfo
# pkg-build util-linux x11/libice x11/libsm x11/libxt
# pkg-build x11/libxmu x11/twm
# pkg-build mkfontscale mkfontdir ttf-bitstream-vera
# pkg-build x11/libxpm x11/libxaw
# pkg-build expat fontconfig x11/libxft
# pkg-build ncurses x11/xterm

For the Wayland graphics backend:

# pkg-build libffi expat
# pkg-build wl/wayland wl/wayland-protocols
# pkg-build byacc flex bison
# pkg-build util-macros xkeyboard-config libxkbcommon
# pkg-build libevdev libudev-zero mtdev libinput
# pkg-build pcre util-linux python3 glib freetype fontconfig libpng pixman wl/cairo
# pkg-build jpeg wl/weston

About

History of graphics backends on Linux system

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published