diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..b8b79b8 --- /dev/null +++ b/.env.example @@ -0,0 +1,23 @@ +# z/VM Configuration for Arch Linux s390x Build +# Copy this file to .env and fill in your values +# Add the entire .env file content as ZVM_CONFIG secret in GitHub Actions + +# z/VM Connection Details +ZVM_HOST=192.0.0.0 +ZVM_USER=linux1 +ZVM_PORT=22 + +# SSH Key Configuration +# The SSH private key content (multiline) +ZVM_SSH_KEY="-----BEGIN OPENSSH PRIVATE KEY----- +... (your full SSH private key content here) ... +-----END OPENSSH PRIVATE KEY-----" + +# Build Configuration +BUILD_TIMEOUT_MINUTES=30 +SYSTEMD_BUILD_DIR="/home/linux1/systemd-build" +SYSTEMD_OUTPUT_DIR="/home/linux1/systemd-minimal" + +# Connection Settings +SSH_CONNECT_TIMEOUT=10 +SSH_STRICT_HOST_KEY_CHECKING=no \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 18cbccd..482a5fd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,9 +37,9 @@ jobs: echo "❌ ERROR: Static busybox not found!" echo "" echo "To build a release, you must first:" - echo "1. SSH into z/VM: ssh -i zvm.pem -o StrictHostKeyChecking=no linux1@148.100.77.9" + echo "1. SSH into z/VM: ssh -i zvm.pem -o StrictHostKeyChecking=no \$ZVM_USER@\$ZVM_HOST" echo "2. Run the build script: ./scripts/build-busybox-zvm.sh" - echo "3. Transfer the busybox binary: scp -i zvm.pem linux1@148.100.77.9:~/busybox-s390x-static boot/" + echo "3. Transfer the busybox binary: scp -i zvm.pem \$ZVM_USER@\$ZVM_HOST:~/busybox-s390x-static boot/" echo "4. Commit the busybox binary to the repository" echo "" echo "The busybox MUST be built natively on s390x hardware for proper static linking." @@ -49,10 +49,46 @@ jobs: ls -la boot/busybox-s390x-static fi + - name: Setup z/VM environment + run: | + # Load z/VM configuration from secret + echo "${{ secrets.ZVM_CONFIG }}" > .env.temp + source .env.temp + rm .env.temp + + # Validate required variables + if [ -z "$ZVM_HOST" ] || [ -z "$ZVM_USER" ] || [ -z "$ZVM_SSH_KEY" ]; then + echo "Error: Missing required z/VM configuration" + echo "ZVM_CONFIG secret must contain: ZVM_HOST, ZVM_USER, ZVM_SSH_KEY" + exit 1 + fi + + # Setup SSH + mkdir -p ~/.ssh + echo "$ZVM_SSH_KEY" > zvm.pem + chmod 600 zvm.pem + ssh-keyscan -H $ZVM_HOST >> ~/.ssh/known_hosts + + # Export for later steps + echo "ZVM_HOST=$ZVM_HOST" >> $GITHUB_ENV + echo "ZVM_USER=$ZVM_USER" >> $GITHUB_ENV + echo "ZVM_PORT=${ZVM_PORT:-22}" >> $GITHUB_ENV + echo "SSH_CONNECT_TIMEOUT=${SSH_CONNECT_TIMEOUT:-10}" >> $GITHUB_ENV + + - name: Test z/VM connectivity + run: | + ssh -i zvm.pem -o ConnectTimeout=$SSH_CONNECT_TIMEOUT $ZVM_USER@$ZVM_HOST "echo 'z/VM connection successful'" + - name: Build complete system run: | echo "Building s390x kernel and creating initramfs..." make all + + - name: Build systemd on z/VM + run: | + echo "Building systemd natively on z/VM..." + make systemd-zvm + timeout-minutes: 30 - name: Prepare release artifacts run: | @@ -88,10 +124,23 @@ jobs: # Copy busybox binary cp boot/busybox-s390x-static release-artifacts/ + # Copy systemd artifacts if available + if [ -d "output/systemd-root" ]; then + echo "✅ Systemd found, including in release" + tar -czf release-artifacts/systemd-s390x.tar.gz -C output/systemd-root . + cp output/systemd-minimal-s390x.tar.gz release-artifacts/ 2>/dev/null || true + else + echo "⚠️ Systemd not found, release will be kernel + initramfs only" + fi + # 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) + SYSTEMD_SIZE="" + if [ -f "release-artifacts/systemd-s390x.tar.gz" ]; then + SYSTEMD_SIZE=$(du -h release-artifacts/systemd-s390x.tar.gz | cut -f1) + fi # Create build info file cat > release-artifacts/BUILD_INFO.txt << EOF @@ -105,14 +154,21 @@ jobs: Component Sizes: - Kernel: $KERNEL_SIZE - Initramfs: $INITRAMFS_SIZE - - Busybox: $BUSYBOX_SIZE + - Busybox: $BUSYBOX_SIZE$(if [ -n "$SYSTEMD_SIZE" ]; then echo " + - Systemd: $SYSTEMD_SIZE"; fi) Build Method: - - Kernel: Cross-compiled in Fedora container + - Kernel: Cross-compiled in Fedora container with CONFIG_UNIX and CONFIG_KMOD - Busybox: Statically compiled on z/VM RHEL 9.6 - - Initramfs: Generated with modified mkinitcpio + - Initramfs: Generated with modified mkinitcpio for s390x$(if [ -n "$SYSTEMD_SIZE" ]; then echo " + - Systemd: Natively compiled on IBM z/VM with mount/udevadm utilities"; fi) - Status: Fully functional - boots to emergency shell + Status: $(if [ -n "$SYSTEMD_SIZE" ]; then echo "Fully functional - boots with systemd to 'Welcome to Arch Linux!'"; else echo "Fully functional - boots to emergency shell"; fi) + + Boot Targets Available: + - make test: Initramfs-only system + - make test-rootfs: Root filesystem with busybox init$(if [ -n "$SYSTEMD_SIZE" ]; then echo " + - make test-systemd: Full systemd boot with modern init system"; fi) EOF # Create checksums @@ -143,6 +199,8 @@ jobs: release-artifacts/vmlinuz-linux-s390x release-artifacts/initramfs-linux-s390x.img release-artifacts/busybox-s390x-static + release-artifacts/systemd-s390x.tar.gz + release-artifacts/systemd-minimal-s390x.tar.gz release-artifacts/BUILD_INFO.txt release-artifacts/SHA256SUMS env: diff --git a/.gitignore b/.gitignore index cafcc74..7439d03 100644 --- a/.gitignore +++ b/.gitignore @@ -35,7 +35,6 @@ temp-initramfs/ tmp-initramfs/ build-kernel/ -# Temporary build scripts build-final-initramfs.sh # Linked mkinitcpio repository @@ -72,8 +71,9 @@ VERSION CLAUDE.md PROJECT_SUMMARY.md -# Sec +# Security *.pem +.env # Test artifacts boot/rootfs-s390x.img diff --git a/Makefile b/Makefile index ad0a80b..7902122 100644 --- a/Makefile +++ b/Makefile @@ -7,14 +7,13 @@ BOOT_DIR := boot # Output files KERNEL := $(OUTPUT_DIR)/vmlinuz-6.6.10-s390x-arch 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 test-systemd clean help container systemd-zvm systemd +.PHONY: all kernel busybox initramfs boot test test-rootfs test-systemd clean help container systemd # Default target -all: boot +all: boot systemd # Build Arch Linux kernel with patches $(KERNEL): | $(OUTPUT_DIR) @@ -29,7 +28,7 @@ build-busybox: | $(BOOT_DIR) 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 "1. SSH into z/VM: ssh -i zvm.pem -o StrictHostKeyChecking=no \$$ZVM_USER@\$$ZVM_HOST"; \ 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 ""; \ @@ -39,30 +38,13 @@ build-busybox: | $(BOOT_DIR) 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) +# Check busybox binary (must be static build from z/VM) +busybox: build-busybox + @echo "✅ Busybox check complete" # Build initramfs (depends on busybox) -$(INITRAMFS): $(BUSYBOX) | $(OUTPUT_DIR) +$(INITRAMFS): busybox | $(OUTPUT_DIR) @echo "Building initramfs with mkinitcpio..." @./scripts/build-initramfs-final.sh @@ -127,8 +109,13 @@ systemd: systemd-zvm # Clean build artifacts clean: @echo "Cleaning build artifacts..." - @rm -rf $(OUTPUT_DIR)/* - @rm -f $(BOOT_KERNEL) $(BOOT_INITRAMFS) + @if [ -d "$(OUTPUT_DIR)" ]; then \ + if ! rm -rf $(OUTPUT_DIR)/* 2>/dev/null; then \ + echo "Permission denied. Trying with sudo..."; \ + sudo rm -rf $(OUTPUT_DIR)/*; \ + fi; \ + fi + @rm -f $(BOOT_KERNEL) $(BOOT_INITRAMFS) 2>/dev/null || true @echo "Clean complete." # Show help @@ -138,18 +125,16 @@ help: @echo "Usage: make [target]" @echo "" @echo "Targets:" - @echo " all - Build everything (kernel + initramfs + boot)" + @echo " all - Build everything (kernel + initramfs + systemd)" @echo " kernel - Build Arch Linux kernel with patches for s390x" - @echo " build-busybox - Check for static s390x busybox (must be built on z/VM)" - @echo " busybox - Check s390x busybox binary exists" + @echo " busybox - Check for static s390x busybox (must be built on z/VM)" @echo " initramfs - Build initramfs only (requires busybox)" @echo " boot - Prepare boot directory" @echo " container - Build development container" + @echo " systemd - Build minimal systemd on z/VM (native s390x)" @echo " test - Test with QEMU s390x emulation (initramfs only)" @echo " test-rootfs - Test with QEMU and minimal root filesystem" @echo " test-systemd - Test with QEMU and systemd as init" - @echo " systemd - Build minimal systemd on z/VM (native s390x)" - @echo " systemd-zvm - Build minimal systemd on z/VM (native s390x)" @echo " clean - Remove build artifacts" @echo " help - Show this help message" @echo "" diff --git a/README.md b/README.md index f81f97b..a685376 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ make test-systemd ## What's Working -- **Arch Linux Kernel**: Linux 6.6.10 with Arch patches cross-compiled for IBM mainframes (5.8MB) +- **Arch Linux Kernel**: Linux 6.6.10 with Arch patches and CONFIG_UNIX/CONFIG_KMOD support (5.8MB) - **Initramfs**: Complete 5.9MB initramfs with s390x busybox - **Boot Process**: Successful boot to root filesystem with busybox shell - **Root Filesystem**: **COMPLETE!** 150MB ext4 root filesystem with Arch Linux identification -- **Systemd**: **NEW!** 42MB minimal systemd built natively on IBM z/VM -- **Modern Init**: Systemd components ready for enterprise mainframe deployment +- **Systemd**: **WORKING!** 42MB minimal systemd with mount/udevadm utilities - boots to "Welcome to Arch Linux!" +- **Modern Init**: Full systemd boot reaching Multi-User and Graphical targets - **QEMU Testing**: Fully functional in s390x emulation - **Ready for Hardware**: IPL configuration for real mainframes @@ -34,21 +34,21 @@ make test-systemd ### Core System Components | Component | Status | Details | |-----------|--------|---------| -| Kernel | ✅ Working | 5.8MB bootable s390x kernel with Arch patches (6.6.10) | +| Kernel | ✅ Working | 5.8MB bootable s390x kernel with CONFIG_UNIX/CONFIG_KMOD (6.6.10) | | Initramfs | ✅ Working | 5.9MB with native s390x binaries | -| Boot Process | ✅ Working | IPL → kernel → initramfs → root filesystem | +| Boot Process | ✅ Working | IPL → kernel → initramfs → root filesystem → systemd | | Root Filesystem | ✅ **COMPLETE** | 150MB ext4 with working busybox switch_root | -| Systemd | ✅ **BUILT** | 42MB minimal systemd with native s390x compilation | +| Systemd | ✅ **WORKING** | 42MB minimal systemd with mount/udevadm - reaches graphical target | | mkinitcpio | ✅ Fixed | Adapted for s390x architecture | ### Userspace Components | Component | Status | Details | |-----------|--------|---------| -| Init System | ✅ **DUAL** | Busybox init + systemd available | +| Init System | ✅ **COMPLETE** | Busybox in initramfs → switch_root → systemd | | Shell | 🟨 Minimal | Busybox sh (not bash) | -| Core Utilities | 🟨 Minimal | Busybox applets only | +| Core Utilities | ✅ **Enhanced** | Busybox applets + mount/udevadm/kmod utilities | | Package Manager | ❌ TODO | Pacman needs porting | -| Systemd | ✅ **BUILT** | Native s390x compilation complete | +| Systemd Runtime | ✅ **WORKING** | Full systemd boot with journal, udev, and basic services | | Bash | ❌ TODO | Needs s390x build | | GNU Coreutils | ❌ TODO | Replace busybox applets | @@ -67,13 +67,13 @@ s390x-archlinux-dev # All-in-one development container ``` ### Build Targets: -- `make all` - Build complete system (kernel + initramfs) +- `make all` - Build complete system (kernel + initramfs + systemd) - `make kernel` - Cross-compile Arch Linux kernel for s390x - `make initramfs` - Generate initramfs with mkinitcpio -- `make systemd` - Build systemd natively on z/VM +- `make systemd` - Build systemd natively on z/VM (requires .env configuration) - `make test` - Test initramfs-only system with QEMU - `make test-rootfs` - Test with root filesystem switching -- `make test-systemd` - Test with systemd as init +- `make test-systemd` - Test with systemd as init (full modern boot) - `make clean` - Clean build artifacts ### Key Scripts: @@ -86,6 +86,31 @@ s390x-archlinux-dev # All-in-one development container - `scripts/test-qemu-systemd.sh` - Test with systemd as init - `scripts/build-busybox-zvm.sh` - Build static busybox on z/VM +## z/VM Configuration + +For building systemd and busybox natively on s390x hardware, you'll need access to an IBM z/VM system: + +1. **Copy the example configuration**: + ```bash + cp .env.example .env + ``` + +2. **Edit `.env` with your z/VM details**: + ```bash + ZVM_HOST=your.zvm.host + ZVM_USER=your_username + ZVM_SSH_KEY="-----BEGIN OPENSSH PRIVATE KEY----- + ... your SSH private key content ... + -----END OPENSSH PRIVATE KEY-----" + ``` + +3. **Build systemd**: + ```bash + make systemd + ``` + +The scripts will automatically load the `.env` configuration when needed. + ## Testing ```bash @@ -99,13 +124,17 @@ make test # Test root filesystem switching make test-rootfs + +# Test full systemd boot (requires systemd build) +make test-systemd ``` -**Expected**: +**Expected Results**: - `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 +- `make test-systemd` - Full systemd boot reaching "Welcome to Arch Linux!" and graphical target -[![asciicast](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9.svg)](https://asciinema.org/a/QVmnI1tyJjjFp4cps93qiTbM9) +[![asciicast](https://asciinema.org/a/u49jp0Bg7YoGtlGyTh6C9RJ7P.svg)](https://asciinema.org/a/u49jp0Bg7YoGtlGyTh6C9RJ7P) ## Output Files @@ -115,7 +144,8 @@ After building: - `boot/rootfs-s390x.img` - Root filesystem image (created by test-rootfs) - `boot/generic.ins` - IPL configuration for real hardware - `boot/arch.prm` - Kernel parameters -- `boot/busybox-s390x-static` - Static busybox binary built on z/VM +- `boot/busybox-s390x-static` - Static busybox binary built on z/VM (used by mkinitcpio) +- `output/systemd-root/` - Complete systemd installation for root filesystem ## Technical Details @@ -127,23 +157,19 @@ After building: ### Key Fixes Applied: 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 +2. **Static busybox in initramfs** - Built natively on z/VM for early boot operations 3. **Architecture compatibility** - Fixed base hook to exclude x86_64 binaries -4. **Init script patching** - Modified standard Arch init to use `busybox switch_root` +4. **switch_root support** - Enables transition from initramfs to systemd on root filesystem +5. **Kernel configuration** - Added CONFIG_UNIX and CONFIG_KMOD for systemd support -## System Boot Success +## System Boot Sequence -The system successfully boots from initramfs to root filesystem: +The complete boot process follows this sequence: -``` -[ 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 - -/ # uname -a -Linux arch 6.6.10 #14 SMP Mon Jun 2 14:59:34 UTC 2025 s390x GNU/Linux -``` +1. **IPL (Initial Program Load)** - IBM mainframe boot process +2. **Kernel loads** - Linux 6.6.10 s390x kernel with Arch patches +3. **Initramfs unpacked** - Contains busybox and init script +4. **Early boot** - Busybox provides utilities for mounting and setup +5. **Root filesystem mounted** - `/dev/vda` mounted to `/new_root` +6. **switch_root** - Busybox `switch_root` transitions to real root filesystem +7. **Systemd starts** - `/usr/lib/systemd/systemd` becomes PID 1 diff --git a/arch-kernel/config-s390x b/arch-kernel/config-s390x index 8009487..cf19f66 100644 --- a/arch-kernel/config-s390x +++ b/arch-kernel/config-s390x @@ -137,6 +137,8 @@ CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EPOLL=y CONFIG_NET=y +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=y CONFIG_SYSFS=y CONFIG_PROC_FS=y CONFIG_FHANDLE=y @@ -145,6 +147,7 @@ CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_SHA256=y CONFIG_DMIID=y CONFIG_AUTOFS_FS=y +CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y CONFIG_TMPFS_XATTR=y CONFIG_SECCOMP=y @@ -189,6 +192,7 @@ CONFIG_INITRAMFS_ROOT_GID=0 # Module support CONFIG_MODULES=y +CONFIG_KMOD=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y diff --git a/boot/boot-info.txt b/boot/boot-info.txt index e9c51cb..b168ad9 100644 --- a/boot/boot-info.txt +++ b/boot/boot-info.txt @@ -2,7 +2,7 @@ Arch Linux s390x Boot Directory ============================== Kernel Version: 6.6.10 -Build Date: Mon Jun 2 09:28:58 PM CEST 2025 +Build Date: Thu Jun 5 11:58:54 AM CEST 2025 Architecture: s390x Files: diff --git a/boot/busybox-s390x-native b/boot/busybox-s390x-native new file mode 120000 index 0000000..60fd7cc --- /dev/null +++ b/boot/busybox-s390x-native @@ -0,0 +1 @@ +busybox-s390x-static \ No newline at end of file diff --git a/boot/vmlinuz-linux b/boot/vmlinuz-linux index 5591e38..1acbf4a 100755 Binary files a/boot/vmlinuz-linux and b/boot/vmlinuz-linux differ diff --git a/patches/mkinitcpio-mount-run.patch b/patches/mkinitcpio-mount-run.patch new file mode 100644 index 0000000..23baa5f --- /dev/null +++ b/patches/mkinitcpio-mount-run.patch @@ -0,0 +1,30 @@ +--- a/usr/lib/initcpio/init_functions ++++ b/usr/lib/initcpio/init_functions +@@ -1,4 +1,14 @@ + #!/usr/bin/ash ++ ++# Pre-mount /run for s390x systems without CONFIG_TMPFS ++premount_run_ramfs() { ++ if [ ! -d /new_root/run ]; then ++ mkdir -p /new_root/run ++ fi ++ # Use ramfs instead of tmpfs due to kernel limitations ++ mount -t ramfs -o mode=755,nodev,nosuid ramfs /new_root/run ++} ++ + # This file contains common functions used in init and in hooks + + msg() { +--- a/usr/lib/initcpio/init ++++ b/usr/lib/initcpio/init +@@ -84,6 +84,10 @@ if [ -n "$earlymodules$MODULES" ]; then + fi + fi + ++# Pre-mount /run using ramfs for s390x systems without CONFIG_TMPFS ++msg ":: Pre-mounting /run with ramfs for systemd compatibility" ++premount_run_ramfs ++ + msg ":: running hook [udev]" + run_hookfunctions 'run_earlyhook' 'early hook' $EARLYHOOKS + \ No newline at end of file diff --git a/scripts/build-systemd-zvm.sh b/scripts/build-systemd-zvm.sh index 8dd7838..af8c54e 100755 --- a/scripts/build-systemd-zvm.sh +++ b/scripts/build-systemd-zvm.sh @@ -37,9 +37,11 @@ sudo dnf install -y \ libblkid-devel \ libuuid-devel \ libseccomp-devel \ + util-linux \ + kmod \ + kmod-devel \ libacl-devel \ libattr-devel \ - kmod-devel \ elfutils-devel \ dbus-devel \ python3-jinja2 \ @@ -145,11 +147,30 @@ rm -rf "$OUTPUT_DIR/usr/share/factory" rm -rf "$OUTPUT_DIR/usr/share/bash-completion" rm -rf "$OUTPUT_DIR/usr/share/zsh" +# Copy essential system utilities that systemd needs +echo -e "${YELLOW}Copying essential system utilities...${NC}" +mkdir -p "$OUTPUT_DIR/usr/bin" "$OUTPUT_DIR/usr/sbin" + +# Copy mount utilities from util-linux +cp /usr/bin/mount "$OUTPUT_DIR/usr/bin/" 2>/dev/null || echo "Warning: mount not found" +cp /usr/bin/umount "$OUTPUT_DIR/usr/bin/" 2>/dev/null || echo "Warning: umount not found" + +# Copy udev utilities +cp /usr/bin/udevadm "$OUTPUT_DIR/usr/bin/" 2>/dev/null || echo "Warning: udevadm not found" + +# Copy kmod utilities +cp /usr/bin/kmod "$OUTPUT_DIR/usr/bin/" 2>/dev/null || echo "Warning: kmod not found" +for util in modprobe insmod rmmod lsmod modinfo depmod; do + cp "/usr/sbin/$util" "$OUTPUT_DIR/usr/sbin/" 2>/dev/null || \ + cp "/usr/bin/$util" "$OUTPUT_DIR/usr/bin/" 2>/dev/null || \ + echo "Warning: $util not found" +done + # Keep only essential binaries cd "$OUTPUT_DIR/usr/bin" for binary in *; do case "$binary" in - systemctl|journalctl|systemd-*) ;; + systemctl|journalctl|systemd-*|mount|umount|udevadm|kmod) ;; *) rm -f "$binary" ;; esac done @@ -158,21 +179,43 @@ done echo -e "${YELLOW}Copying runtime libraries...${NC}" mkdir -p "$OUTPUT_DIR/lib" "$OUTPUT_DIR/lib64" -# Copy dynamic linker and essential libraries -cp -L /lib64/ld-linux-s390x.so.2 "$OUTPUT_DIR/lib/" 2>/dev/null || true -cp -L /lib64/ld64.so.1 "$OUTPUT_DIR/lib/" 2>/dev/null || true +# Copy dynamic linker to /lib - force copy and verify +echo "Copying dynamic linker..." +cp -L /lib64/ld64.so.1 "$OUTPUT_DIR/lib/ld64.so.1" || cp -L /lib/ld64.so.1 "$OUTPUT_DIR/lib/ld64.so.1" || echo "Warning: ld64.so.1 not found" +cp -L /lib64/ld-linux-s390x.so.2 "$OUTPUT_DIR/lib/ld-linux-s390x.so.2" 2>/dev/null || echo "Warning: ld-linux-s390x.so.2 not found" +chmod +x "$OUTPUT_DIR/lib/"ld* 2>/dev/null || true +ls -la "$OUTPUT_DIR/lib/"ld* || echo "No dynamic linker found" -# Copy essential glibc and other system libraries +# Get all library dependencies for systemd and core binaries +echo "Analyzing library dependencies..." +SYSTEMD_DEPS=$(ldd "$OUTPUT_DIR/usr/lib/systemd/systemd" | awk '/=>/ {print $3}' | sort -u) +JOURNALD_DEPS=$(ldd "$OUTPUT_DIR/usr/lib/systemd/systemd-journald" | awk '/=>/ {print $3}' | sort -u) +UDEVD_DEPS=$(ldd "$OUTPUT_DIR/usr/lib/systemd/systemd-udevd" | awk '/=>/ {print $3}' | sort -u) +MOUNT_DEPS=$(ldd "$OUTPUT_DIR/usr/bin/mount" 2>/dev/null | awk '/=>/ {print $3}' | sort -u || true) +UDEVADM_DEPS=$(ldd "$OUTPUT_DIR/usr/bin/udevadm" 2>/dev/null | awk '/=>/ {print $3}' | sort -u || true) +KMOD_DEPS=$(ldd "$OUTPUT_DIR/usr/bin/kmod" 2>/dev/null | awk '/=>/ {print $3}' | sort -u || true) + +# Copy all discovered dependencies +echo "Copying system library dependencies..." +for dep in $SYSTEMD_DEPS $JOURNALD_DEPS $UDEVD_DEPS $MOUNT_DEPS $UDEVADM_DEPS $KMOD_DEPS; do + if [ -f "$dep" ]; then + cp -L "$dep" "$OUTPUT_DIR/lib64/" 2>/dev/null || true + echo "Copied: $(basename "$dep")" + fi +done + +# Also copy common libraries manually for completeness for lib in libc.so.6 libm.so.6 libpthread.so.0 libdl.so.2 librt.so.1 \ - libcrypt.so.1 libcap.so.2 libblkid.so.1 libuuid.so.1 \ + libcrypt.so.1 libcrypt.so.2 libcap.so.2 libblkid.so.1 libuuid.so.1 \ libmount.so.1 libseccomp.so.2 libacl.so.1 libattr.so.1 \ libkmod.so.2 libdw.so.1 libelf.so.1 libz.so.1 \ - libbz2.so.1 liblzma.so.5 libdbus-1.so.3; do + libbz2.so.1 liblzma.so.5 libdbus-1.so.3 libselinux.so.1 \ + libpcre2-8.so.0; do find /lib64 /usr/lib64 -name "$lib*" -exec cp -L {} "$OUTPUT_DIR/lib64/" \; 2>/dev/null || true done -# Create lib64 symlink -ln -sf lib "$OUTPUT_DIR/lib64" 2>/dev/null || true +# Also copy libraries to /lib for compatibility +cp "$OUTPUT_DIR/lib64/"* "$OUTPUT_DIR/lib/" 2>/dev/null || true # Create tarball for transfer cd "$OUTPUT_DIR" @@ -189,4 +232,4 @@ echo -e "${GREEN}Tarball size: $TARBALL_SIZE${NC}" echo -e "${GREEN}Tarball location: $HOME/systemd-minimal-s390x.tar.gz${NC}" echo "" echo "To transfer back to your local system:" -echo "scp -i zvm.pem linux1@148.100.77.9:~/systemd-minimal-s390x.tar.gz output/" \ No newline at end of file +echo "scp -i zvm.pem \$USER@\$(hostname -f):~/systemd-minimal-s390x.tar.gz output/" \ No newline at end of file diff --git a/scripts/deploy-and-build-systemd-zvm.sh b/scripts/deploy-and-build-systemd-zvm.sh index dfc7002..d1b9b73 100755 --- a/scripts/deploy-and-build-systemd-zvm.sh +++ b/scripts/deploy-and-build-systemd-zvm.sh @@ -9,9 +9,33 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' -# z/VM connection details -ZVM_HOST="linux1@148.100.77.9" -ZVM_KEY="zvm.pem" +# Load environment variables from .env file if available and variables not set +if [ -z "$ZVM_HOST" ] || [ -z "$ZVM_USER" ]; then + if [ -f ".env" ]; then + echo -e "${YELLOW}Loading z/VM configuration from .env file...${NC}" + set -a # Export all variables + source .env + set +a # Stop exporting + fi +fi + +# Check if required variables are now set +if [ -z "$ZVM_HOST" ] || [ -z "$ZVM_USER" ]; then + echo -e "${RED}Error: ZVM_HOST and ZVM_USER environment variables must be set${NC}" + echo "" + echo "Option 1: Create a .env file (recommended):" + echo " cp .env.example .env" + echo " # Edit .env with your z/VM details" + echo "" + echo "Option 2: Export variables manually:" + echo " export ZVM_HOST=your.zvm.host" + echo " export ZVM_USER=your_username" + echo " export ZVM_SSH_KEY='your-ssh-key-content'" + exit 1 +fi + +ZVM_CONNECTION="${ZVM_USER}@${ZVM_HOST}" +ZVM_KEY="${ZVM_KEY:-zvm.pem}" echo -e "${GREEN}=== Building systemd on z/VM RHEL 9.6 ===${NC}" @@ -21,18 +45,56 @@ if [ ! -f "$ZVM_KEY" ]; then exit 1 fi +# SSH options +SSH_OPTS="-i $ZVM_KEY -o StrictHostKeyChecking=${SSH_STRICT_HOST_KEY_CHECKING:-no} -o ConnectTimeout=${SSH_CONNECT_TIMEOUT:-10}" + # 1. Copy build script to z/VM echo -e "${YELLOW}1. Copying build script to z/VM...${NC}" -scp -i $ZVM_KEY -o StrictHostKeyChecking=no scripts/build-systemd-zvm.sh $ZVM_HOST:~/ +scp $SSH_OPTS scripts/build-systemd-zvm.sh $ZVM_CONNECTION:~/ # 2. Run the build script echo -e "${YELLOW}2. Running systemd build on z/VM (this may take 10-15 minutes)...${NC}" -ssh -i $ZVM_KEY -o StrictHostKeyChecking=no $ZVM_HOST "chmod +x ~/build-systemd-zvm.sh && ./build-systemd-zvm.sh" +ssh $SSH_OPTS $ZVM_CONNECTION "chmod +x ~/build-systemd-zvm.sh && ./build-systemd-zvm.sh" -# 3. Copy artifacts back +# 3. Copy artifacts back with retry mechanism echo -e "${YELLOW}3. Copying build artifacts back...${NC}" mkdir -p output -scp -i $ZVM_KEY -o StrictHostKeyChecking=no $ZVM_HOST:~/systemd-minimal-s390x.tar.gz output/ + +# Function to copy with retries +copy_with_retry() { + local max_retries=5 + local retry_count=0 + local success=0 + + while [ $retry_count -lt $max_retries ] && [ $success -eq 0 ]; do + if [ $retry_count -gt 0 ]; then + echo -e "${YELLOW}Retry $retry_count/$max_retries - waiting 10 seconds before retrying...${NC}" + sleep 10 + fi + + # Use timeout and compression options to handle stalls + if timeout 300 scp $SSH_OPTS -o ServerAliveInterval=15 -o ServerAliveCountMax=3 -C $ZVM_CONNECTION:~/systemd-minimal-s390x.tar.gz output/; then + success=1 + echo -e "${GREEN}✓ Transfer completed successfully${NC}" + else + retry_count=$((retry_count + 1)) + echo -e "${RED}Transfer failed or timed out${NC}" + + # Kill any stalled scp processes + pkill -f "scp.*systemd-minimal-s390x.tar.gz" 2>/dev/null || true + fi + done + + if [ $success -eq 0 ]; then + echo -e "${RED}Failed to transfer after $max_retries attempts${NC}" + echo -e "${YELLOW}You can manually copy the file with:${NC}" + echo "scp $SSH_OPTS $ZVM_CONNECTION:~/systemd-minimal-s390x.tar.gz output/" + exit 1 + fi +} + +# Perform the copy with retries +copy_with_retry # 4. Extract and organize echo -e "${YELLOW}4. Extracting systemd...${NC}" diff --git a/scripts/test-qemu-systemd.sh b/scripts/test-qemu-systemd.sh index cbde3dd..8f4a567 100755 --- a/scripts/test-qemu-systemd.sh +++ b/scripts/test-qemu-systemd.sh @@ -51,6 +51,8 @@ sudo cp -r output/systemd-root/* /tmp/rootfs-mount/ sudo mkdir -p /tmp/rootfs-mount/run/systemd sudo mkdir -p /tmp/rootfs-mount/var/log/journal sudo mkdir -p /tmp/rootfs-mount/etc/systemd/system +sudo mkdir -p /tmp/rootfs-mount/sys +sudo mkdir -p /tmp/rootfs-mount/proc # Create device nodes sudo mknod /tmp/rootfs-mount/dev/console c 5 1 2>/dev/null || true