001. Installing Debian's x32 port in 2020
↩
Some time ago I bought an HP rp5700 Piece of Shit Point of Sale system
with a 2.13GHz Core 2 Duo E6400, fascinating OEM assembly, and FreeDOS, fourth-hand –
follow this Twitter thread to experience this machine as its story'd unravelled.
Some time later, I decided to make a router out of it, and, having heard of x32
– 32-bit ABI/userland, with a long-mode kernel/CPU –
some time prior, that had become the architecture of choice.
x32
's proponents tout increased performance compared to amd64
, but I couldn't care less;
if you're looking for performance comparisons, this ain't it, I did this entirely because it was weird and rife with funny corner cases.
The Debian wiki X32Port page dates back to around when x32
was introduced in 2012 with such beautiful excerpts as:
The second [system] is the QEMU/Chroot guest, and it must run Debian 8/Jessie Unstable.
Which, while amusing, isn't very conducive to getting an x32
system up, nor are the outdated-at-best instructions.
So this is the combination of the things I've read and tried in order to install Debian "bullseye/sid" x32
on Wed Apr 1 22:02:50 UTC 2020 (it was already 0:02:50 the next day in my timezone but I forgot to set it; oh well):
debian-installer
existing for x32 would have solved most (all) of the problems with this install,
but #778195
is open since Feb 2015, and dead as of that very November.
The patch
from message #15 applied (relatively) cleanly on top of 1ab40c5
from Salsa,
barring one trivial conflict in debian/control
, but I couldn't figure out how to build it for x32
on my amd64
machine
(or in general, frankly).
Just for the fucks, I also tried to add and build a kernel config for x32
, which ended exactly like all my kernel-building endeavours of the past
(plus, tracking and building Debian updates ad infinitum sounds like a horrible time).
I also tried to cross-grade an installed amd64
system,
but doing it through buster-to-sid just™ refused to work,
and sid-to-sid broke on +b2
"Rebuild with ruby2.5 support dropped" binNMUs
existing for i386
and amd64
but not for x32
(being a few versions behind on some packages didn't help, either),
although, in the few days it's taken me to write this, it'd started to look like the rest of the architectures are catching up.
And so, it came time to install Debian without d-i
, like some sort of Arch user.
debootstrap
and root privileges.
Also a kernel that can run x32
binaries; Debian amd64
kernels can,
but have it disabled by default, and need a syscall.x32=y
parameter to do so
(I looked, out of curiosity:
Arch
doesn't support x32
at all, Gentoo
does,
Fedora and RHEL don't;
FreeBSD's "Linux® Binary Compatibility"
does not (as of 12.1)).
I used d-i
's rescue mode (rescue/enable=true
parameter) and added syscall.x32=y
in the bootloader manually,
this allowed me to use d-i
for some of the annoying config parts (hostname, network), and PXE-booting it was the most convenient for me.
In (reverse-)chronological order: a disklabel, a bootloader, an initramfs (generator),
a kernel (at time of writing this means Linux, since
FreeBSD is i386
/amd64
-only on x86,
Hurd is i386
-only),
an init, a user, configs –
/etc/fstab
, /etc/hosts
, timezone.
My target disklabel is a standard GPT-on-BIOS setup with a separate /boot
(this helps by allowing the use of partlabels throughout, since SZAROTKA-BOOT is longer than the vfat
maximum of 11):
nabijaczleweli@szarotka:~$ sudo fdisk -l
Disk /dev/sda: 149.5 GiB, 160041885696 bytes, 312581808 sectors
Disk model: WDC WD1600AAJS-6
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 22C172F7-4E1F-D244-A6DC-260DEE716A5F
Device Start End Sectors Size Type
/dev/sda1 2048 4095 2048 1M BIOS boot
/dev/sda2 4096 312377343 312373248 149G Linux root (x86-64)
/dev/sda3 312377344 312581774 204431 99.8M Linux extended boot
nabijaczleweli@szarotka:~$ sudo blkid
/dev/sda1: PARTLABEL="szarotka-bios-boot" PARTUUID="a331980b-475a-1f43-b985-0849341df04b"
/dev/sda2: LABEL="szarotka-root-ng" UUID="d9e8441a-1a97-47af-b002-d764ac46121b" TYPE="ext4"
PARTLABEL="szarotka-root" PARTUUID="52695edc-4993-654c-9e04-e30d9cc1e367"
/dev/sda3: SEC_TYPE="msdos" LABEL_FATBOOT="SZAROTKA-BO" LABEL="SZAROTKA-BO" UUID="F4E6-9A90"
TYPE="vfat" PARTLABEL="szarotka-boot" PARTUUID="c817f3e5-e3e5-2449-b0f2-23dbb523a239"
Pressing Tab in ISOLINUX et al. pops up the command-line, which looks vaguely like this:
Going through the rescue up to this menu ensures all the small annoying things are configured:
You can press Alt+F2/F3 to switch to a virtual terminal with a usable background and $TERM
.
Prepare the target VFS with all the partitions mounted first. | ~ # mkdir target ~ # mount /dev/disk/by-partlabel/szarotka-root target ~ # mkdir target/boot ~ # mount /dev/disk/by-partlabel/szarotka-boot target/boot |
Start off with a simple chroot. Note the ill-advised --no-check-gpg, but finding/downloading/extracting that .deb in a bare *X environment is too annoying to warrant itself.Note also the sid suite — no stable for as long as x32 is a port. |
~ # debootstrap --arch=x32 --variant=minbase --include=debian-ports-archive-keyring --no-check-gpg sid target https://deb.debian.org/debian-ports |
Now you can (try to) chroot into the new system; if you see chroot: can't execute '/bin/sh': exec format error,
your kernel doesn't support x32 executables.
On Debian kernels, verify that you have syscall.x32=y in /proc/cmdline .The bind-mounts of /dev, /sys, and /proc are there for the GRUB install and dracut's host-only mode; of /tmp and /run – to avoid leaving some mounted-over garbage in the target system. |
~ # mount --bind /dev target/dev ~ # mount --bind /sys target/sys ~ # mount --bind /proc target/proc ~ # mount --bind /run target/run ~ # mount -t tmpfs tmpfs target/tmp ~ # chroot target /bin/bash root@szarotka:/# # Huzzah! |
Sprinkle in your favourite init and initramfs generator. | root@szarotka:/# apt install systemd-sysv root@szarotka:/# apt install dracut --no-install-recommends |
The time has come to add a kernel, which is the only required amd64 part of the system
(if you need something from the non-free or contrib components (e.g. microcode tools),
you'll still need the amd64 packages, or to apt source and rebuild them for x32 ).Note the [arch] options –
those are to avoid errors from apt as it tries to find x32 in the non-ports repositories, and vice versa.Note also lack of deb-src spec for the ports repository,
as it doesn't have sources at all
(compare). |
root@szarotka:/# sed -i 's/deb/deb [arch=x32]/' /etc/apt/sources.list root@szarotka:/# cat >> /etc/apt/sources.list deb [arch=amd64] https://deb.debian.org/debian sid main contrib non-free deb-src https://deb.debian.org/debian sid main contrib non-free ^D root@szarotka:/# dpkg --add-architecture amd64 root@szarotka:/# apt update root@szarotka:/# apt install linux-image-amd64 --no-install-recommends |
And a bootloader (at time of writing grub2 recommends os-prober –
if you don't plan on running other OSs this can be --no-install-recommendsed). Remember: at the prompt, if unsure about the choice offered by GRUB, you can switch VTs again (Alt+F2/F3) and use blkid or lsblk. The sed adds the syscall toggle inside GRUB_CMDLINE_LINUX , rather than _DEFAULT ,
since it's required to boot the system at all
(not using a text editor because, despite ed being the standard text editor,
using sed/awk/cat is less annoying and easier to spec like this
(also, the normal vi derivatives were broken due to the aforementioned ruby2.5-related problem
(I ended up using nvi))). |
root@szarotka:/# apt install grub2 Configuring grub-pc ------------------- 1. /dev/sda (??? MB; ???) 2. - /dev/sda2 (??? MB; /) 3. - /dev/sda3 (??? MB; /boot) GRUB install devices: /dev/sda Installing for i386-pc platform. root@szarotka:/# sed -ri 's/(CMDLINE_LINUX=)""/\1"syscall.x32=y"/' /etc/default/grub root@szarotka:/# update-grub |
Various bits and bobs; /etc/resolv.conf was already set up during debootstrap. If using vfat for your /boot , check if your kernel sets FAT_DEFAULT_UTF8=y ,
or specify utf8=y instead of defaults .This /etc/hosts is really bare-bones and the d-i one is too long to reproduce here in full;
I'd recommend copying and modifying one from another host on your network.Previously this paragraph contained some ill-advised init-specific bollocks about setting timezones, reproduced below, instead of the dpkg-reconfigure; mistakes of my youth slash two weeks ago I guess. |
root@szarotka:/# cat > /etc/fstab PARTLABEL=szarotka-root / ext4 noatime 0 1 PARTLABEL=szarotka-boot /boot vfat defaults 0 2 ^D root@szarotka:/# cat > /etc/hosts 127.0.0.1 localhost 127.0.1.1 szarotka szarotka.local.nabijaczleweli.xyz ^D root@szarotka:/# dpkg-reconfigure tzdata Configuring tzdata ------------------ 1. Africa […] 7. Atlantic 8. Europe 9. Indian 10. Pacific 11. SystemV […] Geographic area: 8 4. Athens […] 32. Minsk 39. Prague 46. Simferopol 53. Ulyanovsk 60. Warsaw Time zone: 60 Current default time zone: 'Europe/Warsaw' Local time is now: Tue Apr 28 02:25:44 CEST 2020. Universal Time is now: Tue Apr 28 00:25:44 UTC 2020. root@szarotka:/# apt install sudo root@szarotka:/# adduser --ingroup users nabijaczleweli root@szarotka:/# adduser nabijaczleweli sudo |
This should ensure the system boots and is usable enough after doing so — press Ctrl+Alt+Del and find out!
If that didn't get your system to boot, please do shoot me an e-mail, but if it did, then that's all from me for today, except, maybe, one last thing?
Ever wondered what'd happen if you had inits but the kernel couldn't execute them? So did I:
Alright, bye!
Nit-pick? Correction? Improvement? Annoying? Cute? Anything? Don't hesitate to post
or open an issue!