diff --git a/.dockerignore b/.dockerignore index 346655e..12fec2d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,6 @@ linux_deb/ linux-bin/ work/ -work-alpine/ output/ .git/ ps5-linux-patches/ diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index beac7dd..33e4e9e 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -8,7 +8,7 @@ on: description: 'Distribution' default: 'ubuntu2604' type: choice - options: [all, ubuntu2604, arch, cachyos, alpine] + options: [all, ubuntu2604, arch, cachyos] workflow_call: inputs: distro: @@ -40,7 +40,7 @@ jobs: run: | INPUT="${{ inputs.distro || 'ubuntu2604' }}" if [ "$INPUT" = "all" ]; then - echo 'distros=["ubuntu2604","arch","cachyos","alpine"]' >> "$GITHUB_OUTPUT" + echo 'distros=["ubuntu2604","arch","cachyos"]' >> "$GITHUB_OUTPUT" else echo "distros=[\"$INPUT\"]" >> "$GITHUB_OUTPUT" fi @@ -59,7 +59,7 @@ jobs: distro: ${{ fromJson(needs.matrix.outputs.distros) }} env: - CCACHE_DIR: /home/opc/ccache + CACHE_DIR: /home/opc/ccache steps: - name: Checkout image builder @@ -176,7 +176,6 @@ jobs: echo "| Ubuntu 26.04 | [\`ps5-ubuntu2604.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-ubuntu2604.img.xz) |" echo "| Arch | [\`ps5-arch.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-arch.img.xz) |" echo "| CachyOS | [\`ps5-cachyos.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-cachyos.img.xz) |" - echo "| Alpine | [\`ps5-alpine.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-alpine.img.xz) |" echo "" echo "**SHA256 checksums:**" echo "\`\`\`" diff --git a/.github/workflows/test-uploads.yml b/.github/workflows/test-uploads.yml index 000c8fb..e4a43c9 100644 --- a/.github/workflows/test-uploads.yml +++ b/.github/workflows/test-uploads.yml @@ -10,7 +10,7 @@ jobs: distros: ${{ steps.set.outputs.distros }} steps: - id: set - run: echo 'distros=["ubuntu2604","arch","cachyos","alpine"]' >> "$GITHUB_OUTPUT" + run: echo 'distros=["ubuntu2604","arch","cachyos"]' >> "$GITHUB_OUTPUT" build: needs: matrix @@ -119,7 +119,6 @@ jobs: echo "| Ubuntu 26.04 | [\`ps5-ubuntu2604.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-ubuntu2604.img.xz) |" echo "| Arch | [\`ps5-arch.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-arch.img.xz) |" echo "| CachyOS | [\`ps5-cachyos.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-cachyos.img.xz) |" - echo "| Alpine | [\`ps5-alpine.img.xz\`](https://pub-561df4012f1a46fbbdf618d5cc5941f6.r2.dev/ps5-alpine.img.xz) |" echo "" echo "**SHA256 checksums:**" echo "\`\`\`" @@ -152,7 +151,7 @@ jobs: RCLONE_CONFIG_R2_ENDPOINT: ${{ secrets.R2_ENDPOINT }} RCLONE_CONFIG_R2_NO_CHECK_BUCKET: true run: | - for d in ubuntu2604 arch cachyos alpine; do + for d in ubuntu2604 arch cachyos; do rclone delete "r2:${{ secrets.R2_BUCKET }}/test-${d}.img.xz" -v || true done diff --git a/README.md b/README.md index 08e1bfd..b5d881b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # PS5 Linux Image Builder -Builds bootable Linux USB images for PlayStation 5 using Docker containers. Supports Ubuntu 26.04, Arch, CachyOS (Gamescope + Steam), and Alpine, individually or as a multi-distro image with kexec switching. +Builds bootable Linux USB images for PlayStation 5 using Docker containers. Supports Ubuntu 26.04, Arch, and CachyOS (Gamescope + Steam), individually or as a multi-distro image with kexec switching. ## Prerequisites @@ -27,7 +27,7 @@ OR OR -# Build a multi-distro image (ubuntu2604 + arch + alpine + cachyos) +# Build a multi-distro image (ubuntu2604 + arch + cachyos) ./build_image.sh --distro all ``` @@ -43,7 +43,7 @@ sudo dd if=output/ps5-ubuntu2604.img of=/dev/sdX bs=4M status=progress | Flag | Description | Default | |------|-------------|---------| -| `--distro` | `ubuntu2604`, `arch`, `cachyos`, `alpine`, or `all` | `ubuntu2604` | +| `--distro` | `ubuntu2604`, `arch`, `cachyos`, or `all` | `ubuntu2604` | | `--kernel` | Path to kernel source directory | auto-clone `v6.19.10` | | `--img-size` | Disk image size in MB | `12000` (`32000` for `all`) | | `--clean` | Remove all cached build artifacts and start fresh | off | @@ -66,7 +66,7 @@ Use `--clean` to wipe everything and rebuild from scratch. The build will also s PS5 Linux Image Builder ======================= Distro: all - (ubuntu2604 arch alpine cachyos) + (ubuntu2604 arch cachyos) Image size: 32000MB Kernel src: /path/to/work/linux @@ -91,19 +91,17 @@ All verbose output goes to `build.log`. The terminal shows a spinner with live p | Ubuntu 26.04 (Resolute) | GNOME | `.deb` | systemd | | Arch | Sway | `.pkg.tar.zst` | systemd | | CachyOS | Gamescope + Steam Big Picture (Arch + `[cachyos]` repo, no v3 migration in image build) | `.pkg.tar.zst` | systemd | -| Alpine (3.21) | GNOME | extracted from `.deb` | OpenRC | ## Multi-distro Image -`--distro all` builds a 32GB image with 5 partitions (one EFI boot partition plus four root filesystems): +`--distro all` builds a 32GB image with 4 partitions (one EFI boot partition plus three root filesystems): | Partition | Type | Label | Content | |-----------|------|-------|---------| | p1 | FAT32 | boot | Shared kernel, per-distro initrds, kexec scripts | | p2 | ext4 | ubuntu2604 | Ubuntu 26.04 rootfs | | p3 | ext4 | arch | Arch rootfs | -| p4 | ext4 | alpine | Alpine rootfs | -| p5 | ext4 | cachyos | CachyOS rootfs | +| p4 | ext4 | cachyos | CachyOS rootfs | The boot partition contains kexec scripts to switch between distros at runtime. Ubuntu 26.04 is the default boot target. @@ -139,12 +137,11 @@ distros/ ubuntu2604/ # Ubuntu 26.04 (Resolute) arch/ # Arch Linux cachyos/ # CachyOS repos + Gamescope/Steam - alpine/ # Alpine 3.21 shared/ # Kernel postinst hooks (single + multi) boot/ cmdline.txt # Kernel cmdline template (__DISTRO__ placeholder) vram.txt # VRAM allocation - kexec-{ubuntu2604,arch,alpine,cachyos}.sh + kexec-{ubuntu2604,arch,cachyos}.sh work/ # Build artifacts (auto-created) linux-bin/ # Compiled kernel packages output/ # Final .img files diff --git a/boot/kexec-alpine.sh b/boot/kexec-alpine.sh deleted file mode 100644 index 0de845f..0000000 --- a/boot/kexec-alpine.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Switch to Alpine Linux via kexec -set -e -BOOT=/boot/efi -kexec -l "$BOOT/bzImage" --initrd="$BOOT/initrd-alpine.img" --command-line="$(cat $BOOT/cmdline-alpine.txt)" -kexec -e diff --git a/build_image.sh b/build_image.sh index ac9fcfb..70961e6 100755 --- a/build_image.sh +++ b/build_image.sh @@ -11,13 +11,13 @@ IMG_SIZE=12000 KERNEL_ONLY=false PATCHES_REF="v1.1" -MULTI_DISTROS="ubuntu2604 arch alpine cachyos" +MULTI_DISTROS="ubuntu2604 arch cachyos" usage() { echo "Usage: $0 [--distro ] [--kernel ] [--img-size ] [--clean]" echo "" echo "Options:" - echo " --distro Distribution to build: ubuntu2604, arch, cachyos, alpine, all (default: ubuntu2604)" + echo " --distro Distribution to build: ubuntu2604, arch, cachyos, all (default: ubuntu2604)" echo " --kernel Path to kernel source directory (default: auto-clone to work/linux/)" echo " --img-size Disk image size in MB (default: 12000, 32000 for --distro all)" echo " --clean Remove all cached build artifacts and start from scratch" diff --git a/distros/alpine/grow-rootfs b/distros/alpine/grow-rootfs deleted file mode 100644 index 6fcb0db..0000000 --- a/distros/alpine/grow-rootfs +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -# Grows the root partition and filesystem to fill the disk. -# Runs once on first boot, then disables itself. -set -e - -ROOT_DEV=$(findmnt -no SOURCE /) -DISK=$(lsblk -ndo PKNAME "$ROOT_DEV") -PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition) - -growpart "/dev/$DISK" "$PART_NUM" || true -partprobe "/dev/$DISK" -resize2fs "$ROOT_DEV" || true - -rc-update del grow-rootfs default diff --git a/distros/alpine/grow-rootfs.openrc b/distros/alpine/grow-rootfs.openrc deleted file mode 100644 index 205e534..0000000 --- a/distros/alpine/grow-rootfs.openrc +++ /dev/null @@ -1,13 +0,0 @@ -#!/sbin/openrc-run - -description="Grow root filesystem to fill disk" - -depend() { - need localmount -} - -start() { - ebegin "Growing root filesystem" - /usr/local/sbin/grow-rootfs - eend $? -} diff --git a/distros/alpine/image.yaml b/distros/alpine/image.yaml deleted file mode 100644 index 1378a39..0000000 --- a/distros/alpine/image.yaml +++ /dev/null @@ -1,175 +0,0 @@ -image: - name: ps5-alpine - distribution: alpine - release: "3.21" - description: Alpine Linux with Weston - architecture: x86_64 - -source: - downloader: alpinelinux-http - url: https://dl-cdn.alpinelinux.org/alpine - skip_verification: true - -packages: - manager: apk - update: true - cleanup: true - - repositories: - - name: repositories - url: |- - https://dl-cdn.alpinelinux.org/alpine/v3.21/main - https://dl-cdn.alpinelinux.org/alpine/v3.21/community - - sets: - - packages: - # Wayland compositor + basics - - weston - - weston-shell-desktop - - weston-backend-drm - - weston-xwayland - - weston-terminal - - foot - - xwayland - - # Wayland support - - dbus - - eudev - - elogind - - polkit-elogind - - seatd - - # Audio / media - - pipewire - - wireplumber - - pipewire-pulse - - # Display / GPU - - mesa-gbm - - mesa-egl - - mesa-gl - - mesa-dri-gallium - - mesa-va-gallium - - mesa-vulkan-ati - - libinput - - xkeyboard-config - - # Networking - - networkmanager - - networkmanager-wifi - - wpa_supplicant - - linux-firmware - - linux-firmware-amdgpu - - xf86-video-amdgpu - - # System - - openrc - - openssh - - sudo - - shadow - - nano - - bash - - coreutils - - util-linux - - e2fsprogs - - e2fsprogs-extra - - cloud-utils-growpart - - mkinitfs - - kmod - - kexec-tools - - syslog-ng - - # Fonts - - font-ubuntu - - font-liberation - - font-dejavu - - fontconfig - action: install - -files: -- path: /etc/hostname - generator: hostname - -- path: /etc/hosts - generator: hosts - -- path: /etc/kernel/postinst.d/zz-update-boot - generator: copy - source: /tmp/build-staging/zz-update-boot - mode: "0755" - -- path: /etc/fstab - generator: copy - source: /tmp/build-staging/fstab - -- path: /usr/local/sbin/grow-rootfs - generator: copy - source: /tmp/build-staging/grow-rootfs - mode: "0755" - -- path: /etc/init.d/grow-rootfs - generator: copy - source: /tmp/build-staging/grow-rootfs.openrc - mode: "0755" - -actions: -- trigger: post-unpack - action: |- - #!/bin/sh - set -eux - # Retry up to 10 times on transient network errors - echo "retries = 10" >> /etc/apk/apk.conf 2>/dev/null || true - # dbus post-install chokes on an empty machine-id - rm -f /etc/machine-id - - -- trigger: post-packages - action: |- - #!/bin/sh - set -eux - fc-cache -f -v - - # SSH - sed -i 's/^#*PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config - sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config - rc-update add syslog-ng default - rc-update add udev sysinit - rc-update add udev-trigger sysinit - rc-update add udev-settle sysinit - rc-update add sshd default - rc-update add dbus default - rc-update add elogind default - rc-update add seatd default - rc-update add networkmanager default - -- trigger: post-files - action: |- - #!/bin/sh - set -eux - rc-update add grow-rootfs default - - # Create default user (ps5/ps5) in groups needed for Wayland/input - addgroup ps5 - adduser -D -s /bin/bash -G ps5 ps5 - echo "ps5:ps5" | chpasswd - addgroup ps5 wheel - addgroup ps5 video - addgroup ps5 input - addgroup ps5 seat - echo "%wheel ALL=(ALL:ALL) NOPASSWD: ALL" > /etc/sudoers.d/wheel - - # Auto-start weston on tty1 login - { - echo 'if [ "$(tty)" = "/dev/tty1" ] && [ -z "$WAYLAND_DISPLAY" ]; then' - echo ' export XDG_RUNTIME_DIR="/tmp/xdg-runtime-$(id -u)"' - echo ' mkdir -p "$XDG_RUNTIME_DIR"' - echo ' chmod 700 "$XDG_RUNTIME_DIR"' - echo ' exec weston --backend=drm-backend.so' - echo 'fi' - } >> /home/ps5/.bash_profile - chown -R ps5:ps5 /home/ps5 - - mkdir -p /boot/efi - -mappings: - architecture_map: alpinelinux diff --git a/docker/image-builder/entrypoint-multi.sh b/docker/image-builder/entrypoint-multi.sh index 156fb23..7922140 100644 --- a/docker/image-builder/entrypoint-multi.sh +++ b/docker/image-builder/entrypoint-multi.sh @@ -5,7 +5,7 @@ set -ex IMG_SIZE="${IMG_SIZE:-32000}" SKIP_CHROOT="${SKIP_CHROOT:-false}" -DISTROS="${DISTROS:-ubuntu2604 arch alpine cachyos}" +DISTROS="${DISTROS:-ubuntu2604 arch cachyos}" STAGING="/tmp/build-staging" EFI_LABEL="boot" IMG="/output/ps5-multi.img" @@ -42,10 +42,6 @@ for DISTRO in $DISTROS; do cp /repo/distros/${DISTRO}/grow-rootfs.service "$STAGING/" cp /kernel-debs/*.deb "$STAGING/debs/" ;; - alpine) - cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/" - cp /repo/distros/alpine/grow-rootfs.openrc "$STAGING/" - ;; arch) cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/" cp /repo/distros/arch/grow-rootfs.service "$STAGING/" @@ -87,75 +83,6 @@ for DISTRO in $DISTROS; do echo "$DISTRO" > "$CHROOT/etc/ps5-distro" fi - # --- Alpine kernel gap: no kernel installed via image.yaml --- - # This runs even with --skip-chroot because Alpine's rootfs never includes a kernel; - # we must always extract it from the .deb artifacts and generate an initrd. - if [ "$DISTRO" = "alpine" ]; then - echo "=== Alpine: installing kernel from .deb artifacts ===" - - # Extract modules + vmlinuz from the linux-image .deb - ALPINE_STAGING="/tmp/alpine-kernel-staging" - rm -rf "$ALPINE_STAGING" - mkdir -p "$ALPINE_STAGING" - for deb in /kernel-debs/linux-image-*.deb; do - [ -f "$deb" ] || continue - dpkg-deb -x "$deb" "$ALPINE_STAGING" - done - - # Identify kernel version from the extracted .deb before copying - KVER=$(ls -1 "$ALPINE_STAGING/lib/modules" 2>/dev/null | head -1) - - if [ -n "$KVER" ]; then - # Resolve the real modules path inside the chroot. - # Alpine may use usr-merge (/lib -> usr/lib), so we must follow - # symlinks to find the actual directory on disk. - if [ -L "$CHROOT/lib" ]; then - MODDIR="$CHROOT/usr/lib/modules" - else - MODDIR="$CHROOT/lib/modules" - fi - mkdir -p "$MODDIR" - # Remove any stale modules from a previous build - rm -rf "$MODDIR/$KVER" - cp -a "$ALPINE_STAGING/lib/modules/$KVER" "$MODDIR/" - mkdir -p "$CHROOT/boot" - cp "$ALPINE_STAGING/boot/vmlinuz-$KVER" "$CHROOT/boot/vmlinuz-$KVER" - echo ">> Alpine: modules copied to $MODDIR/$KVER" - ls -la "$MODDIR/" - fi - rm -rf "$ALPINE_STAGING" - - if [ -n "$KVER" ]; then - echo "=== Alpine: generating initrd ===" - chroot "$CHROOT" depmod -a "$KVER" 2>/dev/null || true - - # Bind-mount essentials and run mkinitfs inside the alpine chroot - mount --bind /dev "$CHROOT/dev" - mount --bind /proc "$CHROOT/proc" - mount --bind /sys "$CHROOT/sys" - chroot "$CHROOT" mkinitfs -k "$KVER" -o "/boot/initrd.img-$KVER" "$KVER" || true - umount "$CHROOT/sys" "$CHROOT/proc" "$CHROOT/dev" - - # Populate /boot/efi/ for boot partition assembly - mkdir -p "$CHROOT/boot/efi" - cp "$CHROOT/boot/vmlinuz-$KVER" "$CHROOT/boot/efi/bzImage" - # mkinitfs may output as initramfs- — find whatever was generated - if [ -f "$CHROOT/boot/initrd.img-$KVER" ]; then - cp "$CHROOT/boot/initrd.img-$KVER" "$CHROOT/boot/efi/initrd.img" - else - # mkinitfs default output: /boot/initramfs-vanilla or similar - INITRD=$(ls -1t "$CHROOT"/boot/initramfs-* "$CHROOT"/boot/initrd* 2>/dev/null | head -1) - if [ -n "$INITRD" ]; then - cp "$INITRD" "$CHROOT/boot/efi/initrd.img" - else - echo "WARNING: No initrd found for alpine after mkinitfs" - fi - fi - echo ">> Alpine: kernel $KVER staged to boot/efi/" - else - echo "WARNING: No kernel modules found in .deb for alpine, skipping initrd generation" - fi - fi done # ====================================================================== @@ -259,9 +186,6 @@ for DISTRO in $DISTROS; do cp "$EFIDIR/initrd.img" "/tmp/mnt_boot/initrd-${DISTRO}.img" elif [ -n "$KVER" ] && [ -f "$BOOTDIR/initrd.img-$KVER" ]; then cp "$BOOTDIR/initrd.img-$KVER" "/tmp/mnt_boot/initrd-${DISTRO}.img" - elif [ -f "$BOOTDIR/initramfs-vanilla" ]; then - # Alpine mkinitfs names its output initramfs-vanilla - cp "$BOOTDIR/initramfs-vanilla" "/tmp/mnt_boot/initrd-${DISTRO}.img" fi # Clean up /boot/efi contents from the rootfs (they're on the boot partition now) diff --git a/docker/image-builder/entrypoint.sh b/docker/image-builder/entrypoint.sh index a4054d6..7a78100 100755 --- a/docker/image-builder/entrypoint.sh +++ b/docker/image-builder/entrypoint.sh @@ -34,10 +34,6 @@ EOF cp /repo/distros/${DISTRO}/grow-rootfs.service "$STAGING/" cp /kernel-debs/*.deb "$STAGING/debs/" ;; - alpine) - cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/" - cp /repo/distros/alpine/grow-rootfs.openrc "$STAGING/" - ;; arch) cp /repo/distros/${DISTRO}/grow-rootfs "$STAGING/" cp /repo/distros/arch/grow-rootfs.service "$STAGING/" @@ -77,65 +73,6 @@ case "$DISTRO" in ;; esac -# --- Alpine kernel gap: no kernel installed via image.yaml --- -# Extract kernel from .deb, copy modules + bzImage, then chroot to run mkinitfs -if [ "$DISTRO" = "alpine" ]; then - echo "=== Alpine: installing kernel from .deb artifacts ===" - - ALPINE_STAGING="/tmp/alpine-kernel-staging" - rm -rf "$ALPINE_STAGING" - mkdir -p "$ALPINE_STAGING" - for deb in /kernel-debs/linux-image-*.deb; do - [ -f "$deb" ] || continue - dpkg-deb -x "$deb" "$ALPINE_STAGING" - done - - KVER=$(ls -1 "$ALPINE_STAGING/lib/modules" 2>/dev/null | head -1) - - if [ -n "$KVER" ]; then - # Resolve the real modules path (Alpine may use usr-merge: /lib -> usr/lib) - if [ -L "$CHROOT/lib" ]; then - MODDIR="$CHROOT/usr/lib/modules" - else - MODDIR="$CHROOT/lib/modules" - fi - mkdir -p "$MODDIR" - rm -rf "$MODDIR/$KVER" - cp -a "$ALPINE_STAGING/lib/modules/$KVER" "$MODDIR/" - mkdir -p "$CHROOT/boot" - cp "$ALPINE_STAGING/boot/vmlinuz-$KVER" "$CHROOT/boot/vmlinuz-$KVER" - echo ">> Alpine: modules copied to $MODDIR/$KVER" - fi - rm -rf "$ALPINE_STAGING" - - if [ -n "$KVER" ]; then - chroot "$CHROOT" depmod -a "$KVER" 2>/dev/null || true - - mount --bind /dev "$CHROOT/dev" - mount --bind /proc "$CHROOT/proc" - mount --bind /sys "$CHROOT/sys" - chroot "$CHROOT" mkinitfs -k "$KVER" -o "/boot/initrd.img-$KVER" "$KVER" || true - umount "$CHROOT/sys" "$CHROOT/proc" "$CHROOT/dev" - - # Populate /boot/efi/ for boot partition assembly - mkdir -p "$CHROOT/boot/efi" - cp "$CHROOT/boot/vmlinuz-$KVER" "$CHROOT/boot/efi/bzImage" - if [ -f "$CHROOT/boot/initrd.img-$KVER" ]; then - cp "$CHROOT/boot/initrd.img-$KVER" "$CHROOT/boot/efi/initrd.img" - else - INITRD=$(ls -1t "$CHROOT"/boot/initramfs-* "$CHROOT"/boot/initrd* 2>/dev/null | head -1) - if [ -n "$INITRD" ]; then - cp "$INITRD" "$CHROOT/boot/efi/initrd.img" - else - echo "WARNING: No initrd found for alpine after mkinitfs" - fi - fi - echo ">> Alpine: kernel $KVER staged to boot/efi/" - else - echo "WARNING: No kernel modules found in .deb for alpine" - fi -fi - # --- Create GPT disk image --- echo "=== Creating ${IMG_SIZE}MB disk image ===" TMPIMG="/build/ps5-${DISTRO}.img"