Files
RedBear-OS/local/scripts/integrate-redbear.sh
T
vasilito b9874d0941 feat: USB storage read/write proof + full Red Bear OS tree sync
Add redbear-usb-storage-check in-guest binary that validates USB mass
storage read and write I/O: discovers /scheme/disk/ devices, writes a
test pattern to sector 2048, reads it back, verifies match, restores
original content. Updates test-usb-storage-qemu.sh with write-proof
verification step.

Includes all accumulated Red Bear OS work: kernel patches, relibc
patches, driver infrastructure, DRM/GPU, KDE recipes, firmware,
validation tooling, build system hardening, and documentation.
2026-05-03 23:03:24 +01:00

374 lines
14 KiB
Bash
Executable File

#!/usr/bin/env bash
# integrate-redbear.sh — Prepare Red Bear OS custom work for standard builds.
#
# Usage:
# ./local/scripts/integrate-redbear.sh
# REDBEAR_TAG=build/x86_64-unknown-redox/redbear.tag ./local/scripts/integrate-redbear.sh
#
# This script is idempotent and safe to run repeatedly. It ensures the Red Bear OS overlay
# is wired into the main build tree, stages branding assets and firmware into local
# recipe sources, and updates a tag file consumed by the build system.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
REDBEAR_TAG="${REDBEAR_TAG:-build/redbear.tag}"
if [ -t 1 ]; then
GREEN='\033[1;32m'
YELLOW='\033[1;33m'
CYAN='\033[1;36m'
RESET='\033[0m'
else
GREEN=''
YELLOW=''
CYAN=''
RESET=''
fi
cd "$PROJECT_ROOT"
status() {
echo -e "${GREEN}${RESET} $1"
}
warn() {
echo -e "${YELLOW}⚠️${RESET} $1"
}
section() {
echo -e "${CYAN}==>${RESET} $1"
}
require_repo_relative_path() {
local path="$1"
case "$path" in
/*|../*|*/../*|..)
warn "Refusing unsafe path outside repo: $path"
return 1
;;
esac
}
require_real_parent_dirs() {
local path="$1"
local parent="$(dirname "$path")"
require_repo_relative_path "$path"
while [ "$parent" != "." ] && [ "$parent" != "/" ]; do
if [ -L "$parent" ]; then
warn "Refusing path with symlink parent: $path"
return 1
fi
parent="$(dirname "$parent")"
done
}
symlink() {
local target="$1"
local link="$2"
local current=""
require_real_parent_dirs "$link"
mkdir -p "$(dirname "$link")"
if [ -L "$link" ]; then
current="$(readlink "$link")"
if [ "$current" = "$target" ]; then
return 0
fi
fi
if [ -d "$link" ] && [ ! -L "$link" ]; then
warn "Refusing to replace directory $link"
return 1
fi
if [ -e "$link" ] || [ -L "$link" ]; then
rm -f "$link"
ln -s "$target" "$link"
status "Refreshed $link -> $target"
else
ln -s "$target" "$link"
status "Linked $link -> $target"
fi
}
stage_file() {
local source_path="$1"
local dest_path="$2"
local label="$3"
if [ ! -f "$source_path" ]; then
warn "$label missing at ${source_path#$PROJECT_ROOT/}; skipping"
return 0
fi
require_real_parent_dirs "$dest_path"
if [ -L "$dest_path" ]; then
warn "$label destination is a symlink at ${dest_path#$PROJECT_ROOT/}; refusing to overwrite"
return 1
fi
mkdir -p "$(dirname "$dest_path")"
if [ -f "$dest_path" ] && cmp -s "$source_path" "$dest_path"; then
status "$label already staged"
return 0
fi
cp "$source_path" "$dest_path"
status "Staged $label"
}
echo "========================================"
echo " Red Bear OS Pre-Build Integration"
echo "========================================"
echo "Root: ${PROJECT_ROOT##*/}"
echo "Tag: $REDBEAR_TAG"
echo ""
section "Ensuring custom recipe symlinks..."
symlink "../../local/recipes/branding/redbear-release" "recipes/branding/redbear-release"
symlink "../../local/recipes/drivers/linux-kpi" "recipes/drivers/linux-kpi"
symlink "../../local/recipes/drivers/redbear-btusb" "recipes/drivers/redbear-btusb"
symlink "../../local/recipes/drivers/redbear-iwlwifi" "recipes/drivers/redbear-iwlwifi"
symlink "../../local/recipes/drivers/redox-driver-sys" "recipes/drivers/redox-driver-sys"
symlink "../../local/recipes/gpu/amdgpu" "recipes/gpu/amdgpu"
symlink "../../local/recipes/gpu/redox-drm" "recipes/gpu/redox-drm"
symlink "../../local/recipes/libs/libqrencode" "recipes/libs/libqrencode"
symlink "../../local/recipes/system/evdevd" "recipes/system/evdevd"
symlink "../../local/recipes/system/redbear-firmware" "recipes/system/redbear-firmware"
symlink "../../local/recipes/system/firmware-loader" "recipes/system/firmware-loader"
symlink "../../local/recipes/system/iommu" "recipes/system/iommu"
symlink "../../local/recipes/system/redbear-btctl" "recipes/system/redbear-btctl"
symlink "../../local/recipes/system/redbear-info" "recipes/system/redbear-info"
symlink "../../local/recipes/system/redbear-hwutils" "recipes/system/redbear-hwutils"
symlink "../../local/recipes/system/redbear-netstat" "recipes/system/redbear-netstat"
symlink "../../local/recipes/system/redbear-netctl" "recipes/system/redbear-netctl"
symlink "../../local/recipes/system/redbear-netctl-console" "recipes/system/redbear-netctl-console"
symlink "../../local/recipes/system/redbear-wifictl" "recipes/system/redbear-wifictl"
symlink "../../local/recipes/system/redbear-traceroute" "recipes/system/redbear-traceroute"
symlink "../../local/recipes/system/redbear-mtr" "recipes/system/redbear-mtr"
symlink "../../local/recipes/system/redbear-nmap" "recipes/system/redbear-nmap"
symlink "../../local/recipes/system/redbear-meta" "recipes/system/redbear-meta"
symlink "../../local/recipes/system/udev-shim" "recipes/system/udev-shim"
symlink "../../local/recipes/core/ext4d" "recipes/core/ext4d"
symlink "../../local/recipes/tui/mc" "recipes/tui/mc"
symlink "../../local/recipes/system/cub" "recipes/system/cub"
symlink "../../../local/recipes/wayland/qt6-wayland-smoke" "recipes/wip/wayland/qt6-wayland-smoke"
# KDE / Phase 6 recipes
mkdir -p recipes/kde
symlink "../../local/recipes/kde/plasma-desktop" "recipes/kde/plasma-desktop"
symlink "../../local/recipes/kde/plasma-workspace" "recipes/kde/plasma-workspace"
symlink "../../local/recipes/kde/plasma-framework" "recipes/kde/plasma-framework"
symlink "../../local/recipes/kde/plasma-wayland-protocols" "recipes/kde/plasma-wayland-protocols"
symlink "../../local/recipes/kde/kwin" "recipes/kde/kwin"
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kirigami"
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kf6-kirigami"
symlink "../../local/recipes/kde/kdecoration" "recipes/kde/kdecoration"
symlink "../../local/recipes/kde/kf6-extra-cmake-modules" "recipes/kde/kf6-extra-cmake-modules"
symlink "../../local/recipes/kde/kf6-kcoreaddons" "recipes/kde/kf6-kcoreaddons"
symlink "../../local/recipes/kde/kf6-kwidgetsaddons" "recipes/kde/kf6-kwidgetsaddons"
symlink "../../local/recipes/kde/kf6-kconfig" "recipes/kde/kf6-kconfig"
symlink "../../local/recipes/kde/kf6-ki18n" "recipes/kde/kf6-ki18n"
symlink "../../local/recipes/kde/kf6-kcodecs" "recipes/kde/kf6-kcodecs"
symlink "../../local/recipes/kde/kf6-kguiaddons" "recipes/kde/kf6-kguiaddons"
symlink "../../local/recipes/kde/kf6-kcolorscheme" "recipes/kde/kf6-kcolorscheme"
symlink "../../local/recipes/kde/kf6-kauth" "recipes/kde/kf6-kauth"
symlink "../../local/recipes/kde/kf6-kitemmodels" "recipes/kde/kf6-kitemmodels"
symlink "../../local/recipes/kde/kf6-kitemviews" "recipes/kde/kf6-kitemviews"
symlink "../../local/recipes/kde/kf6-attica" "recipes/kde/kf6-attica"
symlink "../../local/recipes/kde/kf6-karchive" "recipes/kde/kf6-karchive"
symlink "../../local/recipes/kde/kf6-kwindowsystem" "recipes/kde/kf6-kwindowsystem"
symlink "../../local/recipes/kde/kf6-knotifications" "recipes/kde/kf6-knotifications"
symlink "../../local/recipes/kde/kf6-kjobwidgets" "recipes/kde/kf6-kjobwidgets"
symlink "../../local/recipes/kde/kf6-kconfigwidgets" "recipes/kde/kf6-kconfigwidgets"
symlink "../../local/recipes/kde/kf6-kcrash" "recipes/kde/kf6-kcrash"
symlink "../../local/recipes/kde/kf6-kdbusaddons" "recipes/kde/kf6-kdbusaddons"
symlink "../../local/recipes/kde/kf6-kglobalaccel" "recipes/kde/kf6-kglobalaccel"
symlink "../../local/recipes/kde/kf6-kservice" "recipes/kde/kf6-kservice"
symlink "../../local/recipes/kde/kf6-kpackage" "recipes/kde/kf6-kpackage"
symlink "../../local/recipes/kde/kf6-kiconthemes" "recipes/kde/kf6-kiconthemes"
symlink "../../local/recipes/kde/kf6-kxmlgui" "recipes/kde/kf6-kxmlgui"
symlink "../../local/recipes/kde/kf6-ktextwidgets" "recipes/kde/kf6-ktextwidgets"
symlink "../../local/recipes/kde/kf6-solid" "recipes/kde/kf6-solid"
symlink "../../local/recipes/kde/kf6-sonnet" "recipes/kde/kf6-sonnet"
symlink "../../local/recipes/kde/kf6-kio" "recipes/kde/kf6-kio"
symlink "../../local/recipes/kde/kf6-kbookmarks" "recipes/kde/kf6-kbookmarks"
symlink "../../local/recipes/kde/kf6-kcompletion" "recipes/kde/kf6-kcompletion"
symlink "../../local/recipes/kde/kf6-kdeclarative" "recipes/kde/kf6-kdeclarative"
symlink "../../local/recipes/kde/kf6-kcmutils" "recipes/kde/kf6-kcmutils"
symlink "../../local/recipes/kde/kf6-kidletime" "recipes/kde/kf6-kidletime"
symlink "../../local/recipes/kde/kf6-kwayland" "recipes/kde/kf6-kwayland"
symlink "../../local/recipes/kde/kf6-knewstuff" "recipes/kde/kf6-knewstuff"
symlink "../../local/recipes/kde/kf6-kwallet" "recipes/kde/kf6-kwallet"
symlink "../../local/recipes/kde/kf6-prison" "recipes/kde/kf6-prison"
symlink "../../local/recipes/kde/breeze" "recipes/kde/breeze"
symlink "../../local/recipes/kde/kde-cli-tools" "recipes/kde/kde-cli-tools"
symlink "../../local/recipes/kde/kdecoration" "recipes/kde/kdecoration"
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kirigami"
symlink "../../local/recipes/kde/kwin" "recipes/kde/kwin"
symlink "../../local/recipes/kde/plasma-desktop" "recipes/kde/plasma-desktop"
symlink "../../local/recipes/kde/plasma-framework" "recipes/kde/plasma-framework"
symlink "../../local/recipes/kde/plasma-workspace" "recipes/kde/plasma-workspace"
symlink "../../local/recipes/kde/plasma-wayland-protocols" "recipes/kde/plasma-wayland-protocols"
symlink "../../local/recipes/kde/kglobalacceld" "recipes/kde/kglobalacceld"
symlink "../../local/recipes/wayland/qt6-wayland-smoke" "recipes/wayland/qt6-wayland-smoke"
symlink "../../local/recipes/wayland/seatd-redox" "recipes/wayland/seatd-redox"
symlink "../../local/recipes/wayland/smallvil" "recipes/wayland/smallvil"
symlink "../../local/recipes/wayland/redbear-compositor" "recipes/wayland/redbear-compositor"
symlink "../../local/recipes/tests/redox-drm-prime-test" "recipes/tests/redox-drm-prime-test"
symlink "../../local/recipes/system/redbear-passwd" "recipes/system/redbear-passwd"
symlink "../../local/recipes/gpu/redox-drm" "recipes/gpu/redox-drm"
symlink "../../local/recipes/gpu/amdgpu" "recipes/gpu/amdgpu"
status "Custom recipe symlinks ready"
echo ""
section "Ensuring recipe patch symlinks..."
# Auto-discover patches from local/patches/<component>/ and create/refresh
# symlinks in the corresponding recipe directories. This replaces the
# previous hardcoded-per-patch approach which went stale whenever patches
# were reorganized (e.g. moved to absorbed/ subdirectories).
declare -A PATCH_COMPONENT_TO_RECIPE=(
[kernel]="recipes/core/kernel"
[base]="recipes/core/base"
[relibc]="recipes/core/relibc"
[bootloader]="recipes/core/bootloader"
[installer]="recipes/core/installer"
[userutils]="recipes/core/userutils"
)
linked=0
skipped=0
for component in "${!PATCH_COMPONENT_TO_RECIPE[@]}"; do
recipe_dir="${PATCH_COMPONENT_TO_RECIPE[$component]}"
[ -d "$recipe_dir" ] || continue
patch_dir="local/patches/${component}"
# Collect all .patch files from both the component dir and absorbed/ subdir.
find "$patch_dir" -maxdepth 2 -name "*.patch" -type f 2>/dev/null | while read patch_file; do
patch_name="$(basename "$patch_file")"
# Resolve the relative path from recipe dir to patch file.
# recipe_dir is e.g. recipes/core/base (2 levels deep)
# patch_file is e.g. local/patches/base/absorbed/P0-foo.patch
# We need to go up from recipe_dir to repo root, then into local/patches/...
# For recipes/core/base → ../../.. → repo root → local/patches/base/absorbed/...
# Number of directory components = slashes + 1
depth=$(($(echo "$recipe_dir" | tr -cd '/' | wc -c) + 1))
up=""
for ((i=0; i<depth; i++)); do up="${up}../"; done
rel_target="${up}${patch_file}"
link_path="${recipe_dir}/${patch_name}"
symlink "$rel_target" "$link_path"
done
done
status "Recipe patch symlinks ready"
echo ""
section "Validating Red Bear configs..."
declare -a redbear_configs=(
"config/redbear-mini.toml"
"config/redbear-full.toml"
"config/redbear-grub.toml"
)
declare -a found_configs=()
for config_path in "${redbear_configs[@]}"; do
if [ -f "$config_path" ] || [ -L "$config_path" ]; then
found_configs+=("${config_path#config/}")
fi
done
if [ "${#found_configs[@]}" -gt 0 ]; then
status "Found Red Bear target config(s): ${found_configs[*]}"
else
warn "No redbear target config found in config/"
fi
echo ""
section "Validating branding assets..."
icon_path="local/Assets/images/Red Bear OS icon.png"
background_path="local/Assets/images/Red Bear OS loading background.png"
missing_assets=0
if [ ! -f "$icon_path" ]; then
warn "Missing branding asset: $icon_path"
missing_assets=1
fi
if [ ! -f "$background_path" ]; then
warn "Missing branding asset: $background_path"
missing_assets=1
fi
if [ "$missing_assets" -eq 0 ]; then
status "Branding assets present"
fi
echo ""
section "Checking AMD firmware blobs..."
shopt -s nullglob
firmware_blobs=(local/firmware/amdgpu/*.bin)
shopt -u nullglob
if [ "${#firmware_blobs[@]}" -gt 0 ]; then
status "Found ${#firmware_blobs[@]} AMD firmware blob(s)"
else
warn "No AMD firmware blobs found in local/firmware/amdgpu/"
fi
echo ""
section "Staging branding assets into recipe source..."
stage_file "$icon_path" "local/recipes/branding/redbear-release/source/images/icon.png" "branding icon"
stage_file "$background_path" "local/recipes/branding/redbear-release/source/images/loading-background.png" "branding loading background"
echo ""
section "Staging firmware blobs into firmware-loader recipe source..."
require_real_parent_dirs "local/recipes/system/firmware-loader/source/firmware/amdgpu/.guard"
mkdir -p "local/recipes/system/firmware-loader/source/firmware/amdgpu"
shopt -s nullglob
staged_firmware=(local/recipes/system/firmware-loader/source/firmware/amdgpu/*.bin)
shopt -u nullglob
if [ "${#staged_firmware[@]}" -gt 0 ]; then
rm -f "${staged_firmware[@]}"
fi
if [ "${#firmware_blobs[@]}" -gt 0 ]; then
cp "${firmware_blobs[@]}" "local/recipes/system/firmware-loader/source/firmware/amdgpu/"
status "Staged ${#firmware_blobs[@]} AMD firmware blob(s)"
else
warn "Skipping firmware staging because no AMD firmware blobs were found"
fi
echo ""
section "Updating build tag..."
require_repo_relative_path "$REDBEAR_TAG"
case "$REDBEAR_TAG" in
build/*)
;;
*)
warn "Refusing tag path outside build/: $REDBEAR_TAG"
exit 1
;;
esac
require_real_parent_dirs "$REDBEAR_TAG"
mkdir -p "$(dirname "$REDBEAR_TAG")"
touch "$REDBEAR_TAG"
status "Updated tag file: $REDBEAR_TAG"
echo ""
status "Red Bear integration complete"
exit 0