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:
2026-04-12 19:05:00 +01:00
commit 50b731f1b7
3392 changed files with 98327 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env bash
# This script allow the user to copy a Rust backtrace from Red Bear OS
# and retrieve the symbols
usage()
{
echo "Usage: $0 -r recipe [ -e command_name ] [ -R ] [ -X | -6 | -A ] [[ -b backtracefile ] | [ addr1 ... ]]"
echo
echo "Print the backtrace contained in the backtracefile."
echo "Symbols are taken from the executable for the given recipe."
echo "If no backtracefile is given, decode the given addresses instead."
echo "This command must be run in the 'redox' directory."
echo
echo "-X for x86_64, -6 for i686, -A for aarch64 (x86_64 is the default)."
echo "To read from stdin, use '-b -'"
echo "The name of the executable must match what Cargo believes it to be."
echo "If the executalbe is named 'recipe_command', just use 'command' as the name."
echo "The debug version of the executable is used if available."
echo "The release version is used if no debug version exists."
echo "-R to force the use of the 'release' version of the executable."
echo "Make sure the executable is the one that produced the backtrace."
exit 1
}
ARCH="x86_64"
while getopts ":b:e:r:hRXA6" opt
do
case "$opt" in
X) ARCH="x86_64";;
A) ARCH="aarch64";;
6) ARCH="i686";;
b) INFILE="$OPTARG";;
e) COMMAND="$OPTARG";;
i) INST="$OPTARG";;
r) RECIPE_NAME="$OPTARG";;
R) RELEASE=true;;
h) usage;;
\?) echo "Unknown option -$OPTARG, try -h for help"; exit;;
:) echo "-$OPTARG requires a value"; exit;;
esac
done
shift $((OPTIND -1))
if [ -z "$RECIPE_NAME" ]
then
usage
fi
if [ -z "$INFILE" -a $# = 0 ]
then
usage
fi
# if no command name is given, assume it's the same as the recipe name
RECIPE_DIR="$(target/release/find_recipe $RECIPE_NAME)"
if [ -z "$COMMAND" ]
then
COMMAND="$RECIPE_NAME"
fi
# look for the debug version of the command
EXECUTABLE="$RECIPE_DIR"/target/"$ARCH"-unknown-redox/build/target/"$ARCH"-unknown-redox/debug/"$COMMAND"
# try the release version next
if [ ! -f "$EXECUTABLE" -o ! -z "$RELEASE" ]
then
EXECUTABLE="$RECIPE_DIR"/target/"$ARCH"-unknown-redox/build/target/"$ARCH"-unknown-redox/release/"$COMMAND"
fi
if [ $# -ne 0 ]
then
addr2line --demangle=rust --inlines --pretty-print --functions --exe="$EXECUTABLE" $@
else
sed '/^\s*$/d; s/^.*0x\([0-9a-f]*\).*$/\1/g' "$INFILE" | addr2line --demangle=rust --inlines --pretty-print --functions --exe="$EXECUTABLE"
fi
+10
View File
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
# This script runs "make f.recipe" and "cargo update" in the specified recipe
recipe_name="$1"
recipe_path=$(find recipes -name "$recipe_name" -maxdepth 4)
make f."$recipe_name"
cd "$recipe_path"/source
cargo update
+14
View File
@@ -0,0 +1,14 @@
#!/usr/bin/env bash
# This script run the recipe command options on some Cookbook category
if [ -z "$1" ] || [ -z "$2" ]
then
echo "Build or clean all recipe directories in a category" >&2
echo Usage: $0 "<action>" "<recipe-category>" >&2
echo "<action>" can be f, r, c, u, p, or combinations that \"make\" understands >&2
echo "<category>" can be path of category you want to run e.g. \"core\", \"wip\", \"wip/dev\" >&2
exit 1
fi
make "${1#-}"."--category-$2"
+80
View File
@@ -0,0 +1,80 @@
#!/usr/bin/env bash
# This script show the changelog of all Red Bear OS components
set -e
LAST_RELEASE_TAG="$(git describe --tags --abbrev=0)"
LAST_RELEASE_TIMESTAMP="$(git log --format="%ct" -1 "${LAST_RELEASE_TAG}")"
echo "Last release: ${LAST_RELEASE_TAG} at ${LAST_RELEASE_TIMESTAMP}"
REPOS=(
redox=.
cookbook=cookbook
rust=rust
)
if [ "$1" = "--summary" ]
then
summary=true
elif [ "$1" = "--mdlinks" ]
then
mdlinks=true
fi
for package in $(installer/target/release/redox_installer --list-packages -c config/$(uname -m)/desktop.toml)
do
package_source="$(target/release/find_recipe ${package})"
REPOS+=("${package}=${package_source}/source")
done
# TODO: resolve dependencies instead of manually adding these initfs packages
for package in init logd ramfs randd zerod
do
package_source="$(target/release/find_recipe ${package})"
REPOS+=("${package}=${package_source}/source")
done
for name_repo in "${REPOS[@]}"
do
name="$(echo "${name_repo}" | cut -d "=" -f 1)"
repo="$(echo "${name_repo}" | cut -d "=" -f 2-)"
if [ "${summary}" = true ]
then
echo
echo "### ${name}"
echo
elif [ "${mdlinks}" = true ]
then
echo -n "- [${name}]"
else
echo -en "\x1B[1m${name}:\x1B[0m "
fi
if [ -e "${repo}/.git" ]
then
remote="$(git -C "${repo}" remote get-url origin)"
website="${remote%.*}"
before="$(git -C "${repo}" log --until="${LAST_RELEASE_TIMESTAMP}" --format="%h" -1)"
after="$(git -C "${repo}" log --since="${LAST_RELEASE_TIMESTAMP}" --format="%h" -1)"
if [ -z "${before}" ]
then
echo "New repository at ${website}"
elif [ -z "${after}" ]
then
echo "No changes"
else
if [ "${summary}" = true ]
then
git -C "${repo}" log ${before}...${after} --oneline
elif [ "${mdlinks}" = true ]
then
echo "(${website}/-/compare/${before}...${after})"
else
echo "${website}/-/compare/${before}...${after}"
fi
fi
else
echo "Not a git repository"
fi
done
+36
View File
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e
if [ -n "$1" ]
then
ARCH="$1"
else
ARCH="x86_64"
fi
make build/fstools
declare -A packages
for recipe_dir in $(build/fstools/bin/list_recipes | grep -v '^recipes/wip/')
do
recipe_name="$(basename "${recipe_dir}")"
packages["${recipe_name}"]="${recipe_dir}"
done
config="config/${ARCH}/ci.toml"
for package in $(build/fstools/bin/redox_installer --list-packages -c "${config}")
do
packages["${package}"]=""
done
echo "Checking for missing packages in ${config}"
printf '%-32s%s\n' "PACKAGE" "RECIPE"
for package in "${!packages[@]}"
do
recipe_dir="${packages["${package}"]}"
if [ -n "${recipe_dir}" ]
then
printf '%-32s%s\n' "${package}" "${recipe_dir}"
fi
done | sort
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# This script shows the current Git commit hash of system recipes at recipes/core
set -e
# Check if recipes/core directory exists
if [ ! -d "recipes/core" ]
then
echo "Error: recipes/core directory not found"
exit 1
fi
# Iterate through all system recipes in recipes/core
for recipe_dir in recipes/core/*/
do
recipe_name=$(basename "$recipe_dir")
source_dir="$recipe_dir/source"
# Check if source directory exists and is a git repository
if [ -d "$source_dir" ] && [ -d "$source_dir/.git" ]
then
# Get the commit hash
commit_hash=$(cd "$source_dir" && git rev-parse HEAD)
echo "$recipe_name: $commit_hash"
fi
done
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# This script install Red Bear OS in the free space of your storage device
# and add a boot entry (if you are using the systemd-boot boot loader)
set -e
if [ -n "$1" ]
then
DISK="$1"
else
DISK=/dev/disk/by-partlabel/RBOS_INSTALL
fi
if [ ! -b "${DISK}" ]
then
echo "$0: '${DISK}' is not a block device" >&2
exit 1
fi
eval $(make setenv)
IMAGE="${BUILD}/filesystem.img"
set -x
rm -f "${IMAGE}"
make "${IMAGE}"
sudo popsicle "${IMAGE}" "${DISK}"
set +x
ESP="$(bootctl --print-esp-path)"
if [ -z "${ESP}" ]
then
echo "$0: no ESP found" >&2
exit 1
fi
BOOTLOADER="recipes/core/bootloader/target/${ARCH}-unknown-redox/stage/usr/lib/boot/bootloader.efi"
set -x
sudo mkdir -pv "${ESP}/EFI" "${ESP}/loader/entries"
sudo cp -v "${BOOTLOADER}" "${ESP}/EFI/rbos.efi"
sudo tee "${ESP}/loader/entries/rbos.conf" <<EOF
title Red Bear OS
efi /EFI/rbos.efi
EOF
set +x
sync
echo "Finished installing Red Bear OS dual boot"
echo ""
echo "To mount the RBOS filesystem partition, run:"
echo " ./scripts/mount-redoxfs.sh ${DISK}"
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# This script print all recipe executable names to find duplicates and verify executable name conflicts
usage() {
echo "List executable names to find duplicates"
echo "Usage: $0 [-h] [-a] [-arm64 | -i686] [recipes]"
echo "Default architecture is x86_64, -arm64 is aarch64, -i686 is i686"
echo "Only duplicates are listed unless -a is specified"
echo "-h is this message"
exit
}
recipes=""
target="x86_64-unknown-redox"
uniq="uniq -D --skip-fields=1"
for arg in "${@:1}"
do
if [ "$arg" == "-arm64" ]
then
target="aarch64-unknown-redox"
elif [ "$arg" == "-i686" ]
then
target="i686-unknown-redox"
elif [ "$arg" == "-a" ]
then
uniq="cat"
elif [ "$arg" == "-h" ]
then
usage
else
recipes+=" $arg"
fi
done
if [ -z "$recipes" ]
then
recipes="$(target/release/list_recipes)"
fi
for recipe in $recipes
do
if [[ "$recipe" == *\/* ]]
then
recipe_name="$(basename $recipe)"
recipe_path="recipes/$recipe"
else
recipe_name="$recipe"
recipe_path="$(target/release/find_recipe $recipe_name)"
fi
for command in $(find "$recipe_path/target/$target/stage/usr/bin" -type f 2> /dev/null) \
$(find "$recipe_path/target/$target/stage/bin" -type f 2> /dev/null)
do
shortname="$(basename $command)"
echo "$recipe_path $shortname"
done
done | sort | $uniq
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# This script show all files installed by a recipe
# Ensure arch and config are set as desired, we use these to find the build dir
export ARCH=$(uname -m)
export CONFIG_NAME=desktop
# Make sure to unmount the image first
make unmount &>/dev/null || true
# Mount the image
make mount >/dev/null
# Find all files
find "build/${ARCH}/${CONFIG_NAME}/" -type f | cut -d / -f5- |\
sort |\
uniq |\
while read path
do
# Skip empty paths
if [ -z "${path}" ]
then
continue
fi
# Find all packages providing this file
pkgs="$(
find recipes/*"/target/${ARCH}-unknown-redox/stage/${path}" 2>/dev/null |
cut -d/ -f3 |
tr '\n' ' ' |
sort |
uniq
)"
if [ -n "${pkgs}" ]
then
echo "$path: ${pkgs}"
else
echo "$path: no packages, see config/${ARCH}/${CONFIG_NAME}.toml"
fi
done
# Make sure to unmount the image
make unmount &>/dev/null || true
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# This script create a list with:
# "recipe-name = {} #TODO"
# For quick testing of WIP recipes
# Given a string, find recipe.toml files containing that string.
# Create a list that can be copy/pasted into a filesystem config.
if [ -z "$*" ]
then
echo "Find matching recipes, and format for inclusion in config"
echo "Usage: $0 \"pattern\""
echo "Must be run from the RBOS build directory"
echo "e.g. $0 \"TODO.*error\""
exit 1
fi
cookbook_recipes="recipes"
recipe_paths=$(grep -rl "$*" "$cookbook_recipes" --include recipe.toml)
for recipe_path in $recipe_paths
do
recipe_dir="$(dirname $recipe_path)"
recipe_name="$(basename $recipe_dir)"
echo "$recipe_name = {} # " $(grep "$*" $recipe_path)
done
+119
View File
@@ -0,0 +1,119 @@
#!/usr/bin/env bash
set -e
MOUNT_POINT="/mnt/rbos"
DISK_DEVICE=""
show_help() {
echo "Usage: $0 [options] <device>"
echo ""
echo "Mount or unmount a Red Bear OS filesystem partition"
echo ""
echo "Options:"
echo " -u, --unmount Unmount the RBOS filesystem partition"
echo " -m, --mount-point PATH Custom mount point (default: /mnt/rbos)"
echo " -h, --help Show this help"
echo ""
echo "Examples:"
echo " $0 /dev/sda3 Mount /dev/sda3"
echo " $0 -u Unmount from default location"
echo " $0 -m /mnt/my-rbos /dev/sda3 Mount to custom location"
}
unmount_fs() {
if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then
echo "Unmounting RBOS filesystem from $MOUNT_POINT..."
fusermount -u "$MOUNT_POINT" || fusermount3 -u "$MOUNT_POINT"
echo "Successfully unmounted"
else
echo "Nothing mounted at $MOUNT_POINT"
fi
exit 0
}
check_dependencies() {
# Try to find redoxfs in multiple locations
REDOXFS_BIN=""
if [ -x "build/fstools/bin/redoxfs" ]; then
REDOXFS_BIN="build/fstools/bin/redoxfs"
elif [ -x "$(dirname "$0")/../build/fstools/bin/redoxfs" ]; then
REDOXFS_BIN="$(dirname "$0")/../build/fstools/bin/redoxfs"
elif command -v redoxfs &> /dev/null; then
REDOXFS_BIN="redoxfs"
fi
if [ -z "$REDOXFS_BIN" ]; then
echo "Error: redoxfs command not found"
echo "Please build it first with: make fstools"
exit 1
fi
if ! ldconfig -p 2>/dev/null | grep -q "libfuse3"; then
echo "Error: libfuse 3.x is not installed"
echo "Please install it:"
if command -v apt-get &> /dev/null; then
echo " sudo apt-get install fuse3 libfuse3-dev"
elif command -v dnf &> /dev/null; then
echo " sudo dnf install fuse3-devel"
elif command -v pacman &> /dev/null; then
echo " sudo pacman -S fuse3"
else
echo " (check your package manager for fuse3)"
fi
exit 1
fi
}
UNMOUNT=false
while [[ $# -gt 0 ]]; do
case $1 in
-u|--unmount)
UNMOUNT=true
shift
;;
-m|--mount-point)
MOUNT_POINT="$2"
shift 2
;;
-h|--help)
show_help
exit 0
;;
*)
DISK_DEVICE="$1"
shift
;;
esac
done
if [ "$UNMOUNT" = true ]; then
unmount_fs
fi
if [ -z "$DISK_DEVICE" ]; then
DISK_DEVICE="/dev/disk/by-partlabel/RBOS_INSTALL"
if [ ! -b "$DISK_DEVICE" ]; then
echo "Error: No device specified and default partition not found"
echo ""
show_help
exit 1
fi
fi
if [ ! -b "$DISK_DEVICE" ] && [ ! -f "$DISK_DEVICE" ]; then
echo "Error: $DISK_DEVICE is not a block device or file"
exit 1
fi
check_dependencies
mkdir -p "$MOUNT_POINT"
echo "Mounting $DISK_DEVICE to $MOUNT_POINT..."
"$REDOXFS_BIN" "$DISK_DEVICE" "$MOUNT_POINT"
echo "RBOS filesystem successfully mounted at $MOUNT_POINT"
echo "To unmount, run: $0 -u"
+52
View File
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Your host must use the static IP ${NETWORK}.1 and subnet mask 255.255.255.0
# 'Rx' in ascii is 82 and 120, adjust to taste
NETWORK=10.82.120
set -ex
trap 'kill -HUP 0' EXIT
eval $(make setenv)
make "${BUILD}/rbos-live.iso"
echo "Allowing packet forwarding"
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
iface="$(route | grep '^default ' | grep -o '[^ ]*$' | head -n 1)"
echo "Forwarding packets to '$iface'"
if ! sudo iptables -t nat -C POSTROUTING -o "$iface" -j MASQUERADE
then
echo "Forwarding rule does not exist, adding"
sudo iptables -t nat -A POSTROUTING -o "$iface" -j MASQUERADE
else
echo "Forwarding rule already exists"
fi
ARGS=(
"--no-daemon"
"--bind-interfaces"
"--listen-address=${NETWORK}.1"
"--port=0"
"--dhcp-range=${NETWORK}.3,${NETWORK}.254,255.255.255.0,1h"
"--dhcp-option=6,1.1.1.1,1.0.0.1"
"--enable-tftp"
"--tftp-root=$(realpath "${BUILD}")"
# BIOS
"--dhcp-match=set:bios,option:client-arch,0"
"--dhcp-boot=tag:!ipxe,tag:bios,undionly.kpxe"
# EFI x86_64
"--dhcp-match=set:efi-x86_64,option:client-arch,7"
"--dhcp-match=set:efi-x86_64,option:client-arch,9"
"--dhcp-boot=tag:!ipxe,tag:efi-x86_64,ipxe-x86_64.efi"
# EFI aarch64
"--dhcp-match=set:efi-aarch64,option:client-arch,11"
"--dhcp-boot=tag:!ipxe,tag:efi-aarch64,ipxe-aarch64.efi"
# IPXE
"--dhcp-userclass=set:ipxe,iPXE"
"--dhcp-boot=tag:ipxe,rbos.ipxe"
)
sudo dnsmasq "${ARGS[@]}"&
python3 -m http.server -b "${NETWORK}.1" -d "${BUILD}" "8080"
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# This script show the package size of the recipes ("stage.pkgar" and "stage.tar.gz")
# It must be used by package maintainers to enforce the library linking size policy
if [ $# = 0 ]
then
find recipes \( -name stage.pkgar -o -name stage.tar.gz \) -exec ls -hs {} \;
exit 0
fi
for recipe in $@
do
if [ "$recipe" = "-h" ] || [ "$recipe" = "--help" ]
then
echo "Usage: $0 [recipe] ..."
echo " For the recipe(s), prints the size of 'stage.pkgar' and 'stage.tar.gz'."
echo " If no recipe is given, then all packages are listed."
exit 0
fi
recipe_paths=$(find recipes -name $recipe)
for recipe_path in $recipe_paths
do
if [ -f "$recipe_path/recipe.toml" ] || [ -f "$recipe_path/recipe.sh" ]
then
find "$recipe_path" \( -name stage.pkgar -o -name stage.tar.gz \) -exec ls -hs {} \;
fi
done
done
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# This script print the recipe configuration
cat $(target/release/find_recipe "$1")/recipe.*
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# This script print the recipe configuration files with determined text
bat --decorations=always $(rg "$1" -li --sort=path recipes)
+8
View File
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
FIND_RECIPE="find recipes -maxdepth 4 -name"
for recipe in $*
do
${FIND_RECIPE} "${recipe}"
done
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# This script show the contents of the "stage" and "sysroot" folders in some recipe
if [ -z "$*" ]
then
echo "Show the contents of the stage and sysroot folders in recipe(s)"
echo "Usage: $0 recipe1 ..."
echo "Must be run from the RBOS build directory"
echo "e.g. $0 kernel"
exit 1
fi
find_recipe="target/release/find_recipe"
if [ ! -x "$find_recipe" ]
then
echo "$find_recipe not found."
echo "Please run 'make fstools' and try again."
exit 1
fi
for recipe in $*
do
recipe_dir="$("$find_recipe" "$recipe")"
ls -1 "$recipe_dir/target"/*/{stage,sysroot}
done
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# This script create and copy the Red Bear OS bootable image to an Ventoy-formatted device
set -e
ARCHS=(
i686
x86_64
)
CONFIGS=(
demo
desktop
)
VENTOY="/media/${USER}/Ventoy"
if [ ! -d "${VENTOY}" ]
then
echo "Ventoy not mounted" >&2
exit 1
fi
for ARCH in "${ARCHS[@]}"
do
for CONFIG_NAME in "${CONFIGS[@]}"
do
IMAGE="build/${ARCH}/${CONFIG_NAME}/rbos-live.iso"
make ARCH="${ARCH}" CONFIG_NAME="${CONFIG_NAME}" "${IMAGE}"
cp -v "${IMAGE}" "${VENTOY}/rbos-${CONFIG_NAME}-${ARCH}.iso"
done
done
sync
echo "Finished copying configs (${CONFIGS[@]}) for archs (${ARCHS[@]})"