mirror of
https://github.com/ps5-linux/ps5-linux-image.git
synced 2026-07-16 01:50:40 +00:00
Merge pull request #4 from ps5-linux/feature/ci-integration
Feature/ci integration
This commit is contained in:
18
.github/workflows/dispatch.yml
vendored
Normal file
18
.github/workflows/dispatch.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Dispatch to CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
dispatch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Send repository_dispatch
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.DISPATCH_TOKEN }}
|
||||
repository: ps5-linux/ps5-linux-updates
|
||||
event-type: image-builder-updated
|
||||
client-payload: '{"sha": "${{ github.sha }}"}'
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,6 +1,9 @@
|
||||
cache/
|
||||
ccache/
|
||||
work/
|
||||
output/
|
||||
linux-bin/
|
||||
build.log
|
||||
|
||||
*.swp
|
||||
patches.diff
|
||||
|
||||
21
README.md
21
README.md
@@ -47,6 +47,8 @@ sudo dd if=output/ps5-ubuntu2604.img of=/dev/sdX bs=4M status=progress
|
||||
| `--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 |
|
||||
| `--kernel-only` | Build and package the kernel only, then exit | off |
|
||||
| `--patches-ref` | Branch, tag, or commit SHA for patches | `v1.0` |
|
||||
|
||||
## Caching
|
||||
|
||||
@@ -105,10 +107,27 @@ All verbose output goes to `build.log`. The terminal shows a spinner with live p
|
||||
|
||||
The boot partition contains kexec scripts to switch between distros at runtime. Ubuntu 26.04 is the default boot target.
|
||||
|
||||
## Building the Kernel Standalone
|
||||
|
||||
Use `--kernel-only` to compile the PS5 kernel and produce installable packages without building a full disk image.
|
||||
|
||||
```bash
|
||||
./build_image.sh --kernel-only # .deb (default)
|
||||
./build_image.sh --kernel-only --distro all # .deb + .pkg.tar.zst
|
||||
./build_image.sh --kernel-only --patches-ref main # fetch from specific branch/tag
|
||||
./build_image.sh --kernel-only --clean # wipe and rebuild from scratch
|
||||
```
|
||||
|
||||
Output packages are written to `linux-bin/`. Install on a running PS5 Linux system:
|
||||
|
||||
```bash
|
||||
sudo dpkg -i linux-bin/linux-ps5_*.deb
|
||||
```
|
||||
|
||||
## Directory Layout
|
||||
|
||||
```
|
||||
build_image.sh # Main build script
|
||||
build_image.sh # Image builder (also supports --kernel-only)
|
||||
docker/
|
||||
kernel-builder/ # Kernel compilation container
|
||||
kernel-builder-arch/ # Repackages .deb kernel as .pkg.tar.zst
|
||||
|
||||
179
build_image.sh
179
build_image.sh
@@ -8,6 +8,8 @@ DISTRO="ubuntu2604"
|
||||
KERNEL_SRC=""
|
||||
CLEAN=false
|
||||
IMG_SIZE=12000
|
||||
KERNEL_ONLY=false
|
||||
PATCHES_REF="v1.0"
|
||||
|
||||
MULTI_DISTROS="ubuntu2604 arch alpine cachyos"
|
||||
|
||||
@@ -19,15 +21,19 @@ usage() {
|
||||
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"
|
||||
echo " --kernel-only Build and package the kernel only, then exit"
|
||||
echo " --patches-ref Branch, tag, or commit SHA for patches (default: v1.0)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--distro) DISTRO="$2"; shift 2 ;;
|
||||
--kernel) KERNEL_SRC="$2"; shift 2 ;;
|
||||
--img-size) IMG_SIZE="$2"; shift 2 ;;
|
||||
--clean) CLEAN=true; shift ;;
|
||||
--distro) DISTRO="$2"; shift 2 ;;
|
||||
--kernel) KERNEL_SRC="$2"; shift 2 ;;
|
||||
--img-size) IMG_SIZE="$2"; shift 2 ;;
|
||||
--clean) CLEAN=true; shift ;;
|
||||
--kernel-only) KERNEL_ONLY=true; shift ;;
|
||||
--patches-ref) [ -n "$2" ] && PATCHES_REF="$2"; shift 2 ;;
|
||||
-h|--help) usage ;;
|
||||
*) echo "Unknown option: $1"; usage ;;
|
||||
esac
|
||||
@@ -37,9 +43,7 @@ LINUX_REPO="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
|
||||
LINUX_DEFAULT_DIR="$SCRIPT_DIR/work/linux"
|
||||
|
||||
PATCHES_REPO="https://github.com/ps5-linux/ps5-linux-patches.git"
|
||||
PATCHES_BRANCH="v1.0"
|
||||
PATCHES_DIR="$SCRIPT_DIR/work/ps5-linux-patches"
|
||||
PATCHES_CONFIG=".config"
|
||||
|
||||
if [ -z "$KERNEL_SRC" ]; then
|
||||
KERNEL_SRC="$LINUX_DEFAULT_DIR"
|
||||
@@ -49,14 +53,25 @@ KERNEL_OUT="$SCRIPT_DIR/linux-bin"
|
||||
OUTPUT_DIR="$SCRIPT_DIR/output"
|
||||
CHROOT_DIR="$SCRIPT_DIR/work/chroot"
|
||||
CACHE_DIR="$SCRIPT_DIR/work/cache"
|
||||
CCACHE_DIR="$SCRIPT_DIR/cache/ccache"
|
||||
CCACHE_DIR="${CCACHE_DIR:-$SCRIPT_DIR/ccache}"
|
||||
LOG_FILE="$SCRIPT_DIR/build.log"
|
||||
DOCKER_NAME="ps5-build-$$"
|
||||
|
||||
|
||||
|
||||
if [ "$DISTRO" = "all" ] && [ "$IMG_SIZE" = "12000" ]; then
|
||||
IMG_SIZE=32000
|
||||
fi
|
||||
|
||||
if [ -z "$FORMAT" ]; then
|
||||
case "$DISTRO" in arch) FORMAT="arch" ;; all) FORMAT="all" ;; *) FORMAT="deb" ;; esac
|
||||
fi
|
||||
|
||||
KERNEL_BUILDER_PLATFORM="linux/amd64"
|
||||
case "$(uname -m)" in
|
||||
aarch64|arm64) KERNEL_BUILDER_PLATFORM="linux/arm64" ;;
|
||||
esac
|
||||
|
||||
# --- Signal trap: clean up docker containers and background jobs on exit ---
|
||||
BUILD_PID=""
|
||||
|
||||
@@ -73,14 +88,11 @@ trap cleanup INT TERM
|
||||
# --- Clean ---
|
||||
if [ "$CLEAN" = true ]; then
|
||||
echo "Cleaning all build artifacts..."
|
||||
# Build artifacts contain root-owned files from Docker — use a container to remove them
|
||||
for dir in "$SCRIPT_DIR/work" "$KERNEL_OUT" "$SCRIPT_DIR/cache"; do
|
||||
if [ -d "$dir" ]; then
|
||||
docker run --rm --privileged -v "$dir":/clean alpine sh -c 'rm -rf /clean/*'
|
||||
rmdir "$dir" 2>/dev/null || true
|
||||
fi
|
||||
for dir in "$SCRIPT_DIR/work" "$KERNEL_OUT" "$SCRIPT_DIR/cache" "$OUTPUT_DIR"; do
|
||||
[ -d "$dir" ] && docker run --rm \
|
||||
-v "$(dirname "$dir")":/parent \
|
||||
alpine rm -rf "/parent/$(basename "$dir")"
|
||||
done
|
||||
rm -rf "$OUTPUT_DIR"
|
||||
echo "Done."
|
||||
echo ""
|
||||
fi
|
||||
@@ -89,17 +101,13 @@ fi
|
||||
SKIP_KERNEL=false
|
||||
SKIP_CHROOT=false
|
||||
|
||||
# Kernel packages already built?
|
||||
if [ "$DISTRO" = "arch" ] || [ "$DISTRO" = "cachyos" ]; then
|
||||
ls "$KERNEL_OUT"/*.pkg.tar.zst 1>/dev/null 2>&1 && SKIP_KERNEL=true
|
||||
elif [ "$DISTRO" = "all" ]; then
|
||||
ls "$KERNEL_OUT"/*.deb 1>/dev/null 2>&1 && \
|
||||
ls "$KERNEL_OUT"/*.pkg.tar.zst 1>/dev/null 2>&1 && SKIP_KERNEL=true
|
||||
else
|
||||
ls "$KERNEL_OUT"/*.deb 1>/dev/null 2>&1 && SKIP_KERNEL=true
|
||||
fi
|
||||
case "$FORMAT" in
|
||||
arch) ls "$KERNEL_OUT"/*.pkg.tar.zst 1>/dev/null 2>&1 && SKIP_KERNEL=true ;;
|
||||
all) ls "$KERNEL_OUT"/*.deb 1>/dev/null 2>&1 && \
|
||||
ls "$KERNEL_OUT"/*.pkg.tar.zst 1>/dev/null 2>&1 && SKIP_KERNEL=true ;;
|
||||
*) ls "$KERNEL_OUT"/*.deb 1>/dev/null 2>&1 && SKIP_KERNEL=true ;;
|
||||
esac
|
||||
|
||||
# Chroot already populated?
|
||||
if [ "$DISTRO" = "all" ]; then
|
||||
SKIP_CHROOT=true
|
||||
for d in $MULTI_DISTROS; do
|
||||
@@ -109,21 +117,18 @@ else
|
||||
[ -d "$CHROOT_DIR/bin" ] && SKIP_CHROOT=true
|
||||
fi
|
||||
|
||||
if [ "$DISTRO" = "arch" ] || [ "$DISTRO" = "cachyos" ]; then
|
||||
PKG_EXT="pkg.tar.zst"
|
||||
else
|
||||
PKG_EXT="deb"
|
||||
fi
|
||||
|
||||
# --- Build plan summary ---
|
||||
echo ""
|
||||
echo "PS5 Linux Image Builder"
|
||||
echo "======================="
|
||||
echo " Distro: $DISTRO"
|
||||
if [ "$DISTRO" = "all" ]; then
|
||||
echo " ($MULTI_DISTROS)"
|
||||
if [ "$KERNEL_ONLY" = true ]; then
|
||||
echo " Mode: kernel only"
|
||||
echo " Format: $FORMAT"
|
||||
else
|
||||
echo " Distro: $DISTRO"
|
||||
[ "$DISTRO" = "all" ] && echo " ($MULTI_DISTROS)"
|
||||
echo " Image size: ${IMG_SIZE}MB"
|
||||
fi
|
||||
echo " Image size: ${IMG_SIZE}MB"
|
||||
if [ -f "$PATCHES_DIR/.config" ]; then
|
||||
LINUX_BRANCH="v$(grep -m1 "^# Linux/" "$PATCHES_DIR/.config" | grep -oP '\d+\.\d+(\.\d+)?')"
|
||||
echo " Kernel: $LINUX_BRANCH"
|
||||
@@ -135,19 +140,19 @@ echo ""
|
||||
echo "Stages:"
|
||||
if [ "$SKIP_KERNEL" = true ]; then
|
||||
echo " 1. Kernel cached"
|
||||
elif [ -d "$KERNEL_SRC/.git" ]; then
|
||||
echo " 1. Kernel build (source cached)"
|
||||
else
|
||||
if [ -d "$KERNEL_SRC/.git" ]; then
|
||||
echo " 1. Kernel build (source cached)"
|
||||
echo " 1. Kernel clone + build"
|
||||
fi
|
||||
if [ "$KERNEL_ONLY" = false ]; then
|
||||
if [ "$SKIP_CHROOT" = true ]; then
|
||||
echo " 2. Root filesystem cached"
|
||||
else
|
||||
echo " 1. Kernel clone + build"
|
||||
echo " 2. Root filesystem build"
|
||||
fi
|
||||
echo " 3. Disk image build"
|
||||
fi
|
||||
if [ "$SKIP_CHROOT" = true ]; then
|
||||
echo " 2. Root filesystem cached"
|
||||
else
|
||||
echo " 2. Root filesystem build"
|
||||
fi
|
||||
echo " 3. Disk image build"
|
||||
echo ""
|
||||
echo "Logs: $LOG_FILE"
|
||||
echo ""
|
||||
@@ -160,6 +165,19 @@ SPIN_CHARS='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
|
||||
run_stage() {
|
||||
local name="$1"
|
||||
shift
|
||||
|
||||
if [ "${CI:-}" = "true" ]; then
|
||||
echo "::group::$name"
|
||||
local rc=0
|
||||
"$@" || rc=$?
|
||||
echo "::endgroup::"
|
||||
if [ $rc -ne 0 ]; then
|
||||
echo "::error::Build failed at: $name"
|
||||
exit $rc
|
||||
fi
|
||||
return
|
||||
fi
|
||||
|
||||
local status_msg="$name"
|
||||
local spin_i=0
|
||||
|
||||
@@ -213,27 +231,30 @@ if [ "$SKIP_KERNEL" = true ]; then
|
||||
printf " ✓ %-60s\n" "Kernel packages (cached)"
|
||||
else
|
||||
if [ ! -d "$KERNEL_SRC/.git" ]; then
|
||||
LINUX_TMP_DIR="${LINUX_DEFAULT_DIR}.tmp"
|
||||
rm -rf "$LINUX_TMP_DIR"
|
||||
REPO_URL="$PATCHES_REPO"
|
||||
[ -n "$PATCHES_TOKEN" ] && REPO_URL="${PATCHES_REPO/https:\/\//https:\/\/${PATCHES_TOKEN}@}"
|
||||
|
||||
|
||||
mkdir -p "$PATCHES_DIR"
|
||||
if [ ! -d "$PATCHES_DIR/.git" ]; then
|
||||
run_stage "Clone ps5-linux-patches" \
|
||||
git clone --branch "$PATCHES_BRANCH" --depth 1 "$PATCHES_REPO" "$PATCHES_DIR"
|
||||
else
|
||||
run_stage "Update ps5-linux-patches" bash -c '
|
||||
git -C "'"$PATCHES_DIR"'" fetch --depth 1 origin tag "'"$PATCHES_BRANCH"'"
|
||||
git -C "'"$PATCHES_DIR"'" checkout "'"$PATCHES_BRANCH"'"
|
||||
git -C "'"$PATCHES_DIR"'" reset --hard "'"$PATCHES_BRANCH"'"'
|
||||
fi
|
||||
run_stage "Fetch ps5-linux-patches ($PATCHES_REF)" bash -c '
|
||||
cd "'"$PATCHES_DIR"'"
|
||||
[ ! -d .git ] && git init && git remote add origin "'"$REPO_URL"'"
|
||||
git fetch --depth 1 origin "'"$PATCHES_REF"'" || git fetch origin "'"$PATCHES_REF"'"
|
||||
git reset --hard FETCH_HEAD
|
||||
'
|
||||
LINUX_TMP_DIR="${LINUX_DEFAULT_DIR}.tmp"
|
||||
for dir in "$LINUX_TMP_DIR" "$LINUX_DEFAULT_DIR"; do
|
||||
[ -d "$dir" ] && docker run --rm \
|
||||
-v "$(dirname "$dir")":/parent \
|
||||
alpine rm -rf "/parent/$(basename "$dir")"
|
||||
done
|
||||
LINUX_BRANCH="v$(grep -m1 "^# Linux/" "$PATCHES_DIR/.config" | grep -oP '\d+\.\d+(\.\d+)?')"
|
||||
|
||||
run_stage "Clone kernel $LINUX_BRANCH" \
|
||||
git clone --branch "$LINUX_BRANCH" --depth 1 "$LINUX_REPO" "$LINUX_TMP_DIR"
|
||||
|
||||
run_stage "Apply patches" bash -c '
|
||||
set -e
|
||||
shopt -s nullglob
|
||||
set -e; shopt -s nullglob
|
||||
patches=("'"$PATCHES_DIR"'"/*.patch)
|
||||
[ ${#patches[@]} -eq 0 ] && { echo "No .patch files found in '"$PATCHES_DIR"'"; exit 1; }
|
||||
for p in "${patches[@]}"; do
|
||||
@@ -242,63 +263,57 @@ else
|
||||
done'
|
||||
|
||||
run_stage "Copy kernel config" \
|
||||
cp "$PATCHES_DIR/$PATCHES_CONFIG" "$LINUX_TMP_DIR/.config"
|
||||
cp "$PATCHES_DIR/.config" "$LINUX_TMP_DIR/.config"
|
||||
|
||||
mv "$LINUX_TMP_DIR" "$LINUX_DEFAULT_DIR"
|
||||
KERNEL_SRC="$LINUX_DEFAULT_DIR"
|
||||
else
|
||||
printf " ✓ %-60s\n" "Kernel source (cached)"
|
||||
fi
|
||||
|
||||
KERNEL_SRC="$(cd "$KERNEL_SRC" && pwd)"
|
||||
|
||||
rm -f "$KERNEL_OUT"/*.$PKG_EXT
|
||||
rm -f "$KERNEL_OUT"/*.deb "$KERNEL_OUT"/*.pkg.tar.zst
|
||||
|
||||
run_stage "Build kernel builder image" \
|
||||
docker build -t ps5-kernel-builder -f "$SCRIPT_DIR/docker/kernel-builder/Dockerfile" "$SCRIPT_DIR"
|
||||
docker build --platform "$KERNEL_BUILDER_PLATFORM" -t ps5-kernel-builder \
|
||||
-f "$SCRIPT_DIR/docker/kernel-builder/Dockerfile" "$SCRIPT_DIR"
|
||||
|
||||
run_stage "Compile kernel" \
|
||||
docker run --rm --name "$DOCKER_NAME" \
|
||||
docker run --rm --platform "$KERNEL_BUILDER_PLATFORM" --name "$DOCKER_NAME" \
|
||||
-v "$KERNEL_SRC":/src \
|
||||
-v "$KERNEL_OUT":/out \
|
||||
-v "$CCACHE_DIR":/ccache \
|
||||
ps5-kernel-builder
|
||||
|
||||
if [ "$DISTRO" = "all" ]; then
|
||||
ls "$KERNEL_OUT/staging/lib/modules/" | head -1 > "$KERNEL_OUT/VERSION"
|
||||
|
||||
case "$FORMAT" in deb|all)
|
||||
run_stage "Package kernel (.deb)" \
|
||||
docker run --rm --name "$DOCKER_NAME" \
|
||||
docker run --rm --platform "$KERNEL_BUILDER_PLATFORM" --name "$DOCKER_NAME" \
|
||||
-v "$KERNEL_SRC":/src \
|
||||
-v "$KERNEL_OUT":/out \
|
||||
-v "$CCACHE_DIR":/ccache \
|
||||
ps5-kernel-builder \
|
||||
bash -c 'make -j$(nproc) bindeb-pkg && cp /*.deb /out/'
|
||||
/package-deb.sh
|
||||
esac
|
||||
|
||||
case "$FORMAT" in arch|all)
|
||||
run_stage "Build arch packager image" \
|
||||
docker build -t ps5-kernel-packager-arch \
|
||||
-f "$SCRIPT_DIR/docker/kernel-builder-arch/Dockerfile" "$SCRIPT_DIR"
|
||||
|
||||
run_stage "Package kernel (.pkg.tar.zst)" \
|
||||
docker run --rm --name "$DOCKER_NAME" \
|
||||
-v "$KERNEL_OUT":/out \
|
||||
ps5-kernel-packager-arch
|
||||
esac
|
||||
fi
|
||||
|
||||
elif [ "$DISTRO" = "arch" ] || [ "$DISTRO" = "cachyos" ]; then
|
||||
run_stage "Build arch packager image" \
|
||||
docker build -t ps5-kernel-packager-arch \
|
||||
-f "$SCRIPT_DIR/docker/kernel-builder-arch/Dockerfile" "$SCRIPT_DIR"
|
||||
|
||||
run_stage "Package kernel (.pkg.tar.zst)" \
|
||||
docker run --rm --name "$DOCKER_NAME" \
|
||||
-v "$KERNEL_OUT":/out \
|
||||
ps5-kernel-packager-arch
|
||||
else
|
||||
run_stage "Package kernel (.deb)" \
|
||||
docker run --rm --name "$DOCKER_NAME" \
|
||||
-v "$KERNEL_SRC":/src \
|
||||
-v "$KERNEL_OUT":/out \
|
||||
-v "$CCACHE_DIR":/ccache \
|
||||
ps5-kernel-builder \
|
||||
bash -c 'make -j$(nproc) bindeb-pkg && cp /*.deb /out/'
|
||||
fi
|
||||
if [ "$KERNEL_ONLY" = true ]; then
|
||||
KVER=$(cat "$KERNEL_OUT/VERSION" 2>/dev/null || echo "unknown")
|
||||
echo ""
|
||||
echo "Done! Kernel $KVER packages in $KERNEL_OUT/"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Step 2: Build distribution image ---
|
||||
|
||||
@@ -8,6 +8,7 @@ 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
|
||||
|
||||
@@ -8,6 +8,7 @@ DISK="/dev/$(lsblk -ndo PKNAME "$ROOT_DEV")"
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition)
|
||||
|
||||
parted -s "$DISK" resizepart "$PART_NUM" 100%
|
||||
partprobe "$DISK"
|
||||
resize2fs "$ROOT_DEV"
|
||||
|
||||
systemctl disable grow-rootfs.service
|
||||
|
||||
@@ -175,7 +175,7 @@ actions:
|
||||
|
||||
# Install custom kernel packages
|
||||
if ls /opt/pkgs/*.pkg.tar.zst 1>/dev/null 2>&1; then
|
||||
pacman -U --noconfirm /opt/pkgs/*.pkg.tar.zst
|
||||
pacman -U --noconfirm --ask 4 /opt/pkgs/*.pkg.tar.zst
|
||||
rm -rf /opt/pkgs
|
||||
KVER=$(ls -1t /lib/modules | head -1)
|
||||
# mkinitcpio may warn about missing optional modules; don't fail on those
|
||||
|
||||
@@ -7,8 +7,8 @@ ROOT_DEV=$(findmnt -no SOURCE /)
|
||||
DISK="/dev/$(lsblk -ndo PKNAME "$ROOT_DEV")"
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition)
|
||||
|
||||
growpart "$DISK" "$PART_NUM"
|
||||
|
||||
resize2fs "$ROOT_DEV"
|
||||
growpart "$DISK" "$PART_NUM" || true
|
||||
partprobe "$DISK"
|
||||
resize2fs "$ROOT_DEV" || true
|
||||
|
||||
systemctl disable grow-rootfs.service
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#!/bin/bash
|
||||
# Grows the root partition and filesystem to fill the disk.
|
||||
# Runs once on first boot, then disables itself.
|
||||
set -e
|
||||
# If resize fails, the service stays enabled and retries next boot.
|
||||
|
||||
ROOT_DEV=$(findmnt -no SOURCE /)
|
||||
ROOT_DEV=$(findmnt -no SOURCE /) || { echo "Cannot find root device"; exit 1; }
|
||||
DISK=$(lsblk -ndo PKNAME "$ROOT_DEV")
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition)
|
||||
PART_NUM=$(cat /sys/class/block/$(basename "$ROOT_DEV")/partition 2>/dev/null)
|
||||
|
||||
if [ -z "$DISK" ] || [ -z "$PART_NUM" ]; then
|
||||
echo "Cannot determine disk layout (DISK=$DISK PART_NUM=$PART_NUM)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
growpart "/dev/$DISK" "$PART_NUM" || true
|
||||
resize2fs "$ROOT_DEV" || true
|
||||
partprobe "/dev/$DISK"
|
||||
resize2fs "$ROOT_DEV"
|
||||
|
||||
systemctl disable grow-rootfs.service
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
[Unit]
|
||||
Description=Grow root filesystem to fill disk
|
||||
DefaultDependencies=no
|
||||
Before=local-fs.target
|
||||
After=local-fs-pre.target
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/local/sbin/grow-rootfs
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=local-fs.target
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
FROM archlinux:latest
|
||||
FROM --platform=linux/amd64 archlinux:latest
|
||||
|
||||
# pacman 7+ sandbox doesn't work in Docker containers
|
||||
RUN echo 'DisableSandbox' >> /etc/pacman.conf
|
||||
|
||||
# Only packaging tools needed — kernel is already compiled
|
||||
RUN pacman -Syu --noconfirm && pacman -S --noconfirm \
|
||||
@@ -11,6 +14,7 @@ WORKDIR /out/staging
|
||||
# Output packages go to /out
|
||||
|
||||
COPY docker/kernel-builder-arch/build.sh /build.sh
|
||||
COPY docker/kernel-builder-arch/install.sh /install.sh
|
||||
RUN chmod +x /build.sh
|
||||
|
||||
CMD ["/build.sh"]
|
||||
|
||||
@@ -11,7 +11,7 @@ fi
|
||||
|
||||
# Determine version from staged modules directory
|
||||
KVER=$(ls /out/staging/lib/modules/)
|
||||
PKGNAME="linux-custom"
|
||||
PKGNAME="linux-ps5"
|
||||
VERSION=${KVER%%-*}
|
||||
|
||||
echo "==> Packaging kernel $KVER as pacman package"
|
||||
@@ -24,10 +24,22 @@ cp /out/staging/boot/bzImage "$STAGING/boot/vmlinuz-$KVER"
|
||||
cp /out/staging/System.map "$STAGING/boot/System.map-$KVER"
|
||||
cp /out/staging/.config "$STAGING/boot/config-$KVER"
|
||||
|
||||
# Copy pre-installed modules (Arch uses /lib -> /usr/lib)
|
||||
# Copy pre-installed modules (Arch uses /usr/lib/modules)
|
||||
mkdir -p "$STAGING/usr/lib/modules"
|
||||
cp -a "/out/staging/lib/modules/$KVER" "$STAGING/usr/lib/modules/"
|
||||
|
||||
# Kernel headers (for out-of-tree module builds)
|
||||
if [ -d /out/staging/headers ]; then
|
||||
# UAPI headers (/usr/include/linux/, /usr/include/asm/, etc.)
|
||||
cp -a /out/staging/headers/usr "$STAGING/usr"
|
||||
# Build headers (/usr/lib/modules/$KVER/build/)
|
||||
mkdir -p "$STAGING/usr/lib/modules/$KVER"
|
||||
cp -a /out/staging/headers/lib/modules/$KVER/build "$STAGING/usr/lib/modules/$KVER/build"
|
||||
fi
|
||||
|
||||
# Create .INSTALL from template, baking in KVER
|
||||
sed "s/__KVER__/$KVER/g" /install.sh > "$STAGING/.INSTALL"
|
||||
|
||||
# Create .PKGINFO
|
||||
BUILDDATE=$(date -u +%s)
|
||||
INSTALLED_SIZE=$(du -sb "$STAGING" | awk '{print $1}')
|
||||
@@ -35,24 +47,33 @@ cat > "$STAGING/.PKGINFO" << EOF
|
||||
pkgname = $PKGNAME
|
||||
pkgbase = $PKGNAME
|
||||
pkgver = ${VERSION}-1
|
||||
pkgdesc = Custom Linux kernel $KVER for PS5
|
||||
pkgdesc = PS5 Linux kernel $KVER (image + modules + headers)
|
||||
url = https://kernel.org
|
||||
builddate = $BUILDDATE
|
||||
packager = bootstrap_docker
|
||||
packager = ps5-linux
|
||||
size = $INSTALLED_SIZE
|
||||
arch = x86_64
|
||||
license = GPL-2.0-only
|
||||
provides = linux=$VERSION
|
||||
provides = linux-custom=$VERSION
|
||||
provides = linux-headers=$VERSION
|
||||
provides = linux-api-headers=$VERSION
|
||||
conflict = linux
|
||||
conflict = linux-headers
|
||||
conflict = linux-api-headers
|
||||
conflict = linux-custom
|
||||
replaces = linux
|
||||
replaces = linux-headers
|
||||
replaces = linux-api-headers
|
||||
replaces = linux-custom
|
||||
EOF
|
||||
|
||||
# Create .MTREE (required by newer pacman)
|
||||
cd "$STAGING"
|
||||
LANG=C bsdtar -czf .MTREE --format=mtree \
|
||||
--options='!all,use-set,type,uid,gid,mode,time,size,md5,sha256,link' \
|
||||
.PKGINFO *
|
||||
.PKGINFO .INSTALL *
|
||||
|
||||
# Build the package
|
||||
LANG=C bsdtar -cf - .PKGINFO .MTREE * | zstd -c -T0 > "/out/${PKGNAME}-${VERSION}-1-x86_64.pkg.tar.zst"
|
||||
LANG=C bsdtar -cf - .PKGINFO .INSTALL .MTREE * | zstd -c -T0 > "/out/${PKGNAME}-${VERSION}-1-x86_64.pkg.tar.zst"
|
||||
|
||||
echo "==> Done: /out/${PKGNAME}-${VERSION}-1-x86_64.pkg.tar.zst"
|
||||
|
||||
35
docker/kernel-builder-arch/install.sh
Normal file
35
docker/kernel-builder-arch/install.sh
Normal file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
# Pacman .INSTALL script for linux-ps5.
|
||||
# KVER is replaced at package build time.
|
||||
|
||||
post_install() {
|
||||
KVER="__KVER__"
|
||||
echo ">> linux-ps5 post_install: kernel $KVER"
|
||||
|
||||
# Rebuild initramfs
|
||||
if command -v mkinitcpio >/dev/null 2>&1; then
|
||||
echo ">> Rebuilding initramfs with mkinitcpio for $KVER"
|
||||
mkinitcpio -k "$KVER" -g "/boot/initrd.img-$KVER"
|
||||
fi
|
||||
|
||||
# Copy kernel + initrd to EFI partition
|
||||
if [ -d /boot/efi ]; then
|
||||
OLD_BZ=$(ls -l /boot/efi/bzImage 2>/dev/null | awk '{print $5}') || true
|
||||
OLD_INITRD=$(ls -l /boot/efi/initrd.img 2>/dev/null | awk '{print $5}') || true
|
||||
echo ">> Copying /boot/vmlinuz-$KVER -> /boot/efi/bzImage"
|
||||
cp "/boot/vmlinuz-$KVER" /boot/efi/bzImage
|
||||
NEW_BZ=$(ls -l /boot/efi/bzImage | awk '{print $5}')
|
||||
echo ">> bzImage: ${OLD_BZ:-<new>} -> $NEW_BZ bytes"
|
||||
echo ">> Copying /boot/initrd.img-$KVER -> /boot/efi/initrd.img"
|
||||
cp "/boot/initrd.img-$KVER" /boot/efi/initrd.img
|
||||
NEW_INITRD=$(ls -l /boot/efi/initrd.img | awk '{print $5}')
|
||||
echo ">> initrd.img: ${OLD_INITRD:-<new>} -> $NEW_INITRD bytes"
|
||||
echo ">> Kernel $KVER deployed to /boot/efi"
|
||||
else
|
||||
echo ">> /boot/efi not found, skipping EFI deploy"
|
||||
fi
|
||||
}
|
||||
|
||||
post_upgrade() {
|
||||
post_install
|
||||
}
|
||||
@@ -7,8 +7,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libdw-dev libelf-dev libssl-dev \
|
||||
python3 rsync dpkg-dev debhelper zstd \
|
||||
perl git xz-utils ccache \
|
||||
gcc-x86-64-linux-gnu binutils-x86-64-linux-gnu libc6-dev-amd64-cross \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV ARCH=x86_64
|
||||
ENV CROSS_COMPILE=x86_64-linux-gnu-
|
||||
ENV PATH="/usr/lib/ccache:${PATH}"
|
||||
ENV CCACHE_DIR=/ccache
|
||||
|
||||
@@ -18,6 +21,7 @@ WORKDIR /src
|
||||
# Build artifacts are staged to /out/staging
|
||||
|
||||
COPY docker/kernel-builder/build.sh /build.sh
|
||||
RUN chmod +x /build.sh
|
||||
COPY docker/kernel-builder/package-deb.sh /package-deb.sh
|
||||
RUN chmod +x /build.sh /package-deb.sh
|
||||
|
||||
CMD ["/build.sh"]
|
||||
|
||||
@@ -25,4 +25,13 @@ KVER=$(make -s kernelrelease)
|
||||
rm -f "/out/staging/lib/modules/$KVER/build" \
|
||||
"/out/staging/lib/modules/$KVER/source"
|
||||
|
||||
# Stage kernel headers for out-of-tree module builds
|
||||
echo "=== Staging kernel headers ==="
|
||||
HDR="/out/staging/headers"
|
||||
make headers_install INSTALL_HDR_PATH="$HDR/usr"
|
||||
|
||||
# Use the kernel's own install-extmod-build script (same as deb-pkg uses)
|
||||
export srctree=/src SRCARCH=x86
|
||||
CC="${CROSS_COMPILE}gcc" HOSTCC=gcc MAKE=make /src/scripts/package/install-extmod-build "$HDR/lib/modules/$KVER/build"
|
||||
|
||||
echo "=== Build artifacts staged in /out/staging ==="
|
||||
|
||||
80
docker/kernel-builder/package-deb.sh
Executable file
80
docker/kernel-builder/package-deb.sh
Executable file
@@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
# Builds a combined linux-ps5 .deb from staged artifacts in /out/staging.
|
||||
# Runs inside the kernel-builder container; output goes to /out.
|
||||
set -e
|
||||
|
||||
STAGING="/out/staging"
|
||||
KVER=$(ls -1 "$STAGING/lib/modules" | head -1)
|
||||
VER="${KVER%%-*}"
|
||||
ARCH=amd64
|
||||
|
||||
PKG=$(mktemp -d)
|
||||
mkdir -p "$PKG/DEBIAN"
|
||||
mkdir -p "$PKG/boot"
|
||||
mkdir -p "$PKG/lib/modules"
|
||||
|
||||
cp "$STAGING/boot/bzImage" "$PKG/boot/vmlinuz-$KVER"
|
||||
cp "$STAGING/System.map" "$PKG/boot/System.map-$KVER"
|
||||
cp "$STAGING/.config" "$PKG/boot/config-$KVER"
|
||||
cp -a "$STAGING/lib/modules/$KVER" "$PKG/lib/modules/"
|
||||
|
||||
# Kernel headers (for out-of-tree module builds)
|
||||
if [ -d "$STAGING/headers" ]; then
|
||||
cp -a "$STAGING/headers/usr" "$PKG/usr"
|
||||
# Point /lib/modules/$KVER/build at the installed headers
|
||||
HDR_DEST="/usr/lib/modules/$KVER/build"
|
||||
mkdir -p "$PKG/usr/lib/modules/$KVER"
|
||||
cp -a "$STAGING/headers/lib/modules/$KVER/build" "$PKG/usr/lib/modules/$KVER/build"
|
||||
ln -sf "$HDR_DEST" "$PKG/lib/modules/$KVER/build"
|
||||
fi
|
||||
|
||||
cat > "$PKG/DEBIAN/control" << CTRL
|
||||
Package: linux-ps5
|
||||
Version: $VER
|
||||
Architecture: $ARCH
|
||||
Maintainer: PS5 Linux
|
||||
Provides: linux-image-$KVER, linux-headers-$KVER, linux-libc-dev
|
||||
Conflicts: linux-image-$KVER, linux-headers-$KVER, linux-libc-dev
|
||||
Replaces: linux-image-$KVER, linux-headers-$KVER, linux-libc-dev
|
||||
Description: PS5 Linux kernel $KVER (image + modules + headers + libc-dev)
|
||||
CTRL
|
||||
|
||||
cat > "$PKG/DEBIAN/postinst" << 'POSTINST'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
KVER="$(ls -1t /lib/modules | head -1)"
|
||||
echo ">> linux-ps5 postinst: kernel $KVER"
|
||||
|
||||
# Rebuild initramfs
|
||||
if command -v update-initramfs >/dev/null 2>&1; then
|
||||
echo ">> Rebuilding initramfs with update-initramfs for $KVER"
|
||||
update-initramfs -c -k "$KVER"
|
||||
elif command -v mkinitcpio >/dev/null 2>&1; then
|
||||
echo ">> Rebuilding initramfs with mkinitcpio for $KVER"
|
||||
mkinitcpio -k "$KVER" -g "/boot/initrd.img-$KVER"
|
||||
elif command -v mkinitfs >/dev/null 2>&1; then
|
||||
echo ">> Rebuilding initramfs with mkinitfs for $KVER"
|
||||
mkinitfs -o "/boot/initrd.img-$KVER" "$KVER"
|
||||
fi
|
||||
|
||||
# Copy kernel + initrd to EFI partition
|
||||
if [ -d /boot/efi ]; then
|
||||
OLD_BZ=$(ls -l /boot/efi/bzImage 2>/dev/null | awk '{print $5}') || true
|
||||
OLD_INITRD=$(ls -l /boot/efi/initrd.img 2>/dev/null | awk '{print $5}') || true
|
||||
echo ">> Copying /boot/vmlinuz-$KVER -> /boot/efi/bzImage"
|
||||
cp "/boot/vmlinuz-$KVER" /boot/efi/bzImage
|
||||
NEW_BZ=$(ls -l /boot/efi/bzImage | awk '{print $5}')
|
||||
echo ">> bzImage: ${OLD_BZ:-<new>} -> $NEW_BZ bytes"
|
||||
echo ">> Copying /boot/initrd.img-$KVER -> /boot/efi/initrd.img"
|
||||
cp "/boot/initrd.img-$KVER" /boot/efi/initrd.img
|
||||
NEW_INITRD=$(ls -l /boot/efi/initrd.img | awk '{print $5}')
|
||||
echo ">> initrd.img: ${OLD_INITRD:-<new>} -> $NEW_INITRD bytes"
|
||||
echo ">> Kernel $KVER deployed to /boot/efi"
|
||||
else
|
||||
echo ">> /boot/efi not found, skipping EFI deploy"
|
||||
fi
|
||||
POSTINST
|
||||
chmod 755 "$PKG/DEBIAN/postinst"
|
||||
|
||||
dpkg-deb --build --root-owner-group "$PKG" "/out/linux-ps5_${VER}_${ARCH}.deb"
|
||||
rm -rf "$PKG"
|
||||
Reference in New Issue
Block a user