Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ Rootless cross-compilation of Gentoo stages using crossdev and hakoniwa
| odroid-xu4 | armv7a | mainline v7.2 | signed BL1/BL2/TZSW + U-Boot | `-O2 -march=armv7ve -mtune=cortex-a15.cortex-a7 -mfpu=neon-vfpv4` | testing |
| orangepi-5-ultra | aarch64 | mainline v7.2 | TFA + U-Boot + rkbin | `-O3 -mcpu=cortex-a76.cortex-a55+crc+crypto` | testing |
| pentium-mmx | i586 | mainline v6.18 | BIOS (no firmware) | `-O2 -march=pentium-mmx` | testing |
| dell-dimension-4100 | i686 | mainline v7.2 | BIOS (no firmware) | `-O2 -march=pentium3` | testing |
| premier-p550 | riscv64 | mainline v7.2-rc1 | vendor QSPI (OpenSBI + U-Boot) + extlinux | `-O3 -march=rv64gc_zba_zbb` | testing |
| vsrves01 | riscv32 | mainline v6.18 + patches | VSDSP6/VSOS DDRLoad (no U-Boot/OpenSBI) | `-Os -march=rv32ima_zicsr_zifencei` | experimental (hardware dead) |
| ch32v467 | riscv32 | mainline v7.1 + patches (buildroot) | none: MCU firmware is the machine (tiny-rv32ima) | `-Os -march=rv32ima_zicsr_zifencei` | experimental (never run on hardware) |

## CLI

Expand Down Expand Up @@ -244,7 +246,7 @@ by `uboot`.
| `BOARD_GCC_VERSION` | no | Pin gcc: `15` (slot), `15.2` (prefix), or exact version (default: highest installed slot) |
| `KERNEL_TAG` | no | Kernel git ref (default: top-level `TAG`) |
| `KERNEL_ARCH` | no | Linux `ARCH=` value (default: auto from `BOARD_ARCH`) |
| `BUILD_STEPS` | no | Build pipeline steps (default: deps checkout bootloader kernel assemble pack); custom step names require a matching `override-<step>.sh` hook |
| `BUILD_STEPS` | no | Build pipeline steps (default: deps checkout bootloader kernel assemble pack); custom step names require a matching `override-<step>.sh` hook and build with the cross toolchain |
| `BOOT_PIPELINE` | no | Ordered bootloader stages (default: `("opensbi" "uboot" "syslinux" "grub")`; `()` = none) |
| `BOOT_EXTLINUX` | no | `true` makes `assemble` write `/extlinux/extlinux.conf` |
| `BOOT_APPEND` | no | Kernel arguments added to that entry |
Expand Down Expand Up @@ -411,7 +413,6 @@ Distinct from `enter` below, which opens a shell in the container the *build*
runs in: the build host, with the cross compiler, and the target mounted at
`/target`.

### Debugging a build
### Debugging a build

`enter` opens a shell in the very container a build step runs in -- same
Expand Down Expand Up @@ -457,7 +458,6 @@ The measurement is the ABI and ISA checks below, against the finished image.
They are the only thing that can fail a build, because they are the only thing
that reads the artifact.

### ABI verification
### ABI verification

Nothing in a binary package records the libc or the compiler that produced it.
Expand Down
122 changes: 122 additions & 0 deletions boards/dell-dimension-4100/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Dell Dimension 4100 (Pentium III Coppermine, i815E)

Retail Socket 370 desktop, 2000 vintage. Pentium III Coppermine at
866/933/1000 MHz (MMX and SSE, no SSE2), Intel 815E chipset (FW82815 GMCH
plus FW82801BA ICH2), up to 512 MB PC133, one serial port, two USB 1.1
ports, Ultra ATA disk, Phoenix BIOS (newest A11). Dell's OEM build of
Intel's D815EEA; the UART is on an SMSC LPC47M102 Super I/O.

Nothing here has been booted on the hardware. Every claim below comes
from the kernel tree, the chipset datasheets and Dell's archived tech
specs, not from a serial log.

## Boot chain

No firmware stage of any kind: no U-Boot, no OpenSBI, no vendor blob.

```
BIOS (Phoenix A11, on-board flash)
-> MBR boot code = GRUB boot.img, patched at byte 92 with the LBA of core.img
-> core.img in the gap at LBA 1, prefix (hd0,msdos1)/grub
-> /grub/grub.cfg on the FAT32 boot partition
-> /bzImage
```

`grub-mkimage` runs in the sandbox; the i386-pc modules come from the
crossdev prefix, built by the same portage package version as the host
tool, so the module ABI matches. `genimage.cfg` writes only the first 440
bytes of `boot.img` so the disk signature and partition table survive.

## Disk layout

MBR, 512-byte sectors.

| Offset | Size | Contents |
|---|---|---|
| 0 | 440 B | GRUB `boot.img` |
| 440 | 4 B | disk signature, half of the root `PARTUUID` |
| 512 | up to 1 MiB | GRUB `core.img` |
| 1 MiB | 128 MiB | boot partition, FAT32, type 0x0c, bootable |
| 129 MiB | rest | root partition, ext4, type 0x83 |

Everything is inside the first 8.4 GB, so it is reachable whether the BIOS
answers the INT 13h LBA extension check or falls back to CHS.

Root is named `PARTUUID=${BOOT_DISK_ID}-02`, not `/dev/sda2`: the disk is
`sda` only while it is master on the primary IDE channel, and this machine
has two channels and a CD-ROM. `root=LABEL=` cannot be used at all, with
or without a device path: `early_lookup_bdev()` in `block/early-lookup.c`
takes only `PARTUUID=`, `PARTLABEL=`, `/dev/` and a raw device number, and
`PARTLABEL` is GPT-only. There is no initramfs to resolve anything else.

## Kernel

Mainline v7.2, `i386_defconfig` plus two fragments.

`kernel-config/pentium3` sets `CONFIG_MPENTIUMIII=y`. The defconfig names
no processor family, so the `arch/x86/Kconfig.cpu` choice defaults to
`M686`; MPENTIUMIII adds `-mtune=pentium3` and turns on
`X86_INTEL_USERCOPY`.

`kernel-config/dimension-4100` adds `CONFIG_SND_INTEL8X0=y` (8086:2445,
the ICH2 AC97 controller behind Dell's "SoundMAX 2.0") and
`CONFIG_VORTEX=y` (the 3C905C-TXM Dell listed as an option), and turns
`CONFIG_DRM_I915` off.

The defconfig already has ATA_PIIX, BLK_DEV_SD, E100, SERIAL_8250 with
its console, USB_UHCI_HCD, and EXT4_FS and VFAT_FS built in, which is what
lets the kernel mount root with no initramfs.

## Compiler flags

`-O2 -march=pentium3 -pipe`, arch `i686`.

Coppermine has MMX and SSE and no SSE2. `-march=pentium3` is exactly that
ISA; every `-march` above it turns SSE2 on and an SSE2 instruction faults
on this CPU. `-mfpmath` is left at its 387 default on purpose, because
SSE1 has no double precision. `i686` rather than `i586` so that Gentoo's
`default/linux/x86/23.0/i686` profile, whose `CPU_FLAGS_X86="mmx sse"`,
tells ebuilds the same thing the compiler is emitting.

## Write the image

```sh
xzcat gentoo-linux-dell-dimension-4100_dev-disk-<timestamp>.img.xz \
| sudo dd of=/dev/<target> bs=4M status=progress conv=fsync
```

Write it to the PATA disk in a USB enclosure or on another machine's IDE
channel, then put it back as master on the primary channel. The root
partition grows to the end of the disk on first boot (`grow-rootfs`).

## Console

Serial is COM1, `ttyS0` at 115200 8N1, and it is the last `console=` on
the command line, so it owns `/dev/console`. `console=tty0` comes first,
so the monitor sees the boot messages too.

## Known not to work

- **Integrated video is unaccelerated VGA text.** Nothing in this tree
binds the 815's GMCH: i915's `pciidlist` starts at `INTEL_I830_IDS`,
`INTEL_I815_IDS` (0x1132) is defined in `include/drm/intel/pciids.h` and
referenced nowhere under `drivers/`, and the legacy `drm/i810` driver is
gone. `CONFIG_FB_I810` still exists but does not build as shipped:
`i810_accel.c` calls `cfb_fillrect`, `cfb_copyarea` and `cfb_imageblit`
while its Kconfig entry selects `FB_IOMEM_FOPS`, which pulls in none of
them, instead of `FB_IOMEM_HELPERS`, which selects all three. That looks
like an upstream Kconfig bug.
- **Which NIC is fitted is unknown.** Both drivers are built in, the
integrated Intel 10/100 (`e100`) and the optional 3C905C-TXM
(`3c59x`). One of them is dead weight on any given unit.
- **ACPI 1.0 and an SMP kernel with LOCAL_APIC/IO_APIC.** Both are common
sources of hangs on 2000-era firmware. The second GRUB entry boots with
`acpi=off noapic nolapic`; if the machine needs it every time, that
belongs in the first entry.
- **The RTC battery is flat.** `ntpd` is enabled rather than
`ntp-client`, which would run before dhcpcd has a lease and give up.

## Default credentials

- root, empty password (development image, change on first login)
- sshd enabled, `PermitRootLogin yes`, `PermitEmptyPasswords yes`
84 changes: 84 additions & 0 deletions boards/dell-dimension-4100/board.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
TAGS=("x86" "i686" "pentium3" "i815" "dell" "testing")
DESCRIPTION="Dell Dimension 4100 (Pentium III Coppermine, i815E + ICH2, BIOS/GRUB)"

# Retail desktop, Socket 370. Dell's archived tech specs give the
# configuration: Pentium III at 866/933/1000 MHz, 32 KB L1 and 256 KB
# on-die L2, Intel 815E chipset, 64 MB upgradeable to 512 MB PC133 SDRAM,
# one serial port, two USB ports, Ultra ATA EIDE disk, ACPI 1.0, Phoenix
# BIOS (newest A11). The board is Dell's OEM build of Intel's D815EEA:
# FW82815 GMCH plus FW82801BA ICH2, with an SMSC LPC47M102 Super I/O
# carrying the UART.

BOARD_ARCH="i686"
CROSS_COMPILE="i686-pc-linux-gnu-"
KERNEL_ARCH="x86"

# Coppermine is MMX and SSE and no SSE2, which is exactly what gcc means
# by -march=pentium3: it defines __MMX__, __SSE__ and __FXSR__ and leaves
# __SSE2__ undefined. Every -march above it (pentium-m, pentium4) turns
# SSE2 on, and an SSE2 instruction faults on this CPU.
#
# -mfpmath is deliberately unset: the default is 387 and it has to stay
# 387, because SSE1 has no double precision.
#
# -O2, not the -O3 default_cflags() falls back to for an arch it has no
# entry for. -O2 is also what Gentoo's own arch/x86/i686 profile ships,
# so this is the profile's flags with its -march sharpened to the real
# CPU. i686 rather than i586 for the same reason: gentoo_profile("i686")
# selects default/linux/x86/23.0/i686, whose CPU_FLAGS_X86="mmx sse"
# matches what the compiler is actually emitting.
BOARD_CFLAGS="-O2 -march=pentium3 -pipe"

# The pin the other mainline boards carry. The store key is the gcc PVR
# plus the CFLAGS hash, so leaving it unset moves the cache on every gcc
# bump.
BOARD_GCC_VERSION="16.1.0"

# BIOS boot, no firmware stage of any kind: boot.img in the MBR, core.img
# in the gap before the first partition, grub.cfg on the FAT boot
# partition. GRUB_PLATFORMS is load-bearing -- bootloader/grub.rs returns
# early without it, and it is what puts the i386-pc modules in the
# crossdev prefix the post-assemble hook copies from.
GRUB_PLATFORMS="pc"
# The default pipeline would no-op its way to the same place; naming the
# one real stage says so out loud.
BOOT_PIPELINE=("grub")

KERNEL_REPO="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git"
KERNEL_TAG="v7.2"
KERNEL_DEFCONFIG="i386_defconfig"
# Applied in this order after the defconfig, and every line is asserted
# afterwards. pentium3 is the CPU model, dimension-4100 is this machine.
KERNEL_CONFIG_FRAGMENTS="pentium3 dimension-4100"

BOOT_HOSTNAME="gentoo-dimension-4100"

# rootfs is partition 2, named by the MBR PARTUUID the pack step stamps
# in. BOOT_DISK_ID is exported before this file is sourced, genimage.cfg
# writes the matching disk-signature, and the kernel spells the pair
# "{sig}-02" itself (block/partitions/msdos.c), so no initramfs is
# needed. root=LABEL= is not an option at all: early_lookup_bdev()
# (block/early-lookup.c) takes only PARTUUID=, PARTLABEL=, /dev/ and a
# raw device number, and PARTLABEL is GPT-only. A /dev/ path would be
# wrong for a different reason: the disk is sda only while it is master
# on the primary IDE channel, and this machine has two and a CD-ROM.
BOOT_ROOT_DEV="PARTUUID=${BOOT_DISK_ID}-02"

# The one serial port, COM1 on the LPC47M102 Super I/O. post-assemble.sh
# puts console=tty0 in front of this, so boot messages also reach the
# monitor this machine has; the last console= owns /dev/console.
BOOT_CONSOLE="ttyS0,115200n8"
BOOT_SERIAL_TTY="ttyS0"
BOOT_SERIAL_BAUD="115200"

BOOT_KERNEL_NAME="bzImage"

# ntpd, not ntp-client: the CR2032 in a machine this old is flat, so the
# RTC is wrong at every boot. ntp-client is a one-shot that runs before
# dhcpcd has a lease and gives up; ntpd keeps trying and its default -g
# steps the first offset however large. net-misc/ntp and app-admin/metalog
# are already in defaults/target-packages.txt.
BOOT_SERVICES=("sshd:default" "dhcpcd:default" "metalog:default" "ntpd:default")

# There is no SD card in this machine; it boots off the PATA disk.
IMAGE_NAME="gentoo-linux-dell-dimension-4100_dev-disk.img"
78 changes: 78 additions & 0 deletions boards/dell-dimension-4100/genimage.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
config {
outputpath = .
inputpath = .
rootpath = gen
tmppath = tmp
}

image rootfs.ext4 {
ext4 {
use-mke2fs = "true"
label = "rootfs"
}

size = 4G
mountpoint = "/root"
}

/* FAT32, not ext4. Nothing in this machine's firmware reads a filesystem
* (the BIOS reads sectors, GRUB reads the rest), so the format is free, and
* FAT is the one both grub's fat.mod and a DOS rescue floppy can open. */
image bootfs.vfat {
vfat {
extraargs = "-F 32"
label = "bootfs"
}

size = 128M
mountpoint = "/boot"
}

image gentoo-linux-dell-dimension-4100_dev-disk.img {
hdimage {
partition-table-type = "mbr"
/* Derived from the board and exported by the pack step; genimage
* writes 0 when unset, which every other unsigned disk also claims.
* BOOT_ROOT_DEV names the PARTUUID built from this signature, so the
* value is load-bearing here, not cosmetic. */
disk-signature = "${BOOT_DISK_SIG}"
}

/* 1 MiB in, so LBA 1..2047 stays free for core.img (tens of KiB). Well
* inside the first 8.4 GB, so it is reachable whether the A11 BIOS
* answers the INT 13h LBA extension check or falls back to CHS. */
partition bootfs {
image = "bootfs.vfat"
offset = "1M"
size = "128M"
partition-type = 0x0c
bootable = true
in-partition-table = "true"
}

/* Last partition; grow-rootfs extends it to the end of the real disk on
* first boot with sfdisk ",+". */
partition rootfs {
image = "rootfs.ext4"
offset = "129M"
size = ""
partition-type = 0x83
in-partition-table = "true"
}

/* GRUB i386-pc: boot.img into the MBR boot code, core.img into the gap.
* grub-boot.img and grub-core.img are staged by the bootloader step.
*
* boot.img carries the LBA of core.img at offset 92 (kernel_sector);
* grub-install patches it and nothing else does, so it is patched here.
*
* Only the first 440 bytes of boot.img are written. Bytes 440..511 are
* the disk signature, the partition table and the 0x55AA genimage has
* already laid down, and writing 512 bytes here would destroy the
* signature root= depends on. */
exec-post = 'cp /build/grub-boot.img /build/boot-patched.img && \
printf "\001\000\000\000\000\000\000\000" | \
dd of=/build/boot-patched.img bs=1 seek=92 count=8 conv=notrunc 2>/dev/null && \
dd if=/build/boot-patched.img of=$IMAGEOUTFILE bs=440 count=1 conv=notrunc 2>/dev/null && \
dd if=/build/grub-core.img of=$IMAGEOUTFILE bs=512 seek=1 conv=notrunc 2>/dev/null'
}
29 changes: 29 additions & 0 deletions boards/dell-dimension-4100/kernel-config/dimension-4100
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Dell Dimension 4100: the peripherals i386_defconfig does not carry.
#
# What it already carries was read out of the defconfig, not assumed:
# ATA_PIIX=y (its PCI table has 8086:244B "Intel ICH2 UDMA 100"),
# BLK_DEV_SD=y, E100=y (8086:2449 is the ICH2 integrated LAN),
# SERIAL_8250=y with SERIAL_8250_CONSOLE=y, USB_UHCI_HCD=y, and EXT4_FS=y
# and VFAT_FS=y both built in, which is what lets the kernel mount root
# with no initramfs. VGA_CONSOLE is default y on x86 and not
# user-selectable without EXPERT, so the text console needs no line here.

# 82801BA ICH2 AC97 controller, 8086:2445 in sound/pci/intel8x0.c, which
# names it "Intel 82801BA-ICH2". Dell's solution guide calls the
# integrated audio "ADI SoundMAX 2.0", an AC-link codec snd-ac97-codec
# drives. Not SND_HDA_INTEL, which is what the defconfig carries and
# which this chipset predates by years.
CONFIG_SND_INTEL8X0=y

# 3Com 3C905C-TXM, which Dell's tech specs list as an option alongside the
# integrated Intel 10/100 that CONFIG_E100 already covers. Only opening
# the case says which is fitted, so both are built in.
CONFIG_VORTEX=y

# The 815's integrated video has no driver in this tree that can bind it.
# i915's pciidlist starts at INTEL_I830_IDS; INTEL_I815_IDS (0x1132) is
# defined in include/drm/intel/pciids.h and referenced by nothing under
# drivers/, and the legacy drm/i810 driver is gone. Dropping it saves
# megabytes of always-resident text on a 512 MB machine and loses nothing:
# the console is VGA text mode either way.
# CONFIG_DRM_I915 is not set
12 changes: 12 additions & 0 deletions boards/dell-dimension-4100/kernel-config/pentium3
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Dell Dimension 4100: the CPU model.
#
# i386_defconfig names no processor family, so the choice in
# arch/x86/Kconfig.cpu takes its own default and lands on M686.
# MPENTIUMIII is the Coppermine entry, and two things follow from it that
# M686 does not give: Makefile_32.cpu adds -mtune=pentium3 on top of the
# same -march=i686, and X86_INTEL_USERCOPY turns on (its depends list in
# Kconfig.cpu names MPENTIUMIII and not M686).
#
# X86_L1_CACHE_SHIFT and X86_USE_PPRO_CHECKSUM come out the same either
# way, so those are not reasons.
CONFIG_MPENTIUMIII=y
Loading