Red Bear OS — microkernel OS in Rust, based on Redox
Derivative of Redox OS (https://www.redox-os.org) adding: - AMD GPU driver (amdgpu) via LinuxKPI compat layer - ext4 filesystem support (ext4d scheme daemon) - ACPI fixes for AMD bare metal (x2APIC, DMAR, IVRS, MCFG) - Custom branding (hostname, os-release, boot identity) Build system is full upstream Redox with RBOS overlay in local/. Patches for kernel, base, and relibc are symlinked from local/patches/ and protected from make clean/distclean. Custom recipes live in local/recipes/ with symlinks into the recipes/ search path. Build: make all CONFIG_NAME=redbear-full Sync: ./local/scripts/sync-upstream.sh
This commit is contained in:
Executable
+156
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env bash
|
||||
# apply-patches.sh — Apply all RBOS patches on top of upstream Redox build system.
|
||||
#
|
||||
# Usage: ./local/scripts/apply-patches.sh [--force]
|
||||
#
|
||||
# This script:
|
||||
# 1. Applies build-system patches (rebranding, cookbook fixes, config, docs)
|
||||
# 2. Ensures recipe patches are symlinked from local/patches/
|
||||
# 3. Ensures custom recipe symlinks exist in recipes/
|
||||
#
|
||||
# With --force: reapplies even if patches appear already applied.
|
||||
#
|
||||
# SAFE: does not touch local/ directory. Only modifies upstream files.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
PATCHES_DIR="$REPO_ROOT/local/patches"
|
||||
FORCE="${1:-}"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# ── Helper ──────────────────────────────────────────────────────────
|
||||
symlink() {
|
||||
local target="$1" link="$2"
|
||||
if [ -L "$link" ]; then
|
||||
current="$(readlink "$link")"
|
||||
if [ "$current" = "$target" ]; then
|
||||
return 0 # already correct
|
||||
fi
|
||||
fi
|
||||
rm -f "$link"
|
||||
ln -s "$target" "$link"
|
||||
echo " linked $link -> $target"
|
||||
}
|
||||
|
||||
# ── 1. Build-system patches ─────────────────────────────────────────
|
||||
echo "==> Applying build-system patches..."
|
||||
for patch_file in "$PATCHES_DIR"/build-system/[0-9]*.patch; do
|
||||
[ -f "$patch_file" ] || continue
|
||||
patch_name="$(basename "$patch_file")"
|
||||
|
||||
# Check if already applied (skip unless --force)
|
||||
if [ "$FORCE" != "--force" ]; then
|
||||
if git apply --check "$patch_file" 2>/dev/null; then
|
||||
: # patch applies cleanly, apply it
|
||||
else
|
||||
echo " SKIP $patch_name (already applied or conflicts)"
|
||||
echo " Use --force to attempt re-application"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
if git apply --whitespace=nowarn "$patch_file"; then
|
||||
echo " OK $patch_name"
|
||||
else
|
||||
echo " FAIL $patch_name — resolve conflicts manually"
|
||||
echo " Patch file: $patch_file"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# ── 2. Recipe patches (kernel, base) ───────────────────────────────
|
||||
echo "==> Linking recipe patches from local/patches/..."
|
||||
symlink "../../../local/patches/kernel/redox.patch" "recipes/core/kernel/redox.patch"
|
||||
symlink "../../../local/patches/base/redox.patch" "recipes/core/base/redox.patch"
|
||||
|
||||
# ── 3. Custom recipe symlinks ──────────────────────────────────────
|
||||
echo "==> Linking custom recipes from local/recipes/..."
|
||||
|
||||
# Branding
|
||||
mkdir -p recipes/branding
|
||||
symlink "../../local/recipes/branding/redbear-release" "recipes/branding/redbear-release"
|
||||
|
||||
# Drivers
|
||||
mkdir -p recipes/drivers
|
||||
symlink "../../local/recipes/drivers/linux-kpi" "recipes/drivers/linux-kpi"
|
||||
symlink "../../local/recipes/drivers/redox-driver-sys" "recipes/drivers/redox-driver-sys"
|
||||
|
||||
# GPU
|
||||
mkdir -p recipes/gpu
|
||||
symlink "../../local/recipes/gpu/amdgpu" "recipes/gpu/amdgpu"
|
||||
symlink "../../local/recipes/gpu/redox-drm" "recipes/gpu/redox-drm"
|
||||
|
||||
# System
|
||||
mkdir -p recipes/system
|
||||
symlink "../../local/recipes/system/evdevd" "recipes/system/evdevd"
|
||||
symlink "../../local/recipes/system/firmware-loader" "recipes/system/firmware-loader"
|
||||
symlink "../../local/recipes/system/redbear-meta" "recipes/system/redbear-meta"
|
||||
symlink "../../local/recipes/system/udev-shim" "recipes/system/udev-shim"
|
||||
|
||||
# Core additions
|
||||
mkdir -p recipes/core
|
||||
symlink "../../local/recipes/core/ext4d" "recipes/core/ext4d"
|
||||
|
||||
# ── 4. New files not in upstream ────────────────────────────────────
|
||||
echo "==> Ensuring RBOS-specific files exist..."
|
||||
|
||||
# rbos.ipxe (network boot)
|
||||
if [ ! -f rbos.ipxe ] && [ ! -L rbos.ipxe ]; then
|
||||
cat > rbos.ipxe <<'IPXE'
|
||||
#!ipxe
|
||||
|
||||
kernel bootloader-live.efi
|
||||
initrd http://${next-server}:8080/rbos-live.iso
|
||||
boot
|
||||
IPXE
|
||||
echo " created rbos.ipxe"
|
||||
fi
|
||||
|
||||
# redbear-full config (not in upstream)
|
||||
if [ ! -f config/redbear-full.toml ] && [ ! -L config/redbear-full.toml ]; then
|
||||
cat > config/redbear-full.toml <<'TOML'
|
||||
# Red Bear OS Full Configuration
|
||||
# Complete desktop + all RBOS custom drivers and tools
|
||||
#
|
||||
# Build: make all CONFIG_NAME=redbear-full
|
||||
# Live: make live CONFIG_NAME=redbear-full
|
||||
|
||||
include = ["desktop.toml"]
|
||||
|
||||
[general]
|
||||
# 2GB filesystem — plenty for full desktop + drivers
|
||||
# (desktop.toml sets 650MB, but we want headroom for our custom packages)
|
||||
filesystem_size = 2048
|
||||
|
||||
[packages]
|
||||
# Red Bear OS branding (os-release, hostname, motd)
|
||||
redbear-release = {}
|
||||
|
||||
# ext4 filesystem support (our custom port)
|
||||
ext4d = {}
|
||||
|
||||
# RBOS driver infrastructure
|
||||
redox-driver-sys = {}
|
||||
linux-kpi = {}
|
||||
firmware-loader = {}
|
||||
|
||||
# Input layer
|
||||
evdevd = {}
|
||||
udev-shim = {}
|
||||
|
||||
# GPU driver (AMD — modesetting display core)
|
||||
redox-drm = {}
|
||||
amdgpu = {}
|
||||
|
||||
# RBOS meta-package (dependencies, default config)
|
||||
redbear-meta = {}
|
||||
TOML
|
||||
echo " created config/redbear-full.toml"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "==> All RBOS patches applied. Ready to build."
|
||||
echo " make all CONFIG_NAME=redbear-full"
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build Red Bear OS with AMD GPU support (Phase P2)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
CONFIG="${1:-my-amd-desktop}"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
APPLY_PATCHES="${APPLY_PATCHES:-1}"
|
||||
|
||||
echo "=== Red Bear OS AMD GPU Build ==="
|
||||
echo "Config: $CONFIG"
|
||||
echo "Jobs: $JOBS"
|
||||
echo "Apply patches: $APPLY_PATCHES"
|
||||
echo "Root: $PROJECT_ROOT"
|
||||
echo ""
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Step 0: Apply local patches
|
||||
if [ "$APPLY_PATCHES" = "1" ]; then
|
||||
echo ">>> Applying local patches..."
|
||||
|
||||
apply_patch_dir() {
|
||||
local patch_dir="$1"
|
||||
local target_dir="$2"
|
||||
local label="$3"
|
||||
|
||||
if [ ! -d "$patch_dir" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
for patch_file in $(ls "$patch_dir"/*.patch 2>/dev/null | sort); do
|
||||
patch_name=$(basename "$patch_file")
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
echo " SKIP $patch_name ($label source not fetched yet)"
|
||||
continue
|
||||
fi
|
||||
if patch --dry-run -p1 -d "$target_dir" < "$patch_file" > /dev/null 2>&1; then
|
||||
patch -p1 -d "$target_dir" < "$patch_file" > /dev/null 2>&1
|
||||
echo " OK $patch_name"
|
||||
else
|
||||
echo " SKIP $patch_name (already applied or won't apply)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/kernel" "$PROJECT_ROOT/recipes/core/kernel/source" "kernel"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/base" "$PROJECT_ROOT/recipes/core/base/source" "base"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/relibc" "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/bootloader" "$PROJECT_ROOT/recipes/core/bootloader/source" "bootloader"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/installer" "$PROJECT_ROOT/recipes/core/installer/source" "installer"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 1: Build cookbook binary if needed
|
||||
if [ ! -f "target/release/repo" ]; then
|
||||
echo ">>> Building cookbook binary..."
|
||||
cargo build --release
|
||||
fi
|
||||
|
||||
# Step 2: Fetch AMD firmware blobs if missing
|
||||
FW_DIR="$PROJECT_ROOT/local/firmware/amdgpu"
|
||||
if [ -z "$(ls -A "$FW_DIR" 2>/dev/null)" ]; then
|
||||
echo ">>> AMD firmware blobs not found. Run local/scripts/fetch-firmware.sh first."
|
||||
echo " Skipping firmware fetch. Driver will NOT function without firmware."
|
||||
else
|
||||
FW_COUNT=$(ls "$FW_DIR"/*.bin 2>/dev/null | wc -l)
|
||||
echo ">>> Found $FW_COUNT AMD firmware blobs"
|
||||
fi
|
||||
|
||||
# Step 3: Build
|
||||
echo ">>> Building RBOS with config: $CONFIG"
|
||||
echo ">>> This may take 30-60 minutes on first build..."
|
||||
CI=1 make all "CONFIG_NAME=$CONFIG" "JOBS=$JOBS"
|
||||
|
||||
echo ""
|
||||
echo "=== Build Complete ==="
|
||||
echo "Image: build/x86_64/harddrive.img"
|
||||
echo ""
|
||||
echo "To run in QEMU:"
|
||||
echo " make qemu QEMUFLAGS=\"-m 4G\""
|
||||
echo ""
|
||||
echo "To test on bare metal:"
|
||||
echo " dd if=build/x86_64/harddrive.img of=/dev/sdX bs=4M status=progress"
|
||||
Executable
+117
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
# build-redbear.sh — Build Red Bear OS
|
||||
#
|
||||
# Usage:
|
||||
# ./local/scripts/build-redbear.sh # Default: redbear-desktop
|
||||
# ./local/scripts/build-redbear.sh redbear-minimal # Minimal variant
|
||||
# ./local/scripts/build-redbear.sh redbear-live # Live ISO variant
|
||||
# APPLY_PATCHES=0 ./local/scripts/build-redbear.sh # Skip patch application
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
|
||||
CONFIG="${1:-redbear-desktop}"
|
||||
JOBS="${JOBS:-$(nproc)}"
|
||||
APPLY_PATCHES="${APPLY_PATCHES:-1}"
|
||||
|
||||
case "$CONFIG" in
|
||||
redbear-desktop|redbear-minimal|redbear-live)
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown config '$CONFIG'"
|
||||
echo "Supported: redbear-desktop, redbear-minimal, redbear-live"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "========================================"
|
||||
echo " Red Bear OS Build System"
|
||||
echo "========================================"
|
||||
echo "Config: $CONFIG"
|
||||
echo "Jobs: $JOBS"
|
||||
echo "Apply patches: $APPLY_PATCHES"
|
||||
echo "Root: ${PROJECT_ROOT##*/}"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
# Step 0: Apply local patches
|
||||
if [ "$APPLY_PATCHES" = "1" ]; then
|
||||
echo ">>> Applying local patches..."
|
||||
|
||||
apply_patch_dir() {
|
||||
local patch_dir="$1"
|
||||
local target_dir="$2"
|
||||
local label="$3"
|
||||
|
||||
if [ ! -d "$patch_dir" ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
for patch_file in "$patch_dir"/*.patch; do
|
||||
[ -f "$patch_file" ] || continue
|
||||
patch_name=$(basename "$patch_file")
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
echo " SKIP $patch_name ($label source not fetched yet)"
|
||||
continue
|
||||
fi
|
||||
if patch --dry-run -p1 -d "$target_dir" < "$patch_file" > /dev/null 2>&1; then
|
||||
patch -p1 -d "$target_dir" < "$patch_file" > /dev/null 2>&1
|
||||
echo " OK $patch_name"
|
||||
else
|
||||
echo " SKIP $patch_name (already applied or won't apply)"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/kernel" "$PROJECT_ROOT/recipes/core/kernel/source" "kernel"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/base" "$PROJECT_ROOT/recipes/core/base/source" "base"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/relibc" "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/bootloader" "$PROJECT_ROOT/recipes/core/bootloader/source" "bootloader"
|
||||
apply_patch_dir "$PROJECT_ROOT/local/patches/installer" "$PROJECT_ROOT/recipes/core/installer/source" "installer"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 1: Build cookbook binary
|
||||
if [ ! -f "target/release/repo" ]; then
|
||||
echo ">>> Building cookbook binary..."
|
||||
cargo build --release
|
||||
fi
|
||||
|
||||
# Step 2: Check firmware
|
||||
FW_AMD_DIR="$PROJECT_ROOT/local/firmware/amdgpu"
|
||||
if [ "$CONFIG" != "redbear-minimal" ]; then
|
||||
if [ -d "$FW_AMD_DIR" ] && [ -n "$(ls -A "$FW_AMD_DIR" 2>/dev/null)" ]; then
|
||||
FW_COUNT=$(ls "$FW_AMD_DIR"/*.bin 2>/dev/null | wc -l)
|
||||
echo ">>> Found $FW_COUNT AMD firmware blobs"
|
||||
else
|
||||
echo ">>> WARNING: No AMD firmware blobs found."
|
||||
echo " Run: ./local/scripts/fetch-firmware.sh"
|
||||
echo " GPU driver will NOT function without firmware."
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Step 3: Build
|
||||
echo ">>> Building Red Bear OS with config: $CONFIG"
|
||||
echo ">>> This may take 30-60 minutes on first build..."
|
||||
CI=1 make all "CONFIG_NAME=$CONFIG" "JOBS=$JOBS"
|
||||
|
||||
# Step 4: Report
|
||||
ARCH="${ARCH:-$(uname -m)}"
|
||||
echo ""
|
||||
echo "========================================"
|
||||
echo " Build Complete!"
|
||||
echo "========================================"
|
||||
echo "Image: build/$ARCH/$CONFIG/harddrive.img"
|
||||
echo ""
|
||||
echo "To run in QEMU:"
|
||||
echo " make qemu QEMUFLAGS=\"-m 4G\""
|
||||
echo ""
|
||||
echo "To build live ISO:"
|
||||
echo " make live CONFIG_NAME=$CONFIG"
|
||||
echo ""
|
||||
echo "To burn to USB (verify device first!):"
|
||||
echo " dd if=build/$ARCH/$CONFIG/harddrive.img of=/dev/sdX bs=4M status=progress"
|
||||
Executable
+180
@@ -0,0 +1,180 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fetch AMD GPU firmware blobs from linux-firmware repository
|
||||
# These are required for amdgpu driver to function
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
FIRMWARE_DIR="$SCRIPT_DIR/../firmware/amdgpu"
|
||||
LINUX_FIRMWARE_REPO="https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git"
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
SUBSET="all"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [--subset all|rdna]
|
||||
|
||||
Fetch AMD GPU firmware blobs from linux-firmware.
|
||||
|
||||
Options:
|
||||
--subset all Fetch the full amdgpu firmware set (default)
|
||||
--subset rdna Fetch only RDNA2/RDNA3-oriented firmware blobs
|
||||
-h, --help Show this help text
|
||||
EOF
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf "$TEMP_DIR"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--subset)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: --subset requires a value"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
SUBSET="$2"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$SUBSET" in
|
||||
all|rdna)
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unsupported subset: $SUBSET"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "=== AMD GPU Firmware Fetcher ==="
|
||||
echo "Target: $FIRMWARE_DIR"
|
||||
echo "Subset: $SUBSET"
|
||||
|
||||
# Clone linux-firmware (shallow)
|
||||
echo "Cloning linux-firmware repository..."
|
||||
git clone --depth 1 "$LINUX_FIRMWARE_REPO" "$TEMP_DIR/linux-firmware"
|
||||
|
||||
# Create target directory
|
||||
mkdir -p "$FIRMWARE_DIR"
|
||||
|
||||
# Copy AMD GPU firmware
|
||||
echo "Copying AMD GPU firmware blobs..."
|
||||
if [ -d "$TEMP_DIR/linux-firmware/amdgpu" ]; then
|
||||
shopt -s nullglob
|
||||
source_blobs=("$TEMP_DIR/linux-firmware/amdgpu/"*.bin)
|
||||
|
||||
if [ "$SUBSET" = "rdna" ]; then
|
||||
selected_blobs=()
|
||||
for blob in "${source_blobs[@]}"; do
|
||||
base="$(basename "$blob")"
|
||||
case "$base" in
|
||||
psp_13_*|gc_10_3_*|gc_11_0_*|sdma_5_*|sdma_6_*|dcn_3_*|dcn_3_1_*|mes_2_*|smu_13_*|vcn_4_*|gc_11_5_*)
|
||||
selected_blobs+=("$blob")
|
||||
;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
selected_blobs=("${source_blobs[@]}")
|
||||
fi
|
||||
|
||||
if [ "${#selected_blobs[@]}" -eq 0 ]; then
|
||||
echo "ERROR: No firmware blobs matched subset: $SUBSET"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -f "$FIRMWARE_DIR"/*.bin
|
||||
cp -v "${selected_blobs[@]}" "$FIRMWARE_DIR/"
|
||||
echo "Copied $(ls "$FIRMWARE_DIR/"*.bin 2>/dev/null | wc -l) firmware blobs"
|
||||
|
||||
echo "=== Verifying firmware selection ==="
|
||||
if [ "$SUBSET" = "rdna" ]; then
|
||||
if ls "$FIRMWARE_DIR"/gc_10_3_*.bin "$FIRMWARE_DIR"/gc_11_0_*.bin >/dev/null 2>&1; then
|
||||
echo "Verified RDNA graphics firmware families (gfx10.3/gfx11) are present"
|
||||
else
|
||||
echo "ERROR: Missing RDNA2/RDNA3 graphics firmware blobs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ls "$FIRMWARE_DIR"/psp_13_*_sos.bin >/dev/null 2>&1; then
|
||||
echo "Verified PSP SOS firmware is present"
|
||||
else
|
||||
echo "ERROR: Missing PSP SOS firmware blobs"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
non_rdna_count=0
|
||||
for blob in "$FIRMWARE_DIR"/*.bin; do
|
||||
base="$(basename "$blob")"
|
||||
case "$base" in
|
||||
psp_13_*|gc_10_3_*|gc_11_0_*|sdma_5_*|sdma_6_*|dcn_3_*|mes_2_*|smu_13_*|vcn_4_*|gc_11_5_*) ;;
|
||||
*) non_rdna_count=$((non_rdna_count + 1)) ;;
|
||||
esac
|
||||
done
|
||||
if [ "$non_rdna_count" -gt 0 ]; then
|
||||
echo "ERROR: Non-RDNA firmware blob detected in rdna subset"
|
||||
exit 1
|
||||
fi
|
||||
echo "Verified subset contains only RDNA-oriented firmware families"
|
||||
else
|
||||
if ls "$FIRMWARE_DIR"/*.bin >/dev/null 2>&1; then
|
||||
echo "Verified full AMD firmware set copied successfully"
|
||||
else
|
||||
echo "ERROR: No firmware blobs were copied"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
shopt -u nullglob
|
||||
else
|
||||
echo "ERROR: amdgpu firmware directory not found in linux-firmware"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Also create a listing of which firmware blobs map to which ASICs
|
||||
echo "=== Creating firmware manifest ==="
|
||||
cat > "$FIRMWARE_DIR/MANIFEST.txt" << 'MANIFEST'
|
||||
# AMD GPU Firmware for Red Bear OS
|
||||
# Source: linux-firmware (https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git)
|
||||
# License: Various — see linux-firmware WHENCE file for details
|
||||
#
|
||||
# Required for: RDNA2 (gfx10.3), RDNA3 (gfx11)
|
||||
# Minimum set for basic display output:
|
||||
# - PSP SOS + TA (security processor)
|
||||
# - GC ME/PFP/CE/MEC (graphics/compute)
|
||||
# - SDMA (DMA engine)
|
||||
# - DMCUB (Display Microcontroller)
|
||||
#
|
||||
# Key files for RDNA2 (Navi 21/22/23/24, gfx10.3):
|
||||
# psp_13_0_*_sos.bin, gc_10_3_*.bin, sdma_5_*.bin, dcn_3_*.bin
|
||||
#
|
||||
# Key files for RDNA3 (Navi 31/32/33, gfx11):
|
||||
# psp_13_*_sos.bin, gc_11_0_*.bin, sdma_6_*.bin, dcn_3_1_*.bin
|
||||
MANIFEST
|
||||
|
||||
echo "$FIRMWARE_DIR/MANIFEST.txt created"
|
||||
|
||||
# Summary
|
||||
echo ""
|
||||
echo "=== Firmware blobs installed ==="
|
||||
ls -la "$FIRMWARE_DIR/" | head -20
|
||||
echo "..."
|
||||
echo "Total: $(ls "$FIRMWARE_DIR/"*.bin 2>/dev/null | wc -l) blobs"
|
||||
echo ""
|
||||
echo "WARNING: These are proprietary firmware blobs from AMD."
|
||||
echo "They are NOT open source. Verify your license compliance."
|
||||
Executable
+159
@@ -0,0 +1,159 @@
|
||||
#!/usr/bin/env bash
|
||||
# sync-upstream.sh — Update from upstream Redox and reapply RBOS patches.
|
||||
#
|
||||
# Usage:
|
||||
# ./local/scripts/sync-upstream.sh # Rebase onto upstream master
|
||||
# ./local/scripts/sync-upstream.sh --dry-run # Preview what would change
|
||||
# ./local/scripts/sync-upstream.sh --no-merge # Only fetch + check for conflicts
|
||||
#
|
||||
# Strategy: git rebase (preserves RBOS commits, replays on new upstream).
|
||||
# Fallback: if rebase fails, patches in local/patches/build-system/ can be
|
||||
# applied from scratch via: ./local/scripts/apply-patches.sh --force
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
UPSTREAM_URL="${UPSTREAM_URL:-https://github.com/redox-os/redox.git}"
|
||||
UPSTREAM_REMOTE="upstream-redox"
|
||||
UPSTREAM_BRANCH="${UPSTREAM_BRANCH:-master}"
|
||||
DRY_RUN=0
|
||||
NO_MERGE=0
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) DRY_RUN=1 ;;
|
||||
--no-merge) NO_MERGE=1 ;;
|
||||
--help|-h)
|
||||
echo "Usage: $0 [--dry-run] [--no-merge]"
|
||||
echo " --dry-run Show what would happen without making changes"
|
||||
echo " --no-merge Only fetch and check patch conflicts"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $arg"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# ── 1. Ensure upstream remote ───────────────────────────────────────
|
||||
if ! git remote get-url "$UPSTREAM_REMOTE" &>/dev/null; then
|
||||
echo "==> Adding upstream remote: $UPSTREAM_URL"
|
||||
[ "$DRY_RUN" = "0" ] && git remote add "$UPSTREAM_REMOTE" "$UPSTREAM_URL"
|
||||
fi
|
||||
|
||||
echo "==> Fetching $UPSTREAM_REMOTE/$UPSTREAM_BRANCH..."
|
||||
[ "$DRY_RUN" = "0" ] && git fetch "$UPSTREAM_REMOTE" "$UPSTREAM_BRANCH"
|
||||
|
||||
UPSTREAM_REF="${UPSTREAM_REMOTE}/${UPSTREAM_BRANCH}"
|
||||
|
||||
# ── 2. Check patch conflicts with upstream changes ──────────────────
|
||||
MERGE_BASE=$(git merge-base HEAD "$UPSTREAM_REF" 2>/dev/null || echo "")
|
||||
if [ -n "$MERGE_BASE" ]; then
|
||||
CHANGED_FILES=$(git diff --name-only "$MERGE_BASE" "$UPSTREAM_REF" 2>/dev/null || true)
|
||||
CHANGE_COUNT=$(echo "$CHANGED_FILES" | grep -c . 2>/dev/null || echo "0")
|
||||
echo " $CHANGE_COUNT files changed upstream since common ancestor"
|
||||
|
||||
if [ -n "$CHANGED_FILES" ] && [ -d local/patches ]; then
|
||||
echo ""
|
||||
echo "==> Checking patch conflict risks..."
|
||||
for patch_file in local/patches/build-system/[0-9]*.patch; do
|
||||
[ -f "$patch_file" ] || continue
|
||||
PATCH_NAME=$(basename "$patch_file")
|
||||
PATCHED_FILES=$(grep '^--- a/' "$patch_file" 2>/dev/null | sed 's|^--- a/||' | sort -u || true)
|
||||
for pf in $PATCHED_FILES; do
|
||||
if echo "$CHANGED_FILES" | grep -q "$pf" 2>/dev/null; then
|
||||
echo " ⚠ CONFLICT RISK: $PATCH_NAME modifies $pf (also changed upstream)"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
for patch_dir in local/patches/kernel local/patches/base; do
|
||||
[ -f "$patch_dir/redox.patch" ] || continue
|
||||
echo " ℹ $patch_dir/redox.patch — check manually if kernel/base changed upstream"
|
||||
done
|
||||
fi
|
||||
else
|
||||
echo " WARNING: Could not find common ancestor with upstream"
|
||||
fi
|
||||
|
||||
# ── 3. Summary ─────────────────────────────────────────────────────
|
||||
AHEAD=$(git rev-list --count "$UPSTREAM_REF..HEAD" 2>/dev/null || echo "?")
|
||||
BEHIND=$(git rev-list --count "HEAD..$UPSTREAM_REF" 2>/dev/null || echo "?")
|
||||
echo ""
|
||||
echo "=== Sync Summary ==="
|
||||
echo "Upstream: $UPSTREAM_REF"
|
||||
echo "Local: HEAD ($(git rev-parse --short HEAD))"
|
||||
echo "Ahead: $AHEAD RBOS commits"
|
||||
echo "Behind: $BEHIND upstream commits"
|
||||
|
||||
if [ "$NO_MERGE" = 1 ]; then
|
||||
echo ""
|
||||
echo "To merge manually:"
|
||||
echo " git rebase $UPSTREAM_REF"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$DRY_RUN" = "1" ]; then
|
||||
echo ""
|
||||
echo " [dry-run] Would rebase onto $UPSTREAM_REF"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ── 4. Stash uncommitted changes ────────────────────────────────────
|
||||
STASHED=0
|
||||
if ! git diff --quiet 2>/dev/null || ! git diff --cached --quiet 2>/dev/null; then
|
||||
echo "==> Stashing uncommitted changes..."
|
||||
git stash push -m "rbos-sync-$(date +%Y%m%d-%H%M%S)"
|
||||
STASHED=1
|
||||
fi
|
||||
|
||||
PREV_HEAD=$(git rev-parse HEAD)
|
||||
|
||||
# ── 5. Rebase ───────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "==> Rebasing RBOS commits onto $UPSTREAM_REF..."
|
||||
echo " (this replays our $AHEAD commits on top of updated upstream)"
|
||||
|
||||
if git rebase "$UPSTREAM_REF"; then
|
||||
echo ""
|
||||
echo "==> Rebase successful."
|
||||
else
|
||||
echo ""
|
||||
echo "!! Rebase conflict. Options:"
|
||||
echo " 1. Resolve conflicts: edit files, git add, git rebase --continue"
|
||||
echo " 2. Abort: git rebase --abort"
|
||||
echo " 3. Nuclear option:"
|
||||
echo " git rebase --abort"
|
||||
echo " git reset --hard $UPSTREAM_REF"
|
||||
echo " ./local/scripts/apply-patches.sh --force"
|
||||
echo ""
|
||||
echo " Patches for recovery: local/patches/build-system/"
|
||||
echo " Previous HEAD: $PREV_HEAD"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ── 6. Restore stash ────────────────────────────────────────────────
|
||||
if [ "$STASHED" = 1 ]; then
|
||||
echo "==> Restoring stashed changes..."
|
||||
git stash pop || echo " (stash pop had conflicts — resolve manually)"
|
||||
fi
|
||||
|
||||
# ── 7. Verify symlinks ─────────────────────────────────────────────
|
||||
echo "==> Verifying recipe patch symlinks..."
|
||||
if [ -f local/scripts/apply-patches.sh ]; then
|
||||
bash local/scripts/apply-patches.sh
|
||||
else
|
||||
echo " apply-patches.sh not found — verify symlinks manually"
|
||||
ls -la recipes/core/kernel/redox.patch recipes/core/base/redox.patch
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "==> Sync complete."
|
||||
echo " Previous HEAD: $PREV_HEAD"
|
||||
echo " New HEAD: $(git rev-parse HEAD)"
|
||||
echo ""
|
||||
echo "Next: make all CONFIG_NAME=redbear-full"
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Test AMD GPU driver on Red Bear OS
|
||||
# Run this inside RBOS (or via QEMU serial console)
|
||||
set -euo pipefail
|
||||
|
||||
echo "=== AMD GPU Driver Test ==="
|
||||
echo ""
|
||||
|
||||
# Check if scheme:drm exists
|
||||
if [ -e "/scheme/drm" ]; then
|
||||
echo "✅ scheme:drm registered"
|
||||
else
|
||||
echo "❌ scheme:drm NOT found — redox-drm daemon not running?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check card0
|
||||
if [ -e "/scheme/drm/card0" ]; then
|
||||
echo "✅ /scheme/drm/card0 exists"
|
||||
else
|
||||
echo "❌ /scheme/drm/card0 NOT found — AMD GPU not detected?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Try to read connector info
|
||||
echo ""
|
||||
echo "=== Connector Info ==="
|
||||
if command -v modetest &>/dev/null; then
|
||||
modetest -M amd 2>&1 | head -50
|
||||
else
|
||||
echo "modetest not available — reading raw scheme"
|
||||
# Read from scheme directly
|
||||
cat /scheme/drm/card0 2>&1 | head -20 || true
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== PCI Devices (GPU) ==="
|
||||
ls /scheme/pci/ 2>/dev/null | while read -r entry; do
|
||||
echo " $entry"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Test Complete ==="
|
||||
Executable
+228
@@ -0,0 +1,228 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build and burn a Red Bear OS hard drive image for bare-metal AMD testing
|
||||
# Requires explicit target device selection and write permissions
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REDOX_ROOT="$(dirname "$0")/../.."
|
||||
REDOX_ROOT="$(cd "$REDOX_ROOT" && pwd)"
|
||||
IMAGE_PATH="$REDOX_ROOT/build/harddrive.img"
|
||||
|
||||
CONFIG="my-amd-desktop"
|
||||
DEVICE=""
|
||||
DRY_RUN=0
|
||||
SKIP_BUILD=0
|
||||
VERIFY_BURN=0
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [OPTIONS] [CONFIG_NAME]
|
||||
|
||||
Build and burn a Red Bear OS bare-metal test image to a block device.
|
||||
|
||||
Arguments:
|
||||
CONFIG_NAME Red Bear OS config to build (default: my-amd-desktop)
|
||||
|
||||
Options:
|
||||
--device PATH Target block device to overwrite (required)
|
||||
--skip-build Skip 'make all CONFIG_NAME=...'
|
||||
--verify Verify the written image with cmp after dd
|
||||
--dry-run Show actions without building or writing
|
||||
-h, --help Show this help text
|
||||
|
||||
Notes:
|
||||
- This script never auto-detects a target device.
|
||||
- Run it with permissions that can write to the selected block device.
|
||||
- Expected image path: build/harddrive.img
|
||||
EOF
|
||||
}
|
||||
|
||||
run_cmd() {
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
printf '[dry-run]'
|
||||
printf ' %q' "$@"
|
||||
printf '\n'
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
show_available_devices() {
|
||||
echo "=== Available block devices ==="
|
||||
lsblk -e7 -o NAME,PATH,SIZE,MODEL,TRAN,TYPE,MOUNTPOINTS
|
||||
echo ""
|
||||
}
|
||||
|
||||
warn_if_system_disk() {
|
||||
local target_path="$1"
|
||||
local target_name parent_name mount_info root_source root_parent
|
||||
|
||||
target_name="$(basename "$target_path")"
|
||||
parent_name="$(lsblk -no PKNAME "$target_path" 2>/dev/null | head -n 1 || true)"
|
||||
mount_info="$(lsblk -nr -o PATH,MOUNTPOINTS "$target_path" 2>/dev/null || true)"
|
||||
root_source="$(findmnt -n -o SOURCE / 2>/dev/null || true)"
|
||||
root_parent=""
|
||||
|
||||
if [ -n "$root_source" ] && [ -b "$root_source" ]; then
|
||||
root_parent="$(lsblk -no PKNAME "$root_source" 2>/dev/null | head -n 1 || true)"
|
||||
fi
|
||||
|
||||
if printf '%s\n' "$mount_info" | grep -Eq '(/|/boot|/home|\[SWAP\])'; then
|
||||
echo "WARNING: $target_path or one of its partitions appears to be mounted."
|
||||
echo "$mount_info"
|
||||
fi
|
||||
|
||||
if [ -n "$root_source" ]; then
|
||||
if [ "$root_source" = "$target_path" ] || [ "/dev/$parent_name" = "$target_path" ] || [ "$target_name" = "$root_parent" ]; then
|
||||
echo "WARNING: $target_path appears related to the current root device ($root_source)."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
refuse_unsafe_device() {
|
||||
local target_path="$1"
|
||||
local target_name
|
||||
|
||||
target_name="$(basename "$target_path")"
|
||||
|
||||
case "$target_name" in
|
||||
sda|hda|vda|xvda|mmcblk0|nvme0|nvme0n1)
|
||||
echo "ERROR: Refusing to write to likely system disk $target_path"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
confirm_write() {
|
||||
local prompt="$1"
|
||||
local reply
|
||||
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
echo "[dry-run] Confirmation skipped: $prompt"
|
||||
return
|
||||
fi
|
||||
|
||||
read -r -p "$prompt [y/N]: " reply
|
||||
case "$reply" in
|
||||
y|Y|yes|YES)
|
||||
;;
|
||||
*)
|
||||
echo "Aborted."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
--device)
|
||||
if [ "$#" -lt 2 ]; then
|
||||
echo "ERROR: --device requires a path"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
DEVICE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--skip-build)
|
||||
SKIP_BUILD=1
|
||||
shift
|
||||
;;
|
||||
--verify)
|
||||
VERIFY_BURN=1
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--*)
|
||||
echo "ERROR: Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
CONFIG="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "=== Red Bear OS Bare-Metal AMD Test Image Burner ==="
|
||||
echo "Config: $CONFIG"
|
||||
echo "Image: $IMAGE_PATH"
|
||||
echo "Device: ${DEVICE:-<not set>}"
|
||||
echo ""
|
||||
|
||||
if [ -z "$DEVICE" ]; then
|
||||
echo "ERROR: You must specify a target block device with --device"
|
||||
echo ""
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
show_available_devices
|
||||
|
||||
if [ ! -e "$DEVICE" ]; then
|
||||
echo "ERROR: Target device does not exist: $DEVICE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -b "$DEVICE" ]; then
|
||||
echo "ERROR: Target path is not a block device: $DEVICE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$(lsblk -dn -o TYPE "$DEVICE")" != "disk" ]; then
|
||||
echo "ERROR: Target must be a whole-disk block device, not a partition: $DEVICE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
refuse_unsafe_device "$DEVICE"
|
||||
warn_if_system_disk "$DEVICE"
|
||||
|
||||
if [ "$SKIP_BUILD" -eq 0 ]; then
|
||||
echo "=== Building RBOS image ==="
|
||||
run_cmd make -C "$REDOX_ROOT" all CONFIG_NAME="$CONFIG"
|
||||
else
|
||||
echo "=== Skipping build step ==="
|
||||
fi
|
||||
|
||||
echo "=== Checking image ==="
|
||||
if [ ! -f "$IMAGE_PATH" ]; then
|
||||
echo "ERROR: RBOS image not found: $IMAGE_PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IMAGE_SIZE_BYTES="$(stat -c %s "$IMAGE_PATH")"
|
||||
echo "Image size: $IMAGE_SIZE_BYTES bytes"
|
||||
echo ""
|
||||
|
||||
echo "About to write $IMAGE_PATH to $DEVICE"
|
||||
echo "This will overwrite all data on the target device."
|
||||
confirm_write "Continue with dd write?"
|
||||
|
||||
echo "=== Writing image to device ==="
|
||||
run_cmd dd if="$IMAGE_PATH" of="$DEVICE" bs=4M conv=fsync status=progress
|
||||
|
||||
echo "=== Synchronizing device ==="
|
||||
run_cmd sync
|
||||
|
||||
if [ "$VERIFY_BURN" -eq 1 ]; then
|
||||
echo "=== Verifying written image ==="
|
||||
run_cmd cmp -n "$IMAGE_SIZE_BYTES" "$IMAGE_PATH" "$DEVICE"
|
||||
echo "Verification completed successfully."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Next steps ==="
|
||||
echo "1. Safely eject or unplug the target device if your host requires it."
|
||||
echo "2. Insert the device into the AMD test machine and boot from it in UEFI mode."
|
||||
echo "3. Capture serial output during boot if available to diagnose early failures."
|
||||
echo "4. Check ACPI, SMP, framebuffer, and storage initialization on real hardware."
|
||||
echo ""
|
||||
echo "If you need serial logs, connect your serial console before powering on the target system."
|
||||
Reference in New Issue
Block a user