Skip to content

Enable ia64 firmware build with "kernel only" cross-toolchains - #27

Open
johnny-mnemonic wants to merge 1 commit into
syunnPC:mainfrom
linux-ia64:mods-2
Open

johnny-mnemonic wants to merge 1 commit into
syunnPC:mainfrom
linux-ia64:mods-2

Conversation

@johnny-mnemonic

Copy link
Copy Markdown

Like for Ski the firmware for qemu-system-ia64 can be compiled with cross-toolchains consisting of only binutils and GCC. So remove the unneeded ABI part with this patch.

This allows to use the ia64 cross-toolchains built with buildall and available on:

...and will allow builds on arbitrary Linux distributions (our toolchains are for example made for x86_64 with Ubuntu 24.04 for use in GHA, Arnd Bergmann's are available for a variety of host architectures).

You only need to have the cross-tools in PATH during build.
E.g.:

$ export PATH=$PATH:/opt/gcc-15.2.0-nolibc/ia64-linux/bin

Tested to work fine on a not so recent Debian Sid on x86_64 and Pi OS on aarch64.

Like for Ski the firmware for qemu-system-ia64 can be compiled with
cross-toolchains consisting of only binutils and gcc. So remove the
unneeded ABI part.

This allows to use the ia64 cross-toolchains built with buildall
and available on:

* https://www.kernel.org/pub/tools/crosstool/

* https://ftp.machine-hall.org/pub/epic-linux/toolchains/x86_64/

Signed-off-by: Johnny Mnemonic <jm@machine-hall.org>
@kristibektashi

kristibektashi commented Aug 6, 2026

Copy link
Copy Markdown

You should be able to use both in my opinion. Meaning if the ia64-linux-gnu-* toolchain is there it should use it, otherwise it should fall back to ia64-linux-* (or the other way around). This also has the advantage of not breaking existing workflows

@johnny-mnemonic

@johnny-mnemonic

Copy link
Copy Markdown
Author

@kristibektashi
Well, it actually is already the case, if one defines the respective tool vars when running the build command, as done by the workflow used here ATM via the corresponding Makefile.

But when building the firmware with ninja it seems to use roms/ia64-firmware/build_firmware.sh directly instead:

$ time ninja -v -C build roms/ia64-firmware/ia64-firmware.bin
ninja: Entering directory `build'
[1/1] /usr/bin/sh ../roms/ia64-firmware/build_firmware.sh roms/ia64-firmware/ia64-firmware.bin roms/ia64-firmware/ia64-firmware.elf roms/ia64-firmware/ia64-firmware.map roms/ia64-firmware/ia64-firmware.sections /srv/ssd/qemu-system-ia64-linux-ia64/roms/ia64-firmware roms/ia64-firmware/ia64-firmware.d
/opt/gcc-17-20260802-nolibc/ia64-linux/bin/ia64-linux-ld: warning: roms/ia64-firmware/ia64-firmware.elf has a LOAD segment with RWX permissions

real	0m10.479s
user	0m10.277s
sys	0m0.146s

Still, the Makefile can be modified to use what is available, but this makes the patch uneccessarily complex for no reason, as firmware is firmware and not a userland program. Also the usually used toolchain from Fedora Core only pretends to be a full one from the naming of the tools, but in reality is a "kernel only" one like ours or Arnd's, see description from Fedora.

I vibed a second patch (not part of the PR, see below) with Gemini, but it looks awkward. It should (1) either use the CROSS prefix when defined in the environment or the make command or (2) try to detect an existing ia64-linux[-gnu]- toolchain. If it can't find one, it assumes a native build with native ia64 tools:

From 2cc2e64664a2cf8036c252776983d365b5d697ee Mon Sep 17 00:00:00 2001
From: Johnny Mnemonic <jm@machine-hall.org>
Date: Thu, 6 Aug 2026 11:05:45 +0200
Subject: [PATCH] Also adapt firmware Makefile to auto-detect the available
 cross-toolchain

Defaults to native build when no cross-toolchains are found in `$PATH`.

Assisted-by: Gemini:gemini-2.5-pro
Signed-off-by: Johnny Mnemonic <jm@machine-hall.org>
---
 roms/ia64-firmware/Makefile | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/roms/ia64-firmware/Makefile b/roms/ia64-firmware/Makefile
index 209bc66..e2d4efa 100644
--- a/roms/ia64-firmware/Makefile
+++ b/roms/ia64-firmware/Makefile
@@ -1,7 +1,22 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 # Thin wrapper around the canonical firmware build script.
 
-CROSS   ?= ia64-linux-gnu-
+PATH_DIRS := $(subst :, ,$(PATH))
+CROSS_GCC := $(wildcard $(addsuffix /ia64-linux-gnu-gcc,$(PATH_DIRS)))
+
+ifdef CROSS_GCC
+	CROSS_TOOL_PREFIX := ia64-linux-gnu-
+else
+	CROSS_GCC := $(wildcard $(addsuffix /ia64-linux-gcc,$(PATH_DIRS)))
+	ifdef CROSS_GCC
+		CROSS_TOOL_PREFIX := ia64-linux-
+	else
+		# native build
+		CROSS_TOOL_PREFIX :=
+	endif
+endif
+
+CROSS   ?= $(CROSS_TOOL_PREFIX)
 AS      = $(CROSS)as
 CC      = $(CROSS)gcc
 LD      = $(CROSS)ld
-- 
2.25.1

...which works according to my test:

$ export firmware_dir="roms/ia64-firmware" binary="$firmware_dir/ia64-firmware.bin" elf="$firmware_dir/ia64-firmware.elf" map="$firmware_dir/ia64-firmware.map" sections="$firmware_dir/ia64-firmware.sections"

$ make -C "$firmware_dir" clean
make: Entering directory '/srv/ssd/qemu-system-ia64-linux-ia64/roms/ia64-firmware'
rm -f ia64-fw-*.o ia64-fw-*.o.d ia64-firmware.bin ia64-firmware.elf ia64-firmware.map ia64-firmware.sections ia64-firmware.d
make: Leaving directory '/srv/ssd/qemu-system-ia64-linux-ia64/roms/ia64-firmware'

$ make -C "$firmware_dir" -j"$(nproc)"
make: Entering directory '/srv/ssd/qemu-system-ia64-linux-ia64/roms/ia64-firmware'
AS="ia64-linux-as" CC="ia64-linux-gcc" LD="ia64-linux-ld" OBJCOPY="ia64-linux-objcopy" SIZE="ia64-linux-size" \
	./build_firmware.sh ia64-firmware.bin ia64-firmware.elf \
	ia64-firmware.map ia64-firmware.sections . ia64-firmware.d
/opt/gcc-17-20260802-nolibc/ia64-linux/bin/ia64-linux-ld: warning: ia64-firmware.elf has a LOAD segment with RWX permissions
make: Leaving directory '/srv/ssd/qemu-system-ia64-linux-ia64/roms/ia64-firmware'

But I figure, setting $CROSS to the desired value and work with that instead might be the best solution, when using the Makefile. It's also way simpler to set that in the .github/workflows/build.yml workflow file and use it in the currently two direct tool invocations. And as this file is meant for !ia64 systems (GHA provides x86_64 and aarch64), we can safely ignore the native case here.

So I think I will update my initial patch to do that in addition.

@johnny-mnemonic

johnny-mnemonic commented Aug 6, 2026

Copy link
Copy Markdown
Author

But as the current workflow installs the Fedora toolchain targetting ia64 anyways, the following patch is not needed, but shows how it can be done, no matter if the toolchain used has a ia64-linux-gnu- or ia64-linux- prefix. Hardcoding that prefix for any automatic builds leaves no question open for what is actually used. But it also requires extra changes if another toolchain is used.

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d88e6b5..b081be3 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -46,13 +46,22 @@ jobs:
         run: |
           set -euo pipefail
 
+          if ia64-linux-gnu-gcc --version &> /dev/null; then
+            export CROSS="ia64-linux-gnu-"
+          elif ia64-linux-gcc --version &> /dev/null; then
+            export CROSS="ia64-linux-"
+          else
+            echo "No cross toolchain targetting ia64 found. Cannot continue."
+            false
+          fi
+
           firmware_dir="roms/ia64-firmware"
           binary="$firmware_dir/ia64-firmware.bin"
           elf="$firmware_dir/ia64-firmware.elf"
           map="$firmware_dir/ia64-firmware.map"
           sections="$firmware_dir/ia64-firmware.sections"
 
-          test -f "$(ia64-linux-gnu-gcc -print-libgcc-file-name)"
+          test -f "$(${CROSS}gcc -print-libgcc-file-name)"
 
           make -C "$firmware_dir" clean
           make -C "$firmware_dir" -j"$(nproc)"
@@ -66,7 +75,7 @@ jobs:
             "$binary" \
             "$elf"
 
-          ia64-linux-gnu-readelf -h "$elf" > firmware-elf-header.txt
+          ${CROSS}readelf -h "$elf" > firmware-elf-header.txt
           grep -Eiq 'Machine:.*IA-64' firmware-elf-header.txt
 
       - name: Package the firmware

@kristibektashi

Copy link
Copy Markdown

There's a mistake in the last patch, where you export CROSS="ia64-linux-gnu-" insteead of CROSS="ia64-linux-" in the second case (the elif)

Also I do think the build_firmware.sh file should also consider both cases, simply because that might be what the user has installed in their system (since a full compiler can be used as a freestanding one anyway)

@johnny-mnemonic

Copy link
Copy Markdown
Author

There's a mistake in the last patch, where you export CROSS="ia64-linux-gnu-" insteead of CROSS="ia64-linux-" in the second case (the elif)

Indeed, thanks. Fixed now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants