rearchitechted things

This commit is contained in:
Josephine Pfeiffer 2025-06-02 15:21:38 +02:00
parent a7a7a6160b
commit 8b704b3189
No known key found for this signature in database
20 changed files with 659 additions and 620 deletions

View file

@ -16,63 +16,104 @@ on:
jobs: jobs:
build-and-release: build-and-release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write # Required for creating releases
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up Podman - name: Set up build tools
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y podman sudo apt-get install -y podman libarchive-tools wget
- name: Build containers - name: Build container
run: | run: make container
echo "Building required containers..."
# Build the main container
scripts/build-container.sh
- name: Build kernel - name: Check for required busybox
run: | run: |
echo "Building s390x kernel..." if [ ! -f "boot/busybox-s390x-static" ]; then
scripts/build-kernel-container.sh echo "❌ ERROR: Static busybox not found!"
echo ""
- name: Build s390x busybox echo "To build a release, you must first:"
run: | echo "1. SSH into z/VM: ssh -i zvm.pem -o StrictHostKeyChecking=no linux1@148.100.77.9"
echo "Building s390x busybox binary..." echo "2. Run the build script: ./scripts/build-busybox-zvm.sh"
# The build-all.sh script will handle this automatically echo "3. Transfer the busybox binary: scp -i zvm.pem linux1@148.100.77.9:~/busybox-s390x-static boot/"
# but we'll call it explicitly for clarity in CI echo "4. Commit the busybox binary to the repository"
if [ ! -f output/busybox-s390x-static ]; then echo ""
sudo podman run --rm \ echo "The busybox MUST be built natively on s390x hardware for proper static linking."
-v $PWD:/work \ exit 1
-v $PWD/output:/output \ else
-w /work \ echo "✅ Static busybox found at boot/busybox-s390x-static"
s390x-archlinux-dev \ ls -la boot/busybox-s390x-static
/work/scripts/build-busybox-s390x.sh
fi fi
- name: Build initramfs - name: Build complete system
run: | run: |
echo "Building s390x initramfs..." echo "Building s390x kernel and creating initramfs..."
scripts/build-initramfs-final.sh make all
- name: Prepare boot files
run: |
echo "Preparing boot configuration..."
scripts/prepare-boot.sh
- name: Prepare release artifacts - name: Prepare release artifacts
run: | run: |
mkdir -p release-artifacts mkdir -p release-artifacts
# Copy kernel # Check if build succeeded
cp output/vmlinuz-6.6.10-s390x release-artifacts/vmlinuz-linux-s390x if [ ! -f "boot/vmlinuz-linux" ] || [ ! -f "boot/initramfs-linux.img" ]; then
echo "❌ ERROR: Build artifacts not found!"
echo "Expected files:"
echo " boot/vmlinuz-linux"
echo " boot/initramfs-linux.img"
echo ""
echo "Available files in boot/:"
ls -la boot/
echo ""
echo "Available files in output/:"
ls -la output/ || echo "output/ directory not found"
exit 1
fi
# Copy initramfs # Copy kernel (from boot directory after make all)
cp output/initramfs-6.6.10-s390x.img release-artifacts/initramfs-linux-s390x.img cp boot/vmlinuz-linux release-artifacts/vmlinuz-linux-s390x
# Copy boot configuration files # Copy initramfs (from boot directory after make all)
cp -r boot/* release-artifacts/ cp boot/initramfs-linux.img release-artifacts/initramfs-linux-s390x.img
# Copy boot configuration files (excluding large binaries)
cp boot/arch.prm release-artifacts/
cp boot/generic.ins release-artifacts/
cp boot/initrd.addrsize release-artifacts/
cp boot/boot-info.txt release-artifacts/
# Copy busybox binary
cp boot/busybox-s390x-static release-artifacts/
# Get actual sizes
KERNEL_SIZE=$(du -h boot/vmlinuz-linux | cut -f1)
INITRAMFS_SIZE=$(du -h boot/initramfs-linux.img | cut -f1)
BUSYBOX_SIZE=$(du -h boot/busybox-s390x-static | cut -f1)
# Create build info file
cat > release-artifacts/BUILD_INFO.txt << EOF
Arch Linux s390x Build Information
==================================
Build Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
Kernel Version: 6.6.10
Architecture: IBM s390x (big-endian)
Component Sizes:
- Kernel: $KERNEL_SIZE
- Initramfs: $INITRAMFS_SIZE
- Busybox: $BUSYBOX_SIZE
Build Method:
- Kernel: Cross-compiled in Fedora container
- Busybox: Statically compiled on z/VM RHEL 9.6
- Initramfs: Generated with modified mkinitcpio
Status: Fully functional - boots to emergency shell
EOF
# Create checksums # Create checksums
cd release-artifacts cd release-artifacts
@ -82,10 +123,11 @@ jobs:
# Create tarball of all artifacts # Create tarball of all artifacts
tar -czf archlinux-s390x-${{ github.event.inputs.version }}.tar.gz -C release-artifacts . tar -czf archlinux-s390x-${{ github.event.inputs.version }}.tar.gz -C release-artifacts .
# Capture build information # Capture build information for GitHub release
echo "KERNEL_VERSION=6.6.10" >> $GITHUB_ENV echo "KERNEL_VERSION=6.6.10" >> $GITHUB_ENV
echo "MKINITCPIO_COMMIT=$(cd mkinitcpio-source && git rev-parse HEAD)" >> $GITHUB_ENV echo "BUSYBOX_VERSION=1.35.0" >> $GITHUB_ENV
echo "MKINITCPIO_SHORT_COMMIT=$(cd mkinitcpio-source && git rev-parse --short HEAD)" >> $GITHUB_ENV echo "KERNEL_SIZE=$KERNEL_SIZE" >> $GITHUB_ENV
echo "INITRAMFS_SIZE=$INITRAMFS_SIZE" >> $GITHUB_ENV
- name: Create GitHub Release - name: Create GitHub Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v1
@ -95,29 +137,41 @@ jobs:
body: | body: |
# Arch Linux s390x Port - ${{ github.event.inputs.version }} # Arch Linux s390x Port - ${{ github.event.inputs.version }}
**🎉 First successful Arch Linux port to IBM s390x mainframe architecture!**
${{ github.event.inputs.release_notes }} ${{ github.event.inputs.release_notes }}
## Build Information ## 📊 Build Information
- **Kernel Version**: ${{ env.KERNEL_VERSION }} - **Kernel Version**: ${{ env.KERNEL_VERSION }} (${{ env.KERNEL_SIZE }})
- **mkinitcpio**: Built from commit [`${{ env.MKINITCPIO_SHORT_COMMIT }}`](https://github.com/archlinux/mkinitcpio/commit/${{ env.MKINITCPIO_COMMIT }}) - **Initramfs**: ${{ env.INITRAMFS_SIZE }} with native s390x binaries
- **Build Date**: ${{ github.event.repository.updated_at }} - **Busybox Version**: ${{ env.BUSYBOX_VERSION }} (statically compiled on z/VM)
- **Architecture**: IBM s390x (big-endian mainframe)
- **Status**: ✅ **Fully functional** - boots to emergency shell
## Release Contents ## 📦 Release Contents
This release includes: This release includes:
- **vmlinuz-linux-s390x**: Linux kernel ${{ env.KERNEL_VERSION }} for s390x architecture - **vmlinuz-linux-s390x**: Bootable Linux kernel for s390x architecture
- **initramfs-linux-s390x.img**: Initial RAM filesystem with s390x busybox - **initramfs-linux-s390x.img**: Complete initramfs with s390x busybox and utilities
- **busybox-s390x-static**: Static busybox binary (2.3MB, built on z/VM)
- **Boot configuration files**: IPL configuration for s390x mainframes - **Boot configuration files**: IPL configuration for s390x mainframes
- **BUILD_INFO.txt**: Detailed build information
- **SHA256SUMS**: Checksums for all artifacts - **SHA256SUMS**: Checksums for all artifacts
## Quick Start ## 🚀 Quick Start
### Test with QEMU s390x:
```bash ```bash
# Download and extract # Download and extract
tar -xzf archlinux-s390x-${{ github.event.inputs.version }}.tar.gz tar -xzf archlinux-s390x-${{ github.event.inputs.version }}.tar.gz
# Test with QEMU # Install QEMU s390x emulation
sudo pacman -S qemu-system-s390x # Arch Linux
# or
sudo apt install qemu-system-s390x # Ubuntu/Debian
# Run the system
qemu-system-s390x \ qemu-system-s390x \
-machine s390-ccw-virtio \ -machine s390-ccw-virtio \
-cpu max \ -cpu max \
@ -128,18 +182,36 @@ jobs:
-nographic -nographic
``` ```
## Build Information ### Deploy to real IBM mainframe:
- Use the provided IPL configuration files
- Boot files are ready for z/VM or LPAR deployment
- **Kernel**: Linux 6.6.10 ## ✅ What Works
- **Architecture**: IBM s390x (big-endian)
- **Build System**: Container-based cross-compilation - **Complete boot chain**: IPL → kernel → initramfs → emergency shell
- **Status**: Boots to emergency shell - **Native s390x binaries**: All components built for mainframe architecture
- **Filesystem operations**: Mount, unmount, and basic file operations via busybox
- **IBM hardware support**: DASD, QETH, channel I/O drivers included
- **Console access**: Both 3215 and 3270 terminal support
## 🔧 Technical Achievements
- **Cross-compilation infrastructure**: Fedora containers with s390x toolchain
- **mkinitcpio adaptation**: Modified for cross-architecture initramfs building
- **Static linking solution**: z/VM native compilation eliminates dynamic library issues
- **Architecture compatibility**: Pure s390x environment without x86_64 contamination
---
*This represents a major milestone in porting Linux distributions to IBM mainframe architecture!*
draft: false draft: false
prerelease: false prerelease: false
files: | files: |
archlinux-s390x-${{ github.event.inputs.version }}.tar.gz archlinux-s390x-${{ github.event.inputs.version }}.tar.gz
release-artifacts/vmlinuz-linux-s390x release-artifacts/vmlinuz-linux-s390x
release-artifacts/initramfs-linux-s390x.img release-artifacts/initramfs-linux-s390x.img
release-artifacts/busybox-s390x-static
release-artifacts/BUILD_INFO.txt
release-artifacts/SHA256SUMS release-artifacts/SHA256SUMS
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

19
.gitignore vendored
View file

@ -29,13 +29,11 @@ Thumbs.db
# Log files # Log files
*.log *.log
# Claude context file
CLAUDE.md
# Build outputs # Build outputs
output/ output/
temp-initramfs/ temp-initramfs/
tmp-initramfs/ tmp-initramfs/
build-kernel/
# Temporary build scripts # Temporary build scripts
build-final-initramfs.sh build-final-initramfs.sh
@ -57,7 +55,6 @@ etc/
var/ var/
dev/ dev/
proc/ proc/
sys/
run/ run/
tmp/ tmp/
new_root/ new_root/
@ -67,5 +64,19 @@ early_cpio
buildconfig buildconfig
config config
VERSION VERSION
# Documentation
CLAUDE.md CLAUDE.md
PROJECT_SUMMARY.md PROJECT_SUMMARY.md
# Sec
*.pem
# Test artifacts
boot/rootfs-s390x.img
# Build artifacts in boot directory (regenerated by make)
boot/vmlinuz-linux
boot/initramfs-linux.img
boot/boot-info.txt
boot/.treeinfo

View file

@ -32,11 +32,13 @@ ARCH LINUX COMPONENTS:
- Used and adapted for s390x architecture support - Used and adapted for s390x architecture support
BUSYBOX BINARY: BUSYBOX BINARY:
- BusyBox v1.35.0 (output/busybox-s390x-native) - BusyBox v1.35.0 (boot/busybox-s390x-static)
- Licensed under GNU General Public License v2 - Licensed under GNU General Public License v2
- Source: https://busybox.net/downloads/busybox-1.35.0.tar.bz2 - Binary compiled natively on IBM z/VM RHEL 9.6
- Original source: https://busybox.net/downloads/busybox-1.35.0.tar.bz2
- Copyright (C) 1998-2023 Erik Andersen, Rob Landley, Denys Vlasenko and others - Copyright (C) 1998-2023 Erik Andersen, Rob Landley, Denys Vlasenko and others
- Full BusyBox license: https://git.busybox.net/busybox/tree/LICENSE - Full BusyBox license: https://git.busybox.net/busybox/tree/LICENSE
- Built with static linking for s390x architecture compatibility
LINUX KERNEL: LINUX KERNEL:
- Linux kernel s390x build based on upstream kernel - Linux kernel s390x build based on upstream kernel

125
Makefile
View file

@ -1,35 +1,113 @@
# Arch Linux s390x Port - Makefile # Arch Linux s390x Port - Makefile
.PHONY: all kernel initramfs boot test clean help # Output directories
OUTPUT_DIR := output
BOOT_DIR := boot
# Output files
KERNEL := $(OUTPUT_DIR)/arch/s390/boot/bzImage
INITRAMFS := $(OUTPUT_DIR)/initramfs-6.6.10-s390x.img
BUSYBOX := $(BOOT_DIR)/busybox-s390x-native
BOOT_KERNEL := $(BOOT_DIR)/vmlinuz-linux
BOOT_INITRAMFS := $(BOOT_DIR)/initramfs-linux.img
.PHONY: all kernel build-busybox busybox initramfs boot test test-rootfs clean help container
# Default target # Default target
all: kernel initramfs boot all: boot
# Build kernel # Build kernel
kernel: $(KERNEL): | $(OUTPUT_DIR)
@echo "Building s390x kernel..." @echo "Building s390x kernel..."
@./scripts/build-all.sh --kernel-only @./scripts/build-kernel-container.sh
# Build initramfs kernel: $(KERNEL)
initramfs:
# Build static busybox on z/VM (manual process)
build-busybox: | $(BOOT_DIR)
@if [ ! -f "$(BOOT_DIR)/busybox-s390x-static" ]; then \
echo "❌ ERROR: Static busybox not found!"; \
echo ""; \
echo "To build busybox, you must:"; \
echo "1. SSH into z/VM: ssh -i zvm.pem -o StrictHostKeyChecking=no linux1@148.100.77.9"; \
echo "2. Run the build script: ./scripts/build-busybox-zvm.sh"; \
echo "3. Transfer the resulting busybox binary back to: $(BOOT_DIR)/busybox-s390x-static"; \
echo ""; \
echo "The busybox MUST be built natively on s390x hardware for proper static linking."; \
exit 1; \
else \
echo "✅ Static busybox already exists at $(BOOT_DIR)/busybox-s390x-static"; \
fi
# Download busybox fallback (deprecated - use z/VM build)
download-busybox: | $(OUTPUT_DIR)
@echo "❌ Dynamic busybox download is deprecated"
@echo "Use z/VM static compilation instead:"
@echo " ssh -i zvm.pem linux1@148.100.77.9"
@echo " # Follow build-busybox-zvm.sh instructions"
@exit 1
# Check busybox binary (prefers static build)
$(BUSYBOX): | build-busybox
@if [ -f "$(BOOT_DIR)/busybox-s390x-static" ]; then \
ln -sf busybox-s390x-static $(BUSYBOX); \
echo "✅ Using static busybox"; \
elif [ -f "$(BUSYBOX)" ]; then \
echo "✅ Using existing busybox"; \
else \
echo "ERROR: No busybox binary found"; \
exit 1; \
fi
busybox: $(BUSYBOX)
# Build initramfs (depends on busybox)
$(INITRAMFS): $(BUSYBOX) | $(OUTPUT_DIR)
@echo "Building initramfs with mkinitcpio..." @echo "Building initramfs with mkinitcpio..."
@./scripts/build-all.sh --initramfs-only @./scripts/build-initramfs-final.sh
# Prepare boot files initramfs: $(INITRAMFS)
boot:
# Prepare boot files (depends on kernel and initramfs)
boot: $(KERNEL) $(INITRAMFS) | boot-dir
@echo "Preparing boot directory..." @echo "Preparing boot directory..."
@./scripts/prepare-boot.sh @./scripts/prepare-boot.sh
# Test with QEMU # Build container if needed
container:
@echo "Building s390x-archlinux-dev container..."
@./scripts/build-container.sh
# Test with QEMU (assumes boot files already exist)
test: test:
@if [ ! -f "$(BOOT_DIR)/vmlinuz-linux" ] || [ ! -f "$(BOOT_DIR)/initramfs-linux.img" ]; then \
echo "Error: Boot files not found. Run 'make all' first"; \
exit 1; \
fi
@echo "Testing s390x system with QEMU..." @echo "Testing s390x system with QEMU..."
@./scripts/run-qemu-initramfs-only.sh @./scripts/run-qemu-initramfs-only.sh
# Test with root filesystem (creates minimal rootfs and boots to it)
test-rootfs:
@if [ ! -f "$(BOOT_DIR)/vmlinuz-linux" ] || [ ! -f "$(BOOT_DIR)/initramfs-linux.img" ]; then \
echo "Error: Boot files not found. Run 'make all' first"; \
exit 1; \
fi
@echo "Testing s390x system with root filesystem..."
@./scripts/test-qemu-rootfs.sh
# Create directories
$(OUTPUT_DIR):
@mkdir -p $@
boot-dir:
@mkdir -p $(BOOT_DIR)
# Clean build artifacts # Clean build artifacts
clean: clean:
@echo "Cleaning build artifacts..." @echo "Cleaning build artifacts..."
@rm -rf output/* @rm -rf $(OUTPUT_DIR)/*
@rm -f boot/vmlinuz-linux boot/initramfs-linux.img @rm -f $(BOOT_KERNEL) $(BOOT_INITRAMFS)
@echo "Clean complete." @echo "Clean complete."
# Show help # Show help
@ -39,14 +117,19 @@ help:
@echo "Usage: make [target]" @echo "Usage: make [target]"
@echo "" @echo ""
@echo "Targets:" @echo "Targets:"
@echo " all - Build everything (kernel + initramfs + boot)" @echo " all - Build everything (kernel + initramfs + boot)"
@echo " kernel - Build s390x kernel only" @echo " kernel - Build s390x kernel only"
@echo " initramfs - Build initramfs only" @echo " build-busybox - Check for static s390x busybox (must be built on z/VM)"
@echo " boot - Prepare boot directory" @echo " busybox - Check s390x busybox binary exists"
@echo " test - Test with QEMU s390x emulation" @echo " initramfs - Build initramfs only (requires busybox)"
@echo " clean - Remove build artifacts" @echo " boot - Prepare boot directory"
@echo " help - Show this help message" @echo " container - Build development container"
@echo " test - Test with QEMU s390x emulation (initramfs only)"
@echo " test-rootfs - Test with QEMU and minimal root filesystem"
@echo " clean - Remove build artifacts"
@echo " help - Show this help message"
@echo "" @echo ""
@echo "Quick start:" @echo "Quick start:"
@echo " make all - Build complete system" @echo " make container - Build development container (first time only)"
@echo " make test - Test the built system" @echo " make all - Build complete system"
@echo " make test - Test the built system"

118
README.md
View file

@ -1,51 +1,80 @@
# Arch Linux s390x Port # Arch Linux s390x Port
**Successfully ported Arch Linux to IBM s390x mainframe architecture!** This repository contains a **complete, working** s390x Arch Linux system with full root filesystem support that boots successfully on IBM mainframes and QEMU emulation.
This repository contains a working s390x Arch Linux system that boots successfully on IBM mainframes and QEMU emulation.
## Quick Start ## Quick Start
```bash ```bash
# Build everything # Build everything
scripts/build-all.sh make all
# Test in QEMU # Test initramfs-only system
scripts/run-qemu-initramfs-only.sh make test
# Test with root filesystem
make test-rootfs
``` ```
## What's Working ## What's Working
- **s390x Kernel**: Linux 6.6.10 cross-compiled for IBM mainframes (11MB) - **s390x Kernel**: Linux 6.6.10 cross-compiled for IBM mainframes (11MB)
- **Initramfs**: Complete 5.3MB initramfs with s390x busybox - **Initramfs**: Complete 5.9MB initramfs with s390x busybox
- **Boot Process**: Successful boot to emergency shell - **Boot Process**: Successful boot to root filesystem with busybox shell
- **Root Filesystem**: **COMPLETE!** 100MB ext4 root filesystem with Arch Linux identification
- **QEMU Testing**: Fully functional in s390x emulation - **QEMU Testing**: Fully functional in s390x emulation
- **Ready for Hardware**: IPL configuration for real mainframes - **Ready for Hardware**: IPL configuration for real mainframes
## Build Status ## Build Status
### Core System Components
| Component | Status | Details | | Component | Status | Details |
|-----------|--------|---------| |-----------|--------|---------|
| Kernel | ✅ Working | 11MB bootable s390x kernel | | Kernel | ✅ Working | 11MB bootable s390x kernel (vanilla 6.6.10) |
| Initramfs | ✅ Working | 5.3MB with native s390x binaries | | Initramfs | ✅ Working | 5.9MB with native s390x binaries |
| Boot | ✅ Working | Reaches emergency shell successfully | | Boot Process | ✅ Working | IPL → kernel → initramfs → root filesystem |
| Root Filesystem | ✅ **COMPLETE** | 100MB ext4 with working busybox switch_root |
| mkinitcpio | ✅ Fixed | Adapted for s390x architecture | | mkinitcpio | ✅ Fixed | Adapted for s390x architecture |
### Userspace Components
| Component | Status | Details |
|-----------|--------|---------|
| Init System | 🟨 Minimal | Busybox init (not systemd) |
| Shell | 🟨 Minimal | Busybox sh (not bash) |
| Core Utilities | 🟨 Minimal | Busybox applets only |
| Package Manager | ❌ TODO | Pacman needs porting |
| Systemd | ❌ TODO | Requires cross-compilation |
| Bash | ❌ TODO | Needs s390x build |
| GNU Coreutils | ❌ TODO | Replace busybox applets |
| Arch Kernel Patches | ❌ TODO | Apply Arch-specific patches |
### Legend
- ✅ **Complete** - Fully working
- 🟨 **Minimal** - Working but minimal implementation
- ❌ **TODO** - Not yet implemented
## Build System ## Build System
Uses **Fedora containers with Podman** for cross-compilation: Uses **Fedora containers with Podman** for cross-compilation:
```bash ```bash
# Container images: # Container image:
s390x-fedora-kernel # Kernel compilation
s390x-archlinux-dev # All-in-one development container s390x-archlinux-dev # All-in-one development container
``` ```
### Build Targets:
- `make all` - Build complete system (kernel + initramfs)
- `make kernel` - Cross-compile s390x kernel only
- `make initramfs` - Generate initramfs with mkinitcpio
- `make test` - Test initramfs-only system with QEMU
- `make test-rootfs` - Test with root filesystem switching
- `make clean` - Clean build artifacts
### Key Scripts: ### Key Scripts:
- `scripts/build-all.sh` - Build complete system
- `scripts/build-kernel-container.sh` - Cross-compile kernel - `scripts/build-kernel-container.sh` - Cross-compile kernel
- `scripts/build-initramfs-final.sh` - Generate initramfs - `scripts/build-initramfs-final.sh` - Generate initramfs
- `scripts/run-qemu-initramfs-only.sh` - Test the system - `scripts/run-qemu-initramfs-only.sh` - Test initramfs-only system
- `scripts/test-qemu-rootfs.sh` - Test with root filesystem
- `scripts/build-busybox-zvm.sh` - Build static busybox on z/VM
## Testing ## Testing
@ -55,11 +84,16 @@ sudo pacman -S qemu-system-s390x # Arch Linux
# or # or
sudo apt install qemu-system-s390x # Ubuntu/Debian sudo apt install qemu-system-s390x # Ubuntu/Debian
# Run the system # Test initramfs-only system
scripts/run-qemu-initramfs-only.sh make test
# Test root filesystem switching
make test-rootfs
``` ```
**Expected**: System boots to emergency shell (press Ctrl-A X to exit) **Expected**:
- `make test` - System boots to emergency shell in initramfs-only mode (press Ctrl-A X to exit)
- `make test-rootfs` - Boots completely to root filesystem with busybox shell
[![asciicast](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9.svg)](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9) [![asciicast](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9.svg)](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9)
@ -68,8 +102,10 @@ scripts/run-qemu-initramfs-only.sh
After building: After building:
- `boot/vmlinuz-linux` - Ready-to-use s390x kernel - `boot/vmlinuz-linux` - Ready-to-use s390x kernel
- `boot/initramfs-linux.img` - Working initramfs - `boot/initramfs-linux.img` - Working initramfs
- `boot/rootfs-s390x.img` - Root filesystem image (created by test-rootfs)
- `boot/generic.ins` - IPL configuration for real hardware - `boot/generic.ins` - IPL configuration for real hardware
- `boot/arch.prm` - Kernel parameters - `boot/arch.prm` - Kernel parameters
- `boot/busybox-s390x-static` - Static busybox binary built on z/VM
## Technical Details ## Technical Details
@ -79,35 +115,25 @@ After building:
- Channel I/O subsystem drivers - Channel I/O subsystem drivers
- mkinitcpio modified for cross-architecture builds - mkinitcpio modified for cross-architecture builds
### Key Fix Applied: ### Key Fixes Applied:
Fixed mkinitcpio's `add_binary` vs `add_file` issue for init scripts, enabling successful boot without kernel panic. 1. **mkinitcpio adaptation** - Fixed `add_binary` vs `add_file` issue for init scripts
2. **Static busybox** - Built natively on z/VM to eliminate dynamic linking
3. **Architecture compatibility** - Fixed base hook to exclude x86_64 binaries
4. **Init script patching** - Modified standard Arch init to use `busybox switch_root`
## Known Minor Issues ## System Boot Success
1. **Mount binary PATH** - Busybox mount symlink needs PATH adjustment The system successfully boots from initramfs to root filesystem:
2. **No root filesystem** - Expected for initramfs-only mode
3. **Module warnings** - Harmless kmod messages
These don't prevent boot and will be addressed in future updates. ```
[ 22.867595] Run /init as init process
:: mounting '/dev/vda' on real root
[ 23.131648] EXT4-fs (vda): mounted filesystem r/w with ordered data mode
/ # cat /etc/os-release
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
## Next Steps / # uname -a
Linux arch 6.6.10 #14 SMP Mon Jun 2 14:59:34 UTC 2025 s390x GNU/Linux
This foundation enables: ```
- Building Arch Linux packages for s390x
- Creating full s390x repository
- Native pacman package manager
- Complete Arch Linux s390x distribution
## Success!
**This project proves Arch Linux can run on IBM s390x mainframes!**
The system successfully:
- Boots Linux kernel on s390x architecture
- Loads native s390x initramfs
- Provides working shell environment
- Ready for real mainframe deployment
---
*First successful Arch Linux port to IBM mainframe architecture!* 🚀

View file

@ -2,7 +2,7 @@ Arch Linux s390x Boot Directory
============================== ==============================
Kernel Version: 6.6.10 Kernel Version: 6.6.10
Build Date: Sat May 31 08:47:08 PM CEST 2025 Build Date: Mon Jun 2 05:00:32 PM CEST 2025
Architecture: s390x Architecture: s390x
Files: Files:
@ -12,6 +12,11 @@ Files:
- arch.prm: Kernel boot parameters - arch.prm: Kernel boot parameters
- initrd.addrsize: Memory layout for initrd - initrd.addrsize: Memory layout for initrd
To boot on real s390x hardware:
1. Transfer this boot directory to your z/VM or LPAR system
2. Use FTP or SFTP to copy files to the target system
3. IPL from the device containing these files
4. For z/VM: Use the generic.ins file for IPL
For QEMU testing: For QEMU testing:
make test make test

BIN
boot/busybox-s390x-static Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -5,10 +5,12 @@
build() { build() {
local applet local applet
echo "=== S390X BASE HOOK STARTING ==="
# Use s390x busybox binary if available (cross-architecture support) # Use s390x busybox binary if available (cross-architecture support)
if [[ -f "/work/output/busybox-s390x-static" ]]; then if [[ -f "/work/boot/busybox-s390x-static" ]]; then
echo "Using s390x static busybox binary" echo "Using s390x static busybox binary"
add_file "/work/output/busybox-s390x-static" "/bin/busybox" 755 add_file "/work/boot/busybox-s390x-static" "/usr/bin/busybox" 755
# Create symlinks for busybox applets (using a known list since we can't execute cross-arch binary) # Create symlinks for busybox applets (using a known list since we can't execute cross-arch binary)
local busybox_applets=( local busybox_applets=(
@ -16,16 +18,19 @@ build() {
"date" "dd" "df" "dirname" "dmesg" "du" "echo" "env" "expr" "false" "date" "dd" "df" "dirname" "dmesg" "du" "echo" "env" "expr" "false"
"find" "grep" "head" "hostname" "id" "kill" "ln" "ls" "mkdir" "mknod" "find" "grep" "head" "hostname" "id" "kill" "ln" "ls" "mkdir" "mknod"
"mktemp" "mount" "mv" "printf" "ps" "pwd" "readlink" "rm" "rmdir" "mktemp" "mount" "mv" "printf" "ps" "pwd" "readlink" "rm" "rmdir"
"sed" "sh" "sleep" "sort" "stat" "tail" "tar" "test" "touch" "tr" "sed" "sh" "sleep" "sort" "stat" "switch_root" "tail" "tar" "test" "touch" "tr"
"true" "umount" "uname" "uniq" "wc" "which" "whoami" "xargs" "true" "umount" "uname" "uniq" "wc" "which" "whoami" "xargs"
) )
for applet in "${busybox_applets[@]}"; do for applet in "${busybox_applets[@]}"; do
add_symlink "/usr/bin/$applet" busybox add_symlink "/usr/bin/$applet" busybox
done done
elif [[ -f "/work/output/busybox-s390x-native" ]]; then
# Manually add switch_root symlink (critical for root filesystem switching)
add_symlink "/usr/bin/switch_root" busybox
elif [[ -f "/work/boot/busybox-s390x-native" ]]; then
echo "Using s390x busybox binary" echo "Using s390x busybox binary"
add_file "/work/output/busybox-s390x-native" "/bin/busybox" 755 add_file "/work/boot/busybox-s390x-native" "/usr/bin/busybox" 755
# Create symlinks for busybox applets (using a known list since we can't execute cross-arch binary) # Create symlinks for busybox applets (using a known list since we can't execute cross-arch binary)
local busybox_applets=( local busybox_applets=(
@ -33,13 +38,16 @@ build() {
"date" "dd" "df" "dirname" "dmesg" "du" "echo" "env" "expr" "false" "date" "dd" "df" "dirname" "dmesg" "du" "echo" "env" "expr" "false"
"find" "grep" "head" "hostname" "id" "kill" "ln" "ls" "mkdir" "mknod" "find" "grep" "head" "hostname" "id" "kill" "ln" "ls" "mkdir" "mknod"
"mktemp" "mount" "mv" "printf" "ps" "pwd" "readlink" "rm" "rmdir" "mktemp" "mount" "mv" "printf" "ps" "pwd" "readlink" "rm" "rmdir"
"sed" "sh" "sleep" "sort" "stat" "tail" "tar" "test" "touch" "tr" "sed" "sh" "sleep" "sort" "stat" "switch_root" "tail" "tar" "test" "touch" "tr"
"true" "umount" "uname" "uniq" "wc" "which" "whoami" "xargs" "true" "umount" "uname" "uniq" "wc" "which" "whoami" "xargs"
) )
for applet in "${busybox_applets[@]}"; do for applet in "${busybox_applets[@]}"; do
add_symlink "/usr/bin/$applet" busybox add_symlink "/usr/bin/$applet" busybox
done done
# Manually add switch_root symlink (critical for root filesystem switching)
add_symlink "/usr/bin/switch_root" busybox
else else
echo "Warning: s390x busybox not found, using system busybox (may cause architecture mismatch)" echo "Warning: s390x busybox not found, using system busybox (may cause architecture mismatch)"
# Try to find busybox in various locations # Try to find busybox in various locations
@ -71,7 +79,8 @@ build() {
fi fi
# Check for additional utilities (may not be available in cross-compile environment) # Check for additional utilities (may not be available in cross-compile environment)
for binary in blkid mount umount switch_root; do # IMPORTANT: Skip mount/umount as they should come from busybox to avoid arch mismatch
for binary in blkid switch_root; do
if type -P "$binary" >/dev/null 2>&1; then if type -P "$binary" >/dev/null 2>&1; then
echo "Adding $binary" echo "Adding $binary"
add_binary "$binary" add_binary "$binary"
@ -80,10 +89,45 @@ build() {
fi fi
done done
# Ensure switch_root symlink exists (critical for root filesystem switching)
echo "Ensuring switch_root symlink..."
add_symlink "/usr/bin/switch_root" busybox
# Always add init files # Always add init files
echo "Adding init files..." echo "Adding init files..."
add_file "/usr/lib/initcpio/init_functions" "/init_functions" # Check both lib and lib64 locations for init files
add_file "/usr/lib/initcpio/init" "/init" 755 if [[ -f /usr/lib/initcpio/init_functions ]]; then
add_file "/usr/lib/initcpio/init_functions" "/init_functions" 644
elif [[ -f /usr/lib64/initcpio/init_functions ]]; then
add_file "/usr/lib64/initcpio/init_functions" "/init_functions" 644
else
echo "ERROR: init_functions not found in /usr/lib/initcpio or /usr/lib64/initcpio"
return 1
fi
# Use standard Arch init but patch the switch_root call
echo "Patching standard init script for s390x..."
# Copy the standard init and patch it
if [[ -f /usr/lib/initcpio/init ]]; then
cp /usr/lib/initcpio/init /tmp/s390x_init
elif [[ -f /usr/lib64/initcpio/init ]]; then
cp /usr/lib64/initcpio/init /tmp/s390x_init
else
echo "ERROR: Standard init not found"
return 1
fi
# Patch the switch_root line to use busybox
sed -i 's|/usr/bin/switch_root|/usr/bin/busybox switch_root|g' /tmp/s390x_init
# Add debug break when udevadm fails - use a more aggressive replacement
sed -i 's|udevadm settle|echo ":: udevadm not available, dropping to shell"; /bin/sh|g' /tmp/s390x_init
# Add the patched init script to the initramfs
add_file "/tmp/s390x_init" "/init" 755
echo "✓ Standard Arch init patched for s390x (switch_root -> busybox switch_root)"
echo "=== S390X BASE HOOK COMPLETED ==="
} }
help() { help() {

View file

@ -1,20 +0,0 @@
# Arch Linux s390x Build Scripts
The project focuses on a **single proven approach**: using modified Arch Linux mkinitcpio with s390x support.
### Core Build Workflow (7 scripts)
1. `install-toolchain-fedora-kernel.sh` - Install s390x cross-compilation toolchain via Fedora container
2. `build-kernel-container.sh` - Build Linux kernel in Fedora container
3. `build-mkinitcpio-container.sh` - Build container with upgraded meson for mkinitcpio ⭐
4. `build-initramfs-final.sh` - **MAIN METHOD**: Build initramfs using modified mkinitcpio ⭐
5. `prepare-boot.sh` - Prepare boot directory with kernel, initramfs, and IPL files
6. `test-qemu.sh` - Test the built system with QEMU s390x emulation
7. `setup-path.sh` - Add toolchain wrappers to PATH (used by build-all.sh)
## Modified mkinitcpio Implementation ⭐
**Key Features**:
- s390x-specific configuration (`mkinitcpio-s390x.conf`)
- Works with Fedora containers using upgraded meson (1.8.1)
- Proper s390x module support (DASD, QETH, virtio devices)
- Solves cross-compilation header issues that plagued busybox approaches

View file

@ -1,145 +0,0 @@
#!/bin/bash
# Unified build script for Arch Linux s390x port
# Handles sudo session and builds kernel + initramfs
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
# Project paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
echo -e "${BLUE}=== Arch Linux s390x Build System ===${NC}"
echo
# Function to check if sudo session is active
check_sudo_session() {
if sudo -n true 2>/dev/null; then
return 0
else
return 1
fi
}
# Setup sudo session if not already active
if ! check_sudo_session; then
echo -e "${YELLOW}Setting up sudo session...${NC}"
sudo -v || exit 1
# Keep sudo session alive in background
(
while true; do
sudo -n true
sleep 50
kill -0 "$$" 2>/dev/null || exit
done
) &
SUDO_PID=$!
# Ensure background process is killed on exit
trap "kill $SUDO_PID 2>/dev/null" EXIT
echo -e "${GREEN}✓ Sudo session established${NC}"
else
echo -e "${GREEN}✓ Sudo session already active${NC}"
fi
# Setup toolchain path
echo -e "${YELLOW}Setting up toolchain path...${NC}"
source "$PROJECT_ROOT/scripts/setup-path.sh"
# Parse arguments
BUILD_KERNEL=true
BUILD_INITRAMFS=true
TEST_QEMU=false
while [[ $# -gt 0 ]]; do
case $1 in
--kernel-only)
BUILD_INITRAMFS=false
shift
;;
--initramfs-only)
BUILD_KERNEL=false
shift
;;
--test)
TEST_QEMU=true
shift
;;
--all)
BUILD_KERNEL=true
BUILD_INITRAMFS=true
TEST_QEMU=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--kernel-only|--initramfs-only|--test|--all]"
exit 1
;;
esac
done
# Build kernel
if [ "$BUILD_KERNEL" = true ]; then
echo
echo -e "${BLUE}=== Building Kernel ===${NC}"
"$PROJECT_ROOT/scripts/build-kernel-container.sh"
fi
# Build busybox if it doesn't exist
if [ "$BUILD_INITRAMFS" = true ]; then
if [ ! -f "$PROJECT_ROOT/output/busybox-s390x-static" ] && [ ! -f "$PROJECT_ROOT/output/busybox-s390x-native" ]; then
echo
echo -e "${BLUE}=== Building s390x Busybox ===${NC}"
# Check if busybox build script exists
if [ -f "$PROJECT_ROOT/scripts/build-busybox-s390x.sh" ]; then
# Run busybox build in container
echo -e "${YELLOW}Building s390x busybox binary...${NC}"
sudo podman run --rm \
-v "$PROJECT_ROOT:/work" \
-v "$PROJECT_ROOT/output:/output" \
-w /work \
s390x-archlinux-dev \
/work/scripts/build-busybox-s390x.sh
else
echo -e "${RED}ERROR: build-busybox-s390x.sh not found${NC}"
exit 1
fi
else
echo -e "${GREEN}✓ s390x busybox already exists${NC}"
fi
fi
# Build initramfs
if [ "$BUILD_INITRAMFS" = true ]; then
echo
echo -e "${BLUE}=== Building Initramfs ===${NC}"
"$PROJECT_ROOT/scripts/build-initramfs-final.sh"
fi
# Prepare boot files
if [ "$BUILD_KERNEL" = true ] || [ "$BUILD_INITRAMFS" = true ]; then
echo
echo -e "${BLUE}=== Preparing Boot Files ===${NC}"
"$PROJECT_ROOT/scripts/prepare-boot.sh"
fi
# Test with QEMU
if [ "$TEST_QEMU" = true ]; then
echo
echo -e "${BLUE}=== Testing with QEMU ===${NC}"
"$PROJECT_ROOT/scripts/test-qemu.sh"
fi
echo
echo -e "${GREEN}=== Build Complete ===${NC}"
echo -e "Output files in: ${PROJECT_ROOT}/output/"
ls -la "$PROJECT_ROOT/output/"

View file

@ -1,141 +0,0 @@
#!/bin/bash
# Build s390x Busybox Binary
# This script builds a static busybox binary for s390x architecture to fix
# the architecture mismatch issue in the initramfs.
set -e
BUILD_DIR="/tmp/busybox-build"
OUTPUT_DIR="/output"
BUSYBOX_VERSION="1.35.0"
echo "Building s390x Busybox binary..."
# Install build dependencies
dnf install -y \
gcc-s390x-linux-gnu \
binutils-s390x-linux-gnu \
kernel-headers \
glibc-headers \
glibc-devel \
musl-devel \
make \
wget \
tar
# Create build directory
mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR"
# Download and extract busybox
if [ ! -f "busybox-${BUSYBOX_VERSION}.tar.bz2" ]; then
wget "https://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2"
fi
tar -xjf "busybox-${BUSYBOX_VERSION}.tar.bz2"
cd "busybox-${BUSYBOX_VERSION}/"
# Set cross-compilation environment
export ARCH=s390
export CROSS_COMPILE=s390x-linux-gnu-
export CC=s390x-linux-gnu-gcc
export AR=s390x-linux-gnu-ar
export STRIP=s390x-linux-gnu-strip
# Configure with minimal static build
make defconfig
# Create custom config for static linking and minimal size
cat >> .config << 'EOF'
CONFIG_STATIC=y
CONFIG_FEATURE_HAVE_RPC=n
CONFIG_SELINUX=n
CONFIG_FEATURE_SYSTEMD=n
CONFIG_PAM=n
CONFIG_FEATURE_UTMP=n
CONFIG_FEATURE_WTMP=n
CONFIG_LOCALE_SUPPORT=n
CONFIG_UNICODE_SUPPORT=n
CONFIG_FEATURE_EDITING=n
CONFIG_FEATURE_TAB_COMPLETION=n
EOF
# Disable problematic options that might use byteswap.h
sed -i 's/CONFIG_FEATURE_HAVE_RPC=y/CONFIG_FEATURE_HAVE_RPC=n/' .config
sed -i 's/CONFIG_LOCALE_SUPPORT=y/CONFIG_LOCALE_SUPPORT=n/' .config
# Create minimal byteswap.h (always create to ensure compatibility)
echo "Creating minimal byteswap.h for cross-compilation..."
mkdir -p include
# Create byteswap.h that uses system stdint.h
cat > include/byteswap.h << 'BYTESWAP_EOF'
#ifndef _BYTESWAP_H
#define _BYTESWAP_H
#include <stdint.h>
#if defined(__GNUC__)
#define bswap_16(x) __builtin_bswap16(x)
#define bswap_32(x) __builtin_bswap32(x)
#define bswap_64(x) __builtin_bswap64(x)
#else
static inline uint16_t bswap_16(uint16_t x) {
return (x >> 8) | (x << 8);
}
static inline uint32_t bswap_32(uint32_t x) {
return ((x >> 24) & 0xff) | ((x << 8) & 0xff0000) |
((x >> 8) & 0xff00) | ((x << 24) & 0xff000000);
}
static inline uint64_t bswap_64(uint64_t x) {
return bswap_32(x >> 32) | ((uint64_t)bswap_32(x) << 32);
}
#endif
#endif /* _BYTESWAP_H */
BYTESWAP_EOF
# Remove any conflicting stdint.h from busybox source
if [ -f include/stdint.h ]; then
echo "Removing busybox's conflicting stdint.h"
rm -f include/stdint.h
fi
# Let busybox find its own headers
echo "Building busybox with minimal configuration..."
make clean || true
# Try building with the cross compiler's sysroot
SYSROOT=$(s390x-linux-gnu-gcc -print-sysroot)
echo "Using sysroot: $SYSROOT"
# Build with proper include path order - system headers first
make \
CFLAGS="--sysroot=$SYSROOT -I$(pwd)/include" \
LDFLAGS="-static" \
CONFIG_STATIC=y \
HOSTCC=gcc \
HOSTCFLAGS="" \
-j$(nproc) 2>&1 | tee build.log
# Verify the binary was built and is correct architecture
if [ -f busybox ]; then
echo "Verifying busybox binary:"
file busybox
ls -la busybox
# Copy to output directory with both naming conventions
cp busybox "$OUTPUT_DIR/busybox-s390x-static"
chmod +x "$OUTPUT_DIR/busybox-s390x-static"
# Also create a native version link for compatibility
ln -sf busybox-s390x-static "$OUTPUT_DIR/busybox-s390x-native"
echo "✅ s390x busybox binary built successfully!"
echo "Size: $(du -h busybox | cut -f1)"
echo "Architecture: $(file busybox | grep -o 'ELF.*')"
else
echo "❌ Build failed - no busybox binary found"
echo "Build log:"
tail -20 build.log
exit 1
fi

55
scripts/build-busybox-zvm.sh Executable file
View file

@ -0,0 +1,55 @@
#!/bin/bash
# Build static busybox on z/VM s390x RHEL system
set -e
echo "Building static busybox on native s390x..."
# Install build dependencies
sudo dnf install -y gcc make wget tar bzip2 glibc-static
# Extract busybox
tar -xjf busybox-1.35.0.tar.bz2
cd busybox-1.35.0
# Configure for static build
make defconfig
# Enable static linking in config
cat >> .config << 'EOF'
CONFIG_STATIC=y
CONFIG_FEATURE_HAVE_RPC=n
CONFIG_SELINUX=n
CONFIG_FEATURE_SYSTEMD=n
CONFIG_PAM=n
CONFIG_FEATURE_UTMP=n
CONFIG_FEATURE_WTMP=n
CONFIG_LOCALE_SUPPORT=n
CONFIG_UNICODE_SUPPORT=n
EOF
# Disable problematic options
sed -i 's/CONFIG_FEATURE_HAVE_RPC=y/CONFIG_FEATURE_HAVE_RPC=n/' .config
sed -i 's/CONFIG_LOCALE_SUPPORT=y/CONFIG_LOCALE_SUPPORT=n/' .config
# Build static busybox
echo "Building with static linking..."
make CONFIG_STATIC=y LDFLAGS="-static" -j$(nproc)
# Verify the binary
if [ -f busybox ]; then
echo "✅ Busybox built successfully!"
echo "File info:"
file busybox
echo "Size: $(du -h busybox | cut -f1)"
echo "Static linking check:"
ldd busybox 2>&1 | head -1
# Copy to home directory for easy transfer
cp busybox ~/busybox-s390x-static
chmod +x ~/busybox-s390x-static
echo "✅ Copied to ~/busybox-s390x-static"
else
echo "❌ Build failed!"
exit 1
fi

View file

@ -162,16 +162,16 @@ cat /etc/mkinitcpio-s390x.conf
echo "s390x busybox will be handled by the patched mkinitcpio base hook..." echo "s390x busybox will be handled by the patched mkinitcpio base hook..."
# Ensure busybox binary is available for the base hook # Ensure busybox binary is available for the base hook
if [ -f "/work/output/busybox-s390x-static" ]; then if [ -f "/work/boot/busybox-s390x-static" ]; then
echo "✓ Found s390x static busybox at /work/output/busybox-s390x-static" echo "✓ Found s390x static busybox at /work/boot/busybox-s390x-static"
ls -la /work/output/busybox-s390x-static ls -la /work/boot/busybox-s390x-static
elif [ -f "/work/output/busybox-s390x-native" ]; then elif [ -f "/work/boot/busybox-s390x-native" ]; then
echo "✓ Found s390x native busybox at /work/output/busybox-s390x-native" echo "✓ Found s390x native busybox at /work/boot/busybox-s390x-native"
ls -la /work/output/busybox-s390x-native ls -la /work/boot/busybox-s390x-native
else else
echo "ERROR: No s390x busybox binary found in /work/output/" echo "ERROR: No s390x busybox binary found in /work/boot/"
echo "Available files in /work/output:" echo "Available files in /work/boot:"
ls -la /work/output/ ls -la /work/boot/
exit 1 exit 1
fi fi
@ -191,49 +191,43 @@ if [ -f "$INITRAMFS_OUTPUT" ]; then
ls -la "$INITRAMFS_OUTPUT" ls -la "$INITRAMFS_OUTPUT"
echo "Initramfs size: $(du -h "$INITRAMFS_OUTPUT" | cut -f1)" echo "Initramfs size: $(du -h "$INITRAMFS_OUTPUT" | cut -f1)"
# Analyze the generated initramfs # Analyze the generated initramfs using lsinitcpio
echo "" echo ""
echo "Analyzing generated initramfs..." echo "Analyzing generated initramfs..."
echo "Checking for critical files:" echo "Checking for critical files:"
# Extract and check for init # Use lsinitcpio to list contents (it handles concatenated CPIO properly)
mkdir -p /tmp/initramfs-check if command -v lsinitcpio >/dev/null 2>&1; then
cd /tmp/initramfs-check echo ""
zcat "$INITRAMFS_OUTPUT" | cpio -id 2>/dev/null # Check for critical files
if lsinitcpio "$INITRAMFS_OUTPUT" | grep -q "^init$"; then
echo "✓ /init found"
else
echo "✗ /init missing!"
fi
if [ -f init ]; then if lsinitcpio "$INITRAMFS_OUTPUT" | grep -q "^init_functions$"; then
echo "✓ /init found" echo "✓ /init_functions found"
ls -la init else
echo "✗ /init_functions missing!"
fi
# Check for busybox
if lsinitcpio "$INITRAMFS_OUTPUT" | grep -E "bin/busybox$|usr/bin/busybox$" >/dev/null; then
echo "✓ busybox found in initramfs"
else
echo "✗ busybox missing from initramfs!"
fi
# Show first 20 files
echo ""
echo "First 20 files in initramfs:"
lsinitcpio "$INITRAMFS_OUTPUT" | head -20
else else
echo "✗ /init missing!" echo "Note: lsinitcpio not available for detailed analysis"
echo "Initramfs was created successfully but contents cannot be verified"
fi fi
if [ -f init_functions ]; then
echo "✓ /init_functions found"
else
echo "✗ /init_functions missing!"
fi
# Check for busybox and verify architecture
if [ -f bin/busybox ]; then
echo "✓ busybox found at /bin/busybox"
file bin/busybox | grep -q "s390" && echo "✓ Verified s390x architecture in initramfs" || echo "⚠ Architecture may be incorrect"
elif [ -f usr/bin/busybox ]; then
echo "✓ busybox found at /usr/bin/busybox"
file usr/bin/busybox | grep -q "s390" && echo "✓ Verified s390x architecture in initramfs" || echo "⚠ Architecture may be incorrect"
else
echo "✗ busybox missing from initramfs!"
fi
# List first 20 files
echo ""
echo "First 20 files in initramfs:"
find . -type f | head -20
# Cleanup
cd /
rm -rf /tmp/initramfs-check
echo "" echo ""
echo "✓ Success!" echo "✓ Success!"
else else
@ -258,6 +252,13 @@ sudo podman run --rm \
# Clean up copied source # Clean up copied source
rm -rf "$PROJECT_ROOT/mkinitcpio-source" rm -rf "$PROJECT_ROOT/mkinitcpio-source"
# Fix permissions on output files (they were created as root in container)
if [ -f "$OUTPUT_DIR/$INITRAMFS_NAME" ]; then
echo -e "${YELLOW}Fixing file permissions...${NC}"
sudo chown $(id -u):$(id -g) "$OUTPUT_DIR/$INITRAMFS_NAME"
chmod 644 "$OUTPUT_DIR/$INITRAMFS_NAME"
fi
# Check result # Check result
if [ -f "$OUTPUT_DIR/$INITRAMFS_NAME" ]; then if [ -f "$OUTPUT_DIR/$INITRAMFS_NAME" ]; then
SIZE=$(du -h "$OUTPUT_DIR/$INITRAMFS_NAME" | cut -f1) SIZE=$(du -h "$OUTPUT_DIR/$INITRAMFS_NAME" | cut -f1)

View file

@ -16,8 +16,8 @@ qemu-system-s390x \
-machine s390-ccw-virtio \ -machine s390-ccw-virtio \
-cpu max \ -cpu max \
-m 2G \ -m 2G \
-kernel "output/vmlinuz-6.6.10-s390x" \ -kernel "boot/vmlinuz-linux" \
-initrd "output/initramfs-6.6.10-s390x.img" \ -initrd "boot/initramfs-linux.img" \
-append "console=ttyS0 rdinit=/init" \ -append "console=ttyS0 rdinit=/init" \
-nographic \ -nographic \
-device virtio-net-ccw,netdev=net0 \ -device virtio-net-ccw,netdev=net0 \

View file

@ -1,4 +0,0 @@
#!/bin/bash
# Add toolchain wrappers to PATH
export PATH="$PWD/toolchain-wrappers:$PATH"
echo "s390x toolchain wrappers added to PATH"

174
scripts/test-qemu-rootfs.sh Executable file
View file

@ -0,0 +1,174 @@
#!/bin/bash
# Test s390x Arch Linux with a root filesystem instead of just initramfs
# Get script directory and project root
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
echo "🚀 Starting Arch Linux s390x - Root Filesystem Test"
echo "This will boot with initramfs then switch to a root filesystem"
echo "Press Ctrl-A X to exit"
echo ""
cd "$PROJECT_ROOT"
# Create a minimal root filesystem if it doesn't exist
ROOTFS_IMG="boot/rootfs-s390x.img"
# Force recreation of root filesystem to get updated init script
echo "Creating minimal root filesystem (forcing recreation)..."
rm -f "$ROOTFS_IMG"
# Create 100MB root filesystem image
dd if=/dev/zero of="$ROOTFS_IMG" bs=1M count=100
# Format as ext4
mkfs.ext4 -F "$ROOTFS_IMG"
# Mount and populate
mkdir -p /tmp/rootfs-mount
sudo mount -o loop "$ROOTFS_IMG" /tmp/rootfs-mount
# Create basic directory structure
sudo mkdir -p /tmp/rootfs-mount/{bin,sbin,etc,proc,sys,dev,tmp,var,usr/{bin,sbin},lib,lib64}
# Copy busybox as the main shell and utilities
sudo cp boot/busybox-s390x-static /tmp/rootfs-mount/bin/busybox
# Create busybox symlinks for basic utilities
sudo chroot /tmp/rootfs-mount /bin/busybox --install -s
# Pre-create TTY devices to avoid errors
sudo mknod /tmp/rootfs-mount/dev/console c 5 1 2>/dev/null || true
sudo mknod /tmp/rootfs-mount/dev/tty c 5 0 2>/dev/null || true
sudo mknod /tmp/rootfs-mount/dev/tty1 c 4 1 2>/dev/null || true
sudo mknod /tmp/rootfs-mount/dev/tty2 c 4 2 2>/dev/null || true
sudo mknod /tmp/rootfs-mount/dev/tty3 c 4 3 2>/dev/null || true
sudo mknod /tmp/rootfs-mount/dev/tty4 c 4 4 2>/dev/null || true
# Create basic /etc/passwd
sudo tee /tmp/rootfs-mount/etc/passwd > /dev/null << 'EOF'
root:x:0:0:root:/root:/bin/sh
EOF
# Create basic /etc/group
sudo tee /tmp/rootfs-mount/etc/group > /dev/null << 'EOF'
root:x:0:
EOF
# Create /etc/os-release to identify as Arch Linux
sudo tee /tmp/rootfs-mount/etc/os-release > /dev/null << 'EOF'
NAME="Arch Linux"
PRETTY_NAME="Arch Linux"
ID=arch
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://archlinux.org/"
DOCUMENTATION_URL="https://wiki.archlinux.org/"
SUPPORT_URL="https://bbs.archlinux.org/"
BUG_REPORT_URL="https://bugs.archlinux.org/"
PRIVACY_POLICY_URL="https://terms.archlinux.org/docs/privacy-policy/"
LOGO=archlinux-logo
EOF
# Create /etc/arch-release (traditional Arch identifier)
sudo tee /tmp/rootfs-mount/etc/arch-release > /dev/null << 'EOF'
Arch Linux s390x \r (\l)
EOF
# Create /etc/hostname
sudo tee /tmp/rootfs-mount/etc/hostname > /dev/null << 'EOF'
archlinux-s390x
EOF
# Create basic /etc/hosts
sudo tee /tmp/rootfs-mount/etc/hosts > /dev/null << 'EOF'
127.0.0.1 localhost
::1 localhost
127.0.1.1 archlinux-s390x.localdomain archlinux-s390x
EOF
# Create basic init script for the root filesystem
sudo tee /tmp/rootfs-mount/sbin/init > /dev/null << 'EOF'
#!/bin/sh
echo "🎉 Welcome to Arch Linux s390x Root Filesystem!"
echo "This is running from a real root filesystem, not just initramfs."
echo ""
# Mount essential filesystems
mount -t proc proc /proc 2>/dev/null || true
mount -t sysfs sysfs /sys 2>/dev/null || true
mount -t devtmpfs devtmpfs /dev 2>/dev/null || true
# Create TTY devices that busybox init expects
mknod /dev/tty1 c 4 1 2>/dev/null || true
mknod /dev/tty2 c 4 2 2>/dev/null || true
mknod /dev/tty3 c 4 3 2>/dev/null || true
mknod /dev/tty4 c 4 4 2>/dev/null || true
mknod /dev/console c 5 1 2>/dev/null || true
echo "=== ARCH LINUX VERIFICATION ==="
echo "Distribution info:"
if [ -f /etc/os-release ]; then
cat /etc/os-release
else
echo "No /etc/os-release found"
fi
echo ""
if [ -f /etc/arch-release ]; then
echo "Arch release file:"
cat /etc/arch-release
else
echo "No /etc/arch-release found"
fi
echo ""
echo "Hostname: $(cat /etc/hostname 2>/dev/null || echo 'Not set')"
echo "Architecture: $(uname -m)"
echo "Kernel: $(uname -r)"
echo ""
echo "Root filesystem contents:"
ls -la /
echo ""
echo "Available TTY devices:"
ls -la /dev/tty* 2>/dev/null || echo "No TTY devices found"
echo ""
echo "Available commands:"
echo " ls, cat, mount, umount, ps, top, free, df, etc."
echo " Type 'busybox' to see all available applets"
echo ""
echo "To verify this is Arch Linux, check:"
echo " cat /etc/os-release"
echo " cat /etc/arch-release"
echo " uname -a"
echo ""
# Start a shell
exec /bin/sh
EOF
sudo chmod +x /tmp/rootfs-mount/sbin/init
sudo umount /tmp/rootfs-mount
rmdir /tmp/rootfs-mount
echo "✅ Root filesystem created at $ROOTFS_IMG"
# Boot with root filesystem
qemu-system-s390x \
-machine s390-ccw-virtio \
-cpu max \
-m 2G \
-kernel "boot/vmlinuz-linux" \
-initrd "boot/initramfs-linux.img" \
-append "console=ttyS0 root=/dev/vda rw init=/sbin/init" \
-drive file="$ROOTFS_IMG",format=raw,if=none,id=rootdisk \
-device virtio-blk-ccw,drive=rootdisk \
-nographic \
-device virtio-net-ccw,netdev=net0 \
-netdev user,id=net0

View file

@ -1,106 +0,0 @@
#!/bin/bash
# Test s390x kernel and initramfs with QEMU
set -e
# Configuration
OUTPUT_DIR="output"
KERNEL_VERSION="${KERNEL_VERSION:-6.6.10}"
QEMU_MEM="${QEMU_MEM:-2G}"
QEMU_CPU="${QEMU_CPU:-max}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
echo -e "${GREEN}=== Testing s390x build with QEMU ===${NC}"
# Check for qemu-system-s390x
if ! command -v qemu-system-s390x &> /dev/null; then
echo -e "${RED}Error: qemu-system-s390x not found${NC}"
echo "Install with:"
echo " Arch: sudo pacman -S qemu-system-s390x"
echo " Ubuntu/Debian: sudo apt-get install qemu-system-s390x"
echo " Fedora: sudo dnf install qemu-system-s390x"
exit 1
fi
# Check if boot directory is prepared
if [ -f "boot/vmlinuz-linux" ] && [ -f "boot/initramfs-linux.img" ]; then
echo -e "${GREEN}Using prepared boot directory${NC}"
KERNEL="boot/vmlinuz-linux"
INITRAMFS="boot/initramfs-linux.img"
else
# Find kernel image
KERNEL=""
if [ -f "$OUTPUT_DIR/vmlinuz-${KERNEL_VERSION}-s390x" ]; then
KERNEL="$OUTPUT_DIR/vmlinuz-${KERNEL_VERSION}-s390x"
elif [ -f "$OUTPUT_DIR/bzImage" ]; then
KERNEL="$OUTPUT_DIR/bzImage"
else
echo -e "${RED}Error: No kernel found. Run 'make kernel' first${NC}"
exit 1
fi
# Find initramfs
INITRAMFS=""
for img in "$OUTPUT_DIR/initramfs-${KERNEL_VERSION}-s390x.img" \
"$OUTPUT_DIR/initramfs-${KERNEL_VERSION}-s390x-manual.img" \
"$OUTPUT_DIR/initramfs.img"; do
if [ -f "$img" ]; then
INITRAMFS="$img"
break
fi
done
if [ -z "$INITRAMFS" ]; then
echo -e "${RED}Error: No initramfs found. Run 'make initramfs' first${NC}"
exit 1
fi
fi
echo -e "${GREEN}Using:${NC}"
echo " Kernel: $KERNEL"
echo " Initramfs: $INITRAMFS"
echo " Memory: $QEMU_MEM"
echo " CPU: $QEMU_CPU"
# Create script to run QEMU
cat > run-qemu-s390x.sh << EOF
#!/bin/bash
# Auto-generated QEMU run script
echo "Starting QEMU s390x emulation..."
echo "Press Ctrl-A X to exit"
echo ""
qemu-system-s390x \\
-machine s390-ccw-virtio \\
-cpu $QEMU_CPU \\
-m $QEMU_MEM \\
-kernel "$KERNEL" \\
-initrd "$INITRAMFS" \\
-append "root=/dev/ram0 console=ttyS0 init=/init" \\
-nographic \\
-device virtio-net-ccw,netdev=net0 \\
-netdev user,id=net0 \\
-device virtio-blk-ccw,drive=drive0 \\
-drive file=/dev/zero,if=none,id=drive0,format=raw,readonly=on
EOF
chmod +x run-qemu-s390x.sh
# Option to run directly
echo ""
echo -e "${YELLOW}QEMU run script created: ./run-qemu-s390x.sh${NC}"
echo ""
read -p "Run QEMU now? (y/N) " -n 1 -r
echo ""
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${YELLOW}Starting QEMU (press Ctrl-A X to exit)...${NC}"
./run-qemu-s390x.sh
else
echo -e "${GREEN}Run './run-qemu-s390x.sh' to start QEMU${NC}"
fi

View file

@ -1,18 +0,0 @@
#!/bin/bash
# Wrapper to use s390x toolchain from Podman
# If no arguments, run interactive shell
if [ $# -eq 0 ]; then
sudo podman run --rm -it \
-v "$PWD:/workspace" \
-v "$HOME/.cache:/root/.cache" \
s390x-toolchain \
bash
else
# Run command
sudo podman run --rm \
-v "$PWD:/workspace" \
-v "$HOME/.cache:/root/.cache" \
s390x-toolchain \
"$@"
fi