Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9db9c3bdc9 | |||
| 845ae99f9d | |||
| 5c5f853192 | |||
| ece9837d15 | |||
| d26675708e | |||
| 2d11c98428 | |||
| 5c127bf6f4 | |||
| a0244075e7 | |||
| 2b11b20a2f | |||
| cb50169517 | |||
| 328d1abbcd |
@@ -457,6 +457,49 @@ See `local/docs/BUILD-SYSTEM-HARDENING-PLAN.md` for the full plan.
|
|||||||
- **DO NOT** skip warnings — investigate, diagnose, and fix the root cause; suppressing or ignoring warnings is not acceptable when a fix is feasible
|
- **DO NOT** skip warnings — investigate, diagnose, and fix the root cause; suppressing or ignoring warnings is not acceptable when a fix is feasible
|
||||||
- **DO NOT** remove patches from `recipe.toml` to fix build failures — rebase the patch instead (see `local/docs/PATCH-GOVERNANCE.md`)
|
- **DO NOT** remove patches from `recipe.toml` to fix build failures — rebase the patch instead (see `local/docs/PATCH-GOVERNANCE.md`)
|
||||||
- **DO NOT** remove BINS entries to fix build failures — fix the source or use EXISTING_BINS filtering
|
- **DO NOT** remove BINS entries to fix build failures — fix the source or use EXISTING_BINS filtering
|
||||||
|
- **DO NOT** use the VESA display driver (`vesad`) as the primary display surface after GPU detection. vesad is only for early-boot framebuffer handoff — after redox-drm loads, the display path is `/scheme/drm/card0`. See **NO VESA POLICY** below.
|
||||||
|
|
||||||
|
## NO VESA POLICY
|
||||||
|
|
||||||
|
Red Bear OS does not use the VESA display driver as the primary display surface. All display
|
||||||
|
output goes through the DRM/KMS path via real GPU drivers:
|
||||||
|
|
||||||
|
| Environment | GPU Driver | 3D Support |
|
||||||
|
|---|---|---|
|
||||||
|
| QEMU | virtio-gpu (via redox-drm) | ✅ virgl |
|
||||||
|
| Intel hardware | Intel i915-like (via redox-drm) | ✅ Mesa i965/iris |
|
||||||
|
| AMD hardware | amdgpu (via redox-drm + linux-kpi) | ✅ Mesa radeonsi |
|
||||||
|
| Future | nouveau reimplementation (Rust, via redox-drm) | ✅ Mesa nouveau |
|
||||||
|
|
||||||
|
**vesad is allowed ONLY as an early-boot framebuffer handoff.** The bootloader sets up a linear
|
||||||
|
framebuffer before the kernel starts. vesad takes over this framebuffer so the initfs has console
|
||||||
|
output (fbcond, fbbootlogd) before real GPU drivers are available. Once redox-drm initializes and
|
||||||
|
registers `scheme:drm/card0`, vesad must hand off and NOT register `scheme:display.vesa` as the
|
||||||
|
primary display surface.
|
||||||
|
|
||||||
|
The display path for redbear-full:
|
||||||
|
|
||||||
|
```
|
||||||
|
Bootloader linear framebuffer
|
||||||
|
→ vesad (initfs, service 20): temporary FB handoff for text console
|
||||||
|
→ redox-drm (initfs, service 30): detects GPU hardware, takes over via DRM/KMS
|
||||||
|
→ redox-drm (rootfs, service 14): full DRM driver with 3D (Mesa)
|
||||||
|
→ KWin compositor: DRM/KMS master, composites desktop via /scheme/drm/card0
|
||||||
|
```
|
||||||
|
|
||||||
|
For redbear-mini: vesad handles the bootloader framebuffer for the text-only console. No GPU
|
||||||
|
driver loads — mini is text-only by design.
|
||||||
|
|
||||||
|
**After GPU detection, any code that opens `/scheme/display.vesa/` is incorrect.** The correct
|
||||||
|
display path is `/scheme/drm/card0` via the DRM scheme.
|
||||||
|
|
||||||
|
Rationale: VESA is a legacy BIOS-era standard with no hardware acceleration, no mode setting
|
||||||
|
beyond what the bootloader provides, no 3D, and no future. Red Bear OS targets real GPU
|
||||||
|
hardware with full DRM/KMS and Mesa support. vesad serves only as a bridge between bootloader
|
||||||
|
FB and the real GPU driver — it is never the final display path.
|
||||||
|
|
||||||
|
This policy also covers future GPU driver work: any new GPU support (nouveau Rust reimplementation,
|
||||||
|
ARM Mali, etc.) must go through the redox-drm + DRM/KMS path, never through VESA fallback.
|
||||||
|
|
||||||
## ZERO TOLERANCE FOR STUBS
|
## ZERO TOLERANCE FOR STUBS
|
||||||
|
|
||||||
|
|||||||
@@ -231,3 +231,5 @@ packages-sync: ; @bash local/scripts/sync-packages.sh
|
|||||||
packages-list: ; @ls -la Packages/*.pkgar 2>/dev/null | wc -l && echo "pkgar files in Packages/"
|
packages-list: ; @ls -la Packages/*.pkgar 2>/dev/null | wc -l && echo "pkgar files in Packages/"
|
||||||
validate-patches:
|
validate-patches:
|
||||||
@bash local/scripts/validate-patches.sh
|
@bash local/scripts/validate-patches.sh
|
||||||
|
cascade.%: FORCE
|
||||||
|
@bash local/scripts/rebuild-cascade.sh $(basename $(subst cascade,, $*))
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# Protected recipes — these recipes are NEVER re-fetched from upstream.
|
||||||
|
# They use offline/archived sources from sources/redbear-<release>/.
|
||||||
|
#
|
||||||
|
# Protection reasons:
|
||||||
|
# - patched: carries Red Bear patches (upstream changes could break patches)
|
||||||
|
# - custom: Red Bear-specific recipe (no upstream equivalent)
|
||||||
|
# - core: core system component (kernel, libc, bootloader, etc.)
|
||||||
|
#
|
||||||
|
# The Rust code in src/cook/fetch.rs reads this file at startup.
|
||||||
|
# Recipes NOT listed here but carrying patches (patches = [...] in recipe.toml)
|
||||||
|
# are automatically protected by the recipe_has_patches() check.
|
||||||
|
|
||||||
|
# Core patched recipes (upstream + Red Bear patches)
|
||||||
|
[patched]
|
||||||
|
recipes = [
|
||||||
|
"relibc", "bootloader", "kernel", "base", "base-initfs",
|
||||||
|
"installer", "redoxfs", "grub",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear custom core recipes
|
||||||
|
[custom]
|
||||||
|
recipes = [
|
||||||
|
"ext4d", "fatd",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear driver infrastructure
|
||||||
|
[drivers]
|
||||||
|
recipes = [
|
||||||
|
"redox-driver-sys", "linux-kpi", "firmware-loader",
|
||||||
|
"redbear-btusb", "redbear-iwlwifi",
|
||||||
|
"redox-drm", "amdgpu",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear system tools
|
||||||
|
[system]
|
||||||
|
recipes = [
|
||||||
|
"cub", "evdevd", "udev-shim", "iommu",
|
||||||
|
"redbear-firmware", "redbear-hwutils", "redbear-info", "rbos-info",
|
||||||
|
"redbear-meta", "redbear-netctl", "redbear-netctl-console",
|
||||||
|
"redbear-netstat", "redbear-btctl", "redbear-wifictl",
|
||||||
|
"redbear-traceroute", "redbear-mtr", "redbear-nmap",
|
||||||
|
"redbear-sessiond", "redbear-authd", "redbear-session-launch",
|
||||||
|
"redbear-greeter", "redbear-dbus-services", "redbear-notifications",
|
||||||
|
"redbear-upower", "redbear-udisks", "redbear-polkit", "redbear-quirks",
|
||||||
|
"redbear-release", "redbear-keymapd", "redbear-ime", "redbear-accessibility",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Qt stack with Red Bear patches
|
||||||
|
[qt]
|
||||||
|
recipes = [
|
||||||
|
"qtbase", "qtwayland", "qtdeclarative", "qtbase-compat",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Graphics / display stack with Red Bear patches
|
||||||
|
[graphics]
|
||||||
|
recipes = [
|
||||||
|
"libdrm", "mesa",
|
||||||
|
"libwayland", "libevdev", "libinput",
|
||||||
|
"dbus", "glib",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear library stubs and custom libs
|
||||||
|
[libs]
|
||||||
|
recipes = [
|
||||||
|
"libepoxy-stub", "libdisplay-info-stub", "lcms2-stub",
|
||||||
|
"libxcvt-stub", "libudev-stub", "zbus", "libqrencode",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear Wayland
|
||||||
|
[wayland]
|
||||||
|
recipes = [
|
||||||
|
"qt6-wayland-smoke", "smallvil", "seatd-redox",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Red Bear KDE (47 recipes)
|
||||||
|
[kde]
|
||||||
|
recipes = [
|
||||||
|
"kf6-extra-cmake-modules", "kf6-kcoreaddons", "kf6-kwidgetsaddons",
|
||||||
|
"kf6-kconfig", "kf6-ki18n", "kf6-kcodecs", "kf6-kguiaddons",
|
||||||
|
"kf6-kcolorscheme", "kf6-kauth", "kf6-kitemmodels", "kf6-kitemviews",
|
||||||
|
"kf6-karchive", "kf6-kwindowsystem", "kf6-knotifications",
|
||||||
|
"kf6-kjobwidgets", "kf6-kconfigwidgets", "kf6-kcrash", "kf6-kdbusaddons",
|
||||||
|
"kf6-kglobalaccel", "kf6-kservice", "kf6-kpackage", "kf6-kiconthemes",
|
||||||
|
"kf6-kxmlgui", "kf6-ktextwidgets", "kf6-solid", "kf6-sonnet",
|
||||||
|
"kf6-kio", "kf6-kbookmarks", "kf6-kcompletion", "kf6-kdeclarative",
|
||||||
|
"kf6-kcmutils", "kf6-kidletime", "kf6-kwayland", "kf6-knewstuff",
|
||||||
|
"kf6-kwallet", "kf6-prison", "kf6-kirigami",
|
||||||
|
"kf6-ksvg", "kf6-pty", "kf6-notifyconfig", "kf6-parts",
|
||||||
|
"kdecoration", "kwin", "plasma-desktop", "plasma-workspace",
|
||||||
|
"plasma-framework", "plasma-wayland-protocols", "kirigami",
|
||||||
|
"kglobalacceld",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Orbutils (has local patch)
|
||||||
|
[other]
|
||||||
|
recipes = [
|
||||||
|
"orbutils",
|
||||||
|
]
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
# The current slice is explicit-startup, USB-attached, BLE-first, and intentionally not wired to
|
# The current slice is explicit-startup, USB-attached, BLE-first, and intentionally not wired to
|
||||||
# USB-class autospawn yet.
|
# USB-class autospawn yet.
|
||||||
|
|
||||||
include = ["redbear-minimal.toml", "redbear-bluetooth-services.toml"]
|
include = ["redbear-mini.toml", "redbear-bluetooth-services.toml"]
|
||||||
|
|
||||||
[general]
|
[general]
|
||||||
filesystem_size = 2048
|
filesystem_size = 2048
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ requires_weak = ["04_drivers.target"]
|
|||||||
|
|
||||||
[service]
|
[service]
|
||||||
cmd = "/usr/bin/coretempd"
|
cmd = "/usr/bin/coretempd"
|
||||||
type = { scheme = "coretemp" }
|
type = "oneshot_async"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
|
|||||||
+103
-22
@@ -6,18 +6,25 @@
|
|||||||
#
|
#
|
||||||
# Extends redbear-mini with the full desktop/graphics stack:
|
# Extends redbear-mini with the full desktop/graphics stack:
|
||||||
# Wayland, Qt6, KF6, KWin, Mesa, DRM drivers, firmware, greeter.
|
# Wayland, Qt6, KF6, KWin, Mesa, DRM drivers, firmware, greeter.
|
||||||
|
#
|
||||||
|
# GPU/display policy: DRM/KMS ONLY. No VESA. Real GPU drivers:
|
||||||
|
# QEMU → virtio-gpu via redox-drm (virgl 3D)
|
||||||
|
# Intel → i915-like via redox-drm (Mesa i965/iris)
|
||||||
|
# AMD → amdgpu via redox-drm + linux-kpi (Mesa radeonsi)
|
||||||
|
# Display path: bootloader FB → redox-drm → DRM/KMS → KWin compositor
|
||||||
|
# Consult local/reference/linux-7.0/ for driver behavior reference.
|
||||||
|
|
||||||
include = ["redbear-mini.toml"]
|
include = ["redbear-mini.toml"]
|
||||||
|
|
||||||
[general]
|
[general]
|
||||||
filesystem_size = 4096
|
filesystem_size = 2048
|
||||||
|
|
||||||
[users.messagebus]
|
[users.messagebus]
|
||||||
uid = 100
|
uid = 100
|
||||||
gid = 100
|
gid = 100
|
||||||
name = "messagebus"
|
name = "messagebus"
|
||||||
home = "/nonexistent"
|
home = "/nonexistent"
|
||||||
shell = "/usr/bin/zsh"
|
shell = "/usr/bin/false"
|
||||||
|
|
||||||
[users.root]
|
[users.root]
|
||||||
password = "password"
|
password = "password"
|
||||||
@@ -25,6 +32,14 @@ uid = 0
|
|||||||
gid = 0
|
gid = 0
|
||||||
shell = "/usr/bin/zsh"
|
shell = "/usr/bin/zsh"
|
||||||
|
|
||||||
|
[users.user]
|
||||||
|
password = ""
|
||||||
|
uid = 1000
|
||||||
|
gid = 1000
|
||||||
|
name = "user"
|
||||||
|
home = "/home/user"
|
||||||
|
shell = "/usr/bin/zsh"
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
# Runtime driver parameter control surface.
|
# Runtime driver parameter control surface.
|
||||||
driver-params = {}
|
driver-params = {}
|
||||||
@@ -57,7 +72,7 @@ fontconfig = {}
|
|||||||
libwayland = {}
|
libwayland = {}
|
||||||
wayland-protocols = {}
|
wayland-protocols = {}
|
||||||
plasma-wayland-protocols = {}
|
plasma-wayland-protocols = {}
|
||||||
redbear-compositor = "ignore" # replaced by kwin
|
redbear-compositor = {}
|
||||||
|
|
||||||
# Keyboard/input
|
# Keyboard/input
|
||||||
libxkbcommon = {}
|
libxkbcommon = {}
|
||||||
@@ -138,6 +153,7 @@ redbear-authd = {}
|
|||||||
redbear-session-launch = {}
|
redbear-session-launch = {}
|
||||||
seatd = {}
|
seatd = {}
|
||||||
redbear-greeter = {}
|
redbear-greeter = {}
|
||||||
|
sddm = {}
|
||||||
amdgpu = {}
|
amdgpu = {}
|
||||||
|
|
||||||
# Core Red Bear umbrella package
|
# Core Red Bear umbrella package
|
||||||
@@ -146,12 +162,10 @@ redbear-meta = {}
|
|||||||
# Phase 1 runtime validation tests (POSIX: signalfd, timerfd, eventfd, shm_open, sem_open, waitid)
|
# Phase 1 runtime validation tests (POSIX: signalfd, timerfd, eventfd, shm_open, sem_open, waitid)
|
||||||
relibc-phase1-tests = {}
|
relibc-phase1-tests = {}
|
||||||
|
|
||||||
# Native build toolchain (Phase 3: GCC + binutils running on redox)
|
# Native build toolchain — excluded from desktop ISO to reduce size.
|
||||||
# Produces gcc/g++/as/ld that execute inside Red Bear OS
|
# For on-OS development, build redbear-dev config or install separately.
|
||||||
gcc-native = {}
|
# gcc-native = {}
|
||||||
binutils-native = {}
|
# binutils-native = {}
|
||||||
# llvm-native = {} # suppressed: Redox C++/pthread header gaps; not needed for greeter proof
|
|
||||||
# rust-native = {} # suppressed: depends on llvm-native; not needed for greeter proof
|
|
||||||
|
|
||||||
# Desktop fonts and icons
|
# Desktop fonts and icons
|
||||||
dejavu = {}
|
dejavu = {}
|
||||||
@@ -199,6 +213,15 @@ depends_on = ["pci"]
|
|||||||
|
|
||||||
[[driver.match]]
|
[[driver.match]]
|
||||||
class = 0x03
|
class = 0x03
|
||||||
|
vendor = 0x1002
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
class = 0x03
|
||||||
|
vendor = 0x8086
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
class = 0x03
|
||||||
|
vendor = 0x1af4
|
||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
@@ -223,7 +246,7 @@ data = """
|
|||||||
[unit]
|
[unit]
|
||||||
description = "Firmware loading scheme"
|
description = "Firmware loading scheme"
|
||||||
requires_weak = [
|
requires_weak = [
|
||||||
"00_base.target",
|
"05_boot-essential.target",
|
||||||
]
|
]
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
@@ -237,7 +260,7 @@ data = """
|
|||||||
[unit]
|
[unit]
|
||||||
description = "Boot essential services target"
|
description = "Boot essential services target"
|
||||||
requires_weak = [
|
requires_weak = [
|
||||||
"00_base.target",
|
"04_drivers.target",
|
||||||
]
|
]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -247,7 +270,7 @@ data = """
|
|||||||
[unit]
|
[unit]
|
||||||
description = "IOMMU DMA remapping daemon"
|
description = "IOMMU DMA remapping daemon"
|
||||||
requires_weak = [
|
requires_weak = [
|
||||||
"00_base.target",
|
"05_boot-essential.target",
|
||||||
]
|
]
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
@@ -256,12 +279,13 @@ type = "oneshot_async"
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/init.d/14_redox-drm.service"
|
path = "/etc/init.d/10_redox-drm.service"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
description = "DRM/KMS display driver (AMD + Intel + VirtIO)"
|
description = "DRM/KMS display driver (AMD + Intel + VirtIO)"
|
||||||
requires_weak = [
|
requires_weak = [
|
||||||
"05_boot-essential.target",
|
"05_boot-essential.target",
|
||||||
|
"00_driver-manager.service",
|
||||||
]
|
]
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
@@ -405,7 +429,7 @@ type = "oneshot_async"
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/init.d/19_redbear-authd.service"
|
path = "/etc/init.d/11_redbear-authd.service"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
description = "Red Bear authentication daemon"
|
description = "Red Bear authentication daemon"
|
||||||
@@ -420,22 +444,23 @@ type = "oneshot_async"
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/init.d/20_greeter.service"
|
path = "/etc/init.d/12_sddm.service"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
description = "Red Bear greeter service"
|
description = "SDDM display manager"
|
||||||
requires_weak = [
|
requires_weak = [
|
||||||
"00_driver-manager.service",
|
"00_driver-manager.service",
|
||||||
"14_redox-drm.service",
|
"10_redox-drm.service",
|
||||||
|
"10_evdevd.service",
|
||||||
"12_dbus.service",
|
"12_dbus.service",
|
||||||
"13_redbear-sessiond.service",
|
"13_redbear-sessiond.service",
|
||||||
"13_seatd.service",
|
"13_seatd.service",
|
||||||
"19_redbear-authd.service",
|
"11_redbear-authd.service",
|
||||||
]
|
]
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
cmd = "/usr/bin/redbear-greeterd"
|
cmd = "/usr/bin/sddm"
|
||||||
envs = { VT = "3", REDBEAR_GREETER_USER = "greeter", KWIN_DRM_DEVICES = "/scheme/drm/card0", REDBEAR_DRM_WAIT_SECONDS = "10" }
|
envs = { QT_PLUGIN_PATH = "/usr/plugins", QT_QPA_PLATFORM_PLUGIN_PATH = "/usr/plugins/platforms", QML2_IMPORT_PATH = "/usr/qml", XCURSOR_THEME = "Pop", XKB_CONFIG_ROOT = "/usr/share/X11/xkb" }
|
||||||
type = "oneshot_async"
|
type = "oneshot_async"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@@ -506,17 +531,73 @@ password = ""
|
|||||||
uid = 101
|
uid = 101
|
||||||
gid = 101
|
gid = 101
|
||||||
name = "greeter"
|
name = "greeter"
|
||||||
home = "/nonexistent"
|
home = "/var/lib/sddm"
|
||||||
shell = "/usr/bin/zsh"
|
shell = "/usr/bin/zsh"
|
||||||
|
|
||||||
|
[users.sddm]
|
||||||
|
password = ""
|
||||||
|
uid = 102
|
||||||
|
gid = 102
|
||||||
|
name = "sddm"
|
||||||
|
home = "/var/lib/sddm"
|
||||||
|
shell = "/usr/bin/nologin"
|
||||||
|
|
||||||
[groups.greeter]
|
[groups.greeter]
|
||||||
gid = 101
|
gid = 101
|
||||||
members = ["greeter"]
|
members = ["greeter", "sddm"]
|
||||||
|
|
||||||
|
[groups.sddm]
|
||||||
|
gid = 102
|
||||||
|
members = ["sddm"]
|
||||||
|
|
||||||
|
[groups.sudo]
|
||||||
|
gid = 1
|
||||||
|
members = ["user"]
|
||||||
|
|
||||||
|
[groups.user]
|
||||||
|
gid = 1000
|
||||||
|
members = ["user"]
|
||||||
|
|
||||||
[groups.messagebus]
|
[groups.messagebus]
|
||||||
gid = 100
|
gid = 100
|
||||||
members = ["messagebus"]
|
members = ["messagebus"]
|
||||||
|
|
||||||
|
[[files]]
|
||||||
|
path = "/etc/sddm.conf"
|
||||||
|
data = """
|
||||||
|
[General]
|
||||||
|
DisplayServer=wayland
|
||||||
|
GreeterEnvironment=QT_PLUGIN_PATH=/usr/plugins,QML2_IMPORT_PATH=/usr/qml,QT_QPA_PLATFORM_PLUGIN_PATH=/usr/plugins/platforms
|
||||||
|
|
||||||
|
[Theme]
|
||||||
|
Current=mayagrid
|
||||||
|
ThemeDir=/usr/share/sddm/themes
|
||||||
|
|
||||||
|
[Wayland]
|
||||||
|
CompositorCommand=/usr/libexec/sddm-helper-start-wayland kwin_wayland --drm /scheme/drm/card0
|
||||||
|
|
||||||
|
[Users]
|
||||||
|
DefaultPath=/usr/bin
|
||||||
|
MinimumUid=1000
|
||||||
|
MaximumUid=60000
|
||||||
|
RememberLastUser=true
|
||||||
|
|
||||||
|
[Autologin]
|
||||||
|
User=
|
||||||
|
Session=plasmawayland
|
||||||
|
"""
|
||||||
|
|
||||||
|
[[files]]
|
||||||
|
path = "/usr/share/wayland-sessions/plasmawayland.desktop"
|
||||||
|
data = """
|
||||||
|
[Desktop Entry]
|
||||||
|
Name=Plasma Wayland
|
||||||
|
Comment=KDE Plasma on Wayland
|
||||||
|
Exec=/usr/bin/kwin_wayland --drm /scheme/drm/card0
|
||||||
|
Type=Application
|
||||||
|
DesktopNames=KDE
|
||||||
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/pcid.d/ihdgd.toml"
|
path = "/etc/pcid.d/ihdgd.toml"
|
||||||
data = """
|
data = """
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
# Red Bear greeter/login service wiring
|
# DEPRECATED: This fragment is NO LONGER INCLUDED by any active config.
|
||||||
#
|
# All greeter/auth/session wiring is now inlined in redbear-full.toml.
|
||||||
# This fragment is intended to be included by the active desktop/graphics target.
|
# This file is retained for reference only. Do not include it in new configs.
|
||||||
|
# To add greeter services, edit redbear-full.toml directly.
|
||||||
|
|
||||||
[[files]]
|
# Original contents below (preserved for reference):
|
||||||
|
#[[files]]
|
||||||
path = "/etc/init.d/05_boot-essential.target"
|
path = "/etc/init.d/05_boot-essential.target"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
@@ -30,7 +32,7 @@ redbear-session-launch = {}
|
|||||||
redbear-greeter = {}
|
redbear-greeter = {}
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/init.d/19_redbear-authd.service"
|
path = "/etc/init.d/11_redbear-authd.service"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
description = "Red Bear authentication daemon"
|
description = "Red Bear authentication daemon"
|
||||||
@@ -61,7 +63,7 @@ type = "oneshot_async"
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/init.d/20_greeter.service"
|
path = "/etc/init.d/12_greeter.service"
|
||||||
data = """
|
data = """
|
||||||
[unit]
|
[unit]
|
||||||
description = "Red Bear greeter service (experimental — Phase 3 user session bring-up)"
|
description = "Red Bear greeter service (experimental — Phase 3 user session bring-up)"
|
||||||
@@ -70,7 +72,7 @@ requires_weak = [
|
|||||||
"12_dbus.service",
|
"12_dbus.service",
|
||||||
"13_redbear-sessiond.service",
|
"13_redbear-sessiond.service",
|
||||||
"13_seatd.service",
|
"13_seatd.service",
|
||||||
"19_redbear-authd.service",
|
"11_redbear-authd.service",
|
||||||
]
|
]
|
||||||
|
|
||||||
[service]
|
[service]
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ uid = 100
|
|||||||
gid = 100
|
gid = 100
|
||||||
name = "messagebus"
|
name = "messagebus"
|
||||||
home = "/nonexistent"
|
home = "/nonexistent"
|
||||||
shell = "/usr/bin/zsh"
|
shell = "/usr/bin/false"
|
||||||
|
|
||||||
[packages]
|
[packages]
|
||||||
# Red Bear OS branding and host utilities.
|
# Red Bear OS branding and host utilities.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Red Bear OS shared network profile wiring
|
# Red Bear OS shared network profile wiring
|
||||||
#
|
#
|
||||||
# Shared by redbear-minimal, redbear-desktop, redbear-full, and redbear-kde.
|
# Shared by redbear-mini, redbear-full, and other network-enabled configs.
|
||||||
|
|
||||||
[[files]]
|
[[files]]
|
||||||
path = "/etc/netctl"
|
path = "/etc/netctl"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
# to the bounded Wi-Fi path and adds the first Intel driver-side package on top of the shared
|
# to the bounded Wi-Fi path and adds the first Intel driver-side package on top of the shared
|
||||||
# firmware/control/profile tooling.
|
# firmware/control/profile tooling.
|
||||||
|
|
||||||
include = ["redbear-minimal.toml"]
|
include = ["redbear-mini.toml"]
|
||||||
|
|
||||||
[general]
|
[general]
|
||||||
filesystem_size = 2048
|
filesystem_size = 2048
|
||||||
|
|||||||
+1
-1
@@ -239,7 +239,7 @@ fi
|
|||||||
export XCURSOR_THEME="${XCURSOR_THEME:-Pop}"
|
export XCURSOR_THEME="${XCURSOR_THEME:-Pop}"
|
||||||
export XKB_CONFIG_ROOT="${XKB_CONFIG_ROOT:-/usr/share/X11/xkb}"
|
export XKB_CONFIG_ROOT="${XKB_CONFIG_ROOT:-/usr/share/X11/xkb}"
|
||||||
|
|
||||||
if [ -z "${KWIN_DRM_DEVICES:-}" ] && [ -e /scheme/drm/card0 ]; then
|
if [ -z "${KWIN_DRM_DEVICES:-}" ] && ( exec 3<"/scheme/drm/card0" && exec 3>&- ) >/dev/null 2>&1; then
|
||||||
export KWIN_DRM_DEVICES=/scheme/drm/card0
|
export KWIN_DRM_DEVICES=/scheme/drm/card0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+1
-3
@@ -21,8 +21,7 @@ current/canonical versus historical/reference split obvious.
|
|||||||
> **Red Bear note:** newer subsystem plans can also live under `local/docs/` when they are Red Bear-
|
> **Red Bear note:** newer subsystem plans can also live under `local/docs/` when they are Red Bear-
|
||||||
> specific rather than general Redox architecture material. In particular, see
|
> specific rather than general Redox architecture material. In particular, see
|
||||||
> `local/docs/WIFI-IMPLEMENTATION-PLAN.md` for the current Wi-Fi direction,
|
> `local/docs/WIFI-IMPLEMENTATION-PLAN.md` for the current Wi-Fi direction,
|
||||||
> `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the canonical desktop path,
|
> `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the canonical desktop path.
|
||||||
> and `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the canonical desktop path.
|
|
||||||
|
|
||||||
> **Repository model:** RedBearOS relates to Redox in the same way Ubuntu relates to Debian.
|
> **Repository model:** RedBearOS relates to Redox in the same way Ubuntu relates to Debian.
|
||||||
> Upstream Redox remains the base platform; Red Bear carries packaging, patch, validation, and
|
> Upstream Redox remains the base platform; Red Bear carries packaging, patch, validation, and
|
||||||
@@ -101,7 +100,6 @@ This summary is only a quick orientation layer. For canonical current-state deta
|
|||||||
- `docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md` for repository-wide execution order,
|
- `docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md` for repository-wide execution order,
|
||||||
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the canonical comprehensive plan,
|
- `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md` for the canonical comprehensive plan,
|
||||||
- `local/docs/PROFILE-MATRIX.md` for support-language by tracked profile,
|
- `local/docs/PROFILE-MATRIX.md` for support-language by tracked profile,
|
||||||
- `local/docs/PROFILE-MATRIX.md` for support-language by tracked profile,
|
|
||||||
- and the active subsystem plans under `local/docs/` for detailed current workstreams.
|
- and the active subsystem plans under `local/docs/` for detailed current workstreams.
|
||||||
|
|
||||||
- **Compile targets**: the supported compile targets are `redbear-mini`, `redbear-full`, and `redbear-grub`
|
- **Compile targets**: the supported compile targets are `redbear-mini`, `redbear-full`, and `redbear-grub`
|
||||||
|
|||||||
+3
-9
@@ -534,15 +534,10 @@ When mainline updates affect our work:
|
|||||||
- `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` is the current DRM-focused execution plan beneath
|
- `local/docs/DRM-MODERNIZATION-EXECUTION-PLAN.md` is the current DRM-focused execution plan beneath
|
||||||
the canonical desktop path. It keeps Intel and AMD at the same evidence bar while separating
|
the canonical desktop path. It keeps Intel and AMD at the same evidence bar while separating
|
||||||
display/KMS maturity from render/3D maturity.
|
display/KMS maturity from render/3D maturity.
|
||||||
- Older GPU-specific docs such as `local/docs/AMD-FIRST-INTEGRATION.md`,
|
- Older GPU-specific docs (`AMD-FIRST-INTEGRATION.md`, `HARDWARE-3D-ASSESSMENT.md`, `DMA-BUF-IMPROVEMENT-PLAN.md`) have been retired and removed from the tree. Their content is subsumed by `CONSOLE-TO-KDE-DESKTOP-PLAN.md` and `DRM-MODERNIZATION-EXECUTION-PLAN.md`.
|
||||||
`local/docs/HARDWARE-3D-ASSESSMENT.md`, and `local/docs/DMA-BUF-IMPROVEMENT-PLAN.md` remain
|
- `DESKTOP-STACK-CURRENT-STATUS.md` has been retired — its content merged into `CONSOLE-TO-KDE-DESKTOP-PLAN.md`.
|
||||||
useful reference material, but they are not the planning authority when sequencing or acceptance
|
|
||||||
criteria differ.
|
|
||||||
- `local/docs/AMD-FIRST-INTEGRATION.md` remains the deeper AMD-specific technical roadmap, but AMD
|
- `local/docs/AMD-FIRST-INTEGRATION.md` remains the deeper AMD-specific technical roadmap, but AMD
|
||||||
and Intel machines are now equal-priority Red Bear OS targets.
|
and Intel machines are now equal-priority Red Bear OS targets.
|
||||||
- The earlier Phase 0–3 reassessment bridge has been retired. Its reconciliation role is now
|
|
||||||
covered by `local/docs/CONSOLE-TO-KDE-DESKTOP-PLAN.md`,
|
|
||||||
`local/docs/DESKTOP-STACK-CURRENT-STATUS.md`, and `docs/07-RED-BEAR-OS-IMPLEMENTATION-PLAN.md`.
|
|
||||||
- `local/docs/WIFI-IMPLEMENTATION-PLAN.md` is the current Wi-Fi architecture and rollout plan,
|
- `local/docs/WIFI-IMPLEMENTATION-PLAN.md` is the current Wi-Fi architecture and rollout plan,
|
||||||
including the bounded role of `linux-kpi` and the native wireless control-plane direction.
|
including the bounded role of `linux-kpi` and the native wireless control-plane direction.
|
||||||
- `local/docs/USB-IMPLEMENTATION-PLAN.md` and `local/docs/BLUETOOTH-IMPLEMENTATION-PLAN.md` should
|
- `local/docs/USB-IMPLEMENTATION-PLAN.md` and `local/docs/BLUETOOTH-IMPLEMENTATION-PLAN.md` should
|
||||||
@@ -551,8 +546,7 @@ When mainline updates affect our work:
|
|||||||
IRQ delivery, MSI/MSI-X quality, IOMMU validation, and other low-level controller completeness work.
|
IRQ delivery, MSI/MSI-X quality, IOMMU validation, and other low-level controller completeness work.
|
||||||
- `local/docs/QUIRKS-SYSTEM.md` documents the hardware quirks infrastructure: compiled-in tables,
|
- `local/docs/QUIRKS-SYSTEM.md` documents the hardware quirks infrastructure: compiled-in tables,
|
||||||
TOML runtime files, DMI matching, driver integration, and the linux-kpi C FFI bridge.
|
TOML runtime files, DMI matching, driver integration, and the linux-kpi C FFI bridge.
|
||||||
- `local/docs/QUIRKS-IMPROVEMENT-PLAN.md` is the current follow-up plan for removing quirks drift,
|
- `local/docs/QUIRKS-IMPROVEMENT-PLAN.md` has been retired — quirks convergence is tracked in `QUIRKS-SYSTEM.md` and the canonical desktop path plan.
|
||||||
integrating quirks into real drivers, and converging on one source of truth.
|
|
||||||
- `local/docs/DBUS-INTEGRATION-PLAN.md` is the canonical D-Bus architecture and implementation plan for KDE Plasma 6 on Wayland. It defines the phased approach to D-Bus service integration, the `redbear-sessiond` login1-compatible session broker, and the gap analysis for desktop-facing D-Bus services.
|
- `local/docs/DBUS-INTEGRATION-PLAN.md` is the canonical D-Bus architecture and implementation plan for KDE Plasma 6 on Wayland. It defines the phased approach to D-Bus service integration, the `redbear-sessiond` login1-compatible session broker, and the gap analysis for desktop-facing D-Bus services.
|
||||||
- `local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md` is the canonical Red Bear-native greeter/login design and current implementation plan for the `redbear-full` desktop path. It defines the `redbear-authd` / `redbear-session-launch` / `redbear-greeter` split, service wiring, validation surface, and the current boundary between the active greeter path and the older `redbear-validation-session` helper flows.
|
- `local/docs/GREETER-LOGIN-IMPLEMENTATION-PLAN.md` is the canonical Red Bear-native greeter/login design and current implementation plan for the `redbear-full` desktop path. It defines the `redbear-authd` / `redbear-session-launch` / `redbear-greeter` split, service wiring, validation surface, and the current boundary between the active greeter path and the older `redbear-validation-session` helper flows.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,363 @@
|
|||||||
|
# Driver Discovery and Dynamic Hardware Mapping Plan
|
||||||
|
|
||||||
|
**Status**: Draft — implementation pending
|
||||||
|
**Date**: 2026-05-27
|
||||||
|
**Supersedes**: Ad-hoc pcid-spawner + hardcoded lived disk paths
|
||||||
|
**Author**: Red Bear OS team
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Problem Statement
|
||||||
|
|
||||||
|
Red Bear OS has two critical gaps in hardware discovery:
|
||||||
|
|
||||||
|
1. **lived's disk fallback is broken**: The live ISO boot daemon (`lived`) tries hardcoded paths `/scheme/disk/0` and `/scheme/usbscsi/0` to find the physical boot disk. But no disk driver registers those exact scheme names — they register `disk.pci-00-1F-2_ahci`, `disk.usb-xhci+1-scsi`, etc. The fallback **never works**.
|
||||||
|
|
||||||
|
2. **No dynamic hardware mapping**: The system does not distinguish between "hardware present" and "driver needed." On bare metal with no virtio devices, the system should not try to load `virtio-blkd`. On QEMU with no real AHCI controller, the system should not try to load `ahcid`. Today, the driver-manager loads whatever matches its static config files regardless of whether the hardware exists.
|
||||||
|
|
||||||
|
Linux solves both problems with a two-stage model:
|
||||||
|
- **Stage 1 (initramfs)**: Enumerate PCI bus, load ONLY the storage driver matching the boot controller, mount rootfs.
|
||||||
|
- **Stage 2 (rootfs)**: Full enumeration, udev + modprobe dynamically load all remaining drivers based on actual hardware.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Current Architecture
|
||||||
|
|
||||||
|
### 2.1 Boot Sequence (Initfs Phase)
|
||||||
|
|
||||||
|
```
|
||||||
|
Bootstrap (PID 1) → init → services start in dependency order:
|
||||||
|
|
||||||
|
00_runtime.target randd, nulld, zerod, rtcd, logd
|
||||||
|
10_inputd.service VT input multiplexer
|
||||||
|
10_lived.service Live disk daemon (RAM preload + disk fallback)
|
||||||
|
20_graphics.target vesad (FB handoff), fbcond, fbbootlogd
|
||||||
|
41_acpid.service ACPI interpreter → scheme:acpi
|
||||||
|
40_hwd.service Hardware manager → spawns pcid internally
|
||||||
|
pcid → enumerates PCI bus → registers scheme:pci
|
||||||
|
00_driver-manager-initfs.service (if P26 applied)
|
||||||
|
Loads /scheme/initfs/lib/drivers.d/00-storage.toml
|
||||||
|
Only: ahcid, ided, nvmed, virtio-blkd
|
||||||
|
40_drivers.target All initfs drivers
|
||||||
|
50_rootfs.service Mount rootfs (hard dep on drivers.target)
|
||||||
|
90_initfs.target Trigger switchroot
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 Driver Registration Contract
|
||||||
|
|
||||||
|
All disk drivers using `driver_block::DiskScheme` register schemes starting with `"disk"`:
|
||||||
|
|
||||||
|
| Driver | Scheme Name Pattern | Match Criteria |
|
||||||
|
|--------|---------------------|----------------|
|
||||||
|
| ided | `disk.pci-XX-XX-X_ide` | PCI class 0x01, subclass 0x01 |
|
||||||
|
| ahcid | `disk.pci-XX-XX-X_ahci` | PCI class 0x01, subclass 0x06 |
|
||||||
|
| nvmed | `disk.pci-XX-XX-X-nvme` | PCI class 0x01, subclass 0x08 |
|
||||||
|
| virtio-blkd | `disk.pci-XX-XX-X_virtio_blk` | PCI vendor 0x1AF4, device 0x1001 |
|
||||||
|
| usbscsid | `disk.usb-xhci+PORT-scsi` | USB SCSI transport |
|
||||||
|
| lived | `disk.live` | RAM-backed (our daemon) |
|
||||||
|
|
||||||
|
The `DiskScheme::new()` assertion (`assert!(scheme_name.starts_with("disk"))`) is the **contract** that enables dynamic discovery: any consumer can find all disk schemes by listing `/scheme/` and filtering for the `"disk"` prefix.
|
||||||
|
|
||||||
|
### 2.3 The Two Driver-Loading Paths
|
||||||
|
|
||||||
|
| Path | Mechanism | Config Source | Drivers |
|
||||||
|
|------|-----------|---------------|---------|
|
||||||
|
| **Initfs** | `driver-manager --initfs` | `/scheme/initfs/lib/drivers.d/00-storage.toml` | Storage only (4 drivers) |
|
||||||
|
| **Rootfs** | `driver-manager --hotplug` | `/lib/drivers.d/*.toml` | All categories (40+ drivers) |
|
||||||
|
|
||||||
|
### 2.4 How Linux Does It (Reference)
|
||||||
|
|
||||||
|
Linux uses a two-tier ordering:
|
||||||
|
|
||||||
|
**Tier 1 — Initcall levels** (include/linux/init.h):
|
||||||
|
```
|
||||||
|
Level 0: pure_initcall (architecture setup)
|
||||||
|
Level 2: postcore_initcall (PCI subsystem registers here)
|
||||||
|
Level 4: subsys_initcall (SCSI, networking subsystems)
|
||||||
|
Level 6: device_initcall (module_init → all built-in drivers)
|
||||||
|
Level 7: late_initcall (late-stage platform drivers)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tier 2 — Link order** within device_initcall (drivers/Makefile):
|
||||||
|
```
|
||||||
|
Line 49: obj-y += virtio/ # VirtIO before block
|
||||||
|
Line 76: obj-y += block/ # Block devices (storage)
|
||||||
|
Line 84: obj-y += nvme/ # NVMe
|
||||||
|
Line 85: obj-y += ata/ # ATA/AHCI
|
||||||
|
Line 92: obj-y += net/ # Network
|
||||||
|
Line 68: obj-y += gpu/ # GPU comes AFTER storage
|
||||||
|
```
|
||||||
|
|
||||||
|
**The critical principle**: Storage must load before GPU not because of PCI ordering, but because GPU drivers need firmware blobs from `/lib/firmware/` — which requires a mounted filesystem. Storage drivers are needed to mount that filesystem.
|
||||||
|
|
||||||
|
**Dynamic loading** (after rootfs mount): `MODULE_DEVICE_TABLE` entries in every driver generate `modules.alias` patterns. udev receives kernel uevents with `MODALIAS=pci:v00001AF4d00001001...`, calls `modprobe`, which looks up the alias and loads the matching `.ko` module.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Design: Two-Stage Dynamic Hardware Discovery
|
||||||
|
|
||||||
|
### 3.1 Stage 1 — Initfs Boot (Storage-Only)
|
||||||
|
|
||||||
|
**Goal**: Load exactly the storage driver(s) needed to mount the root filesystem. No more, no less.
|
||||||
|
|
||||||
|
**Mechanism**: driver-manager `--initfs` already exists and does PCI class/vendor matching. The missing piece is that the P26 patch (which creates `00_driver-manager-initfs.service` and `initfs-storage.toml`) is wired in `recipe.toml` but needs to be applied.
|
||||||
|
|
||||||
|
**Initfs driver config** (`initfs-storage.toml`):
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Only storage drivers — needed to mount rootfs
|
||||||
|
# GPU/display deliberately excluded (handled by rootfs DRM/KMS stack)
|
||||||
|
|
||||||
|
[[driver]]
|
||||||
|
name = "nvmed"
|
||||||
|
description = "NVMe storage driver"
|
||||||
|
priority = 100
|
||||||
|
command = ["/scheme/initfs/lib/drivers/nvmed"]
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
bus = "pci"
|
||||||
|
class = 1
|
||||||
|
subclass = 8
|
||||||
|
|
||||||
|
[[driver]]
|
||||||
|
name = "ahcid"
|
||||||
|
description = "AHCI SATA driver"
|
||||||
|
priority = 100
|
||||||
|
command = ["/scheme/initfs/lib/drivers/ahcid"]
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
bus = "pci"
|
||||||
|
class = 1
|
||||||
|
subclass = 6
|
||||||
|
|
||||||
|
[[driver]]
|
||||||
|
name = "ided"
|
||||||
|
description = "PATA IDE driver"
|
||||||
|
priority = 100
|
||||||
|
command = ["/scheme/initfs/lib/drivers/ided"]
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
bus = "pci"
|
||||||
|
class = 1
|
||||||
|
subclass = 1
|
||||||
|
|
||||||
|
[[driver]]
|
||||||
|
name = "virtio-blkd"
|
||||||
|
description = "VirtIO block device driver"
|
||||||
|
priority = 100
|
||||||
|
command = ["/scheme/initfs/lib/drivers/virtio-blkd"]
|
||||||
|
|
||||||
|
[[driver.match]]
|
||||||
|
bus = "pci"
|
||||||
|
vendor = 0x1AF4
|
||||||
|
device = 0x1001
|
||||||
|
```
|
||||||
|
|
||||||
|
**How this is already dynamic**: The driver-manager only spawns a driver when the PCI bus actually reports a matching device. If QEMU has no AHCI controller, `ahcid` is never spawned. If bare metal has no VirtIO devices, `virtio-blkd` is never spawned. The TOML match table is a **candidate list**, not a **must-load list**.
|
||||||
|
|
||||||
|
**What's needed**: Ensure P26 is applied, ensure `virtio-blkd` is in the BINS list, and ensure the initfs binary staging includes all 4 storage drivers.
|
||||||
|
|
||||||
|
### 3.2 Stage 2 — Rootfs (Full Hardware Discovery)
|
||||||
|
|
||||||
|
**Goal**: After rootfs is mounted, dynamically discover and load ALL remaining drivers based on actual hardware.
|
||||||
|
|
||||||
|
**Mechanism**: `driver-manager --hotplug` already reads `/lib/drivers.d/*.toml` (8 config files, 40+ drivers), enumerates PCI + ACPI buses, and spawns matching drivers. It also runs a hotplug loop for device add/remove.
|
||||||
|
|
||||||
|
**The existing driver configs are already data-driven and dynamic**:
|
||||||
|
|
||||||
|
| Config File | Category | Priority | Matching |
|
||||||
|
|-------------|----------|----------|----------|
|
||||||
|
| `00-storage.toml` | Storage | 100 | PCI class-based |
|
||||||
|
| `10-network.toml` | Network | 50 | PCI vendor + class |
|
||||||
|
| `20-usb.toml` | USB | 80 | PCI class + prog_if |
|
||||||
|
| `30-graphics.toml` | GPU/Display | 60 | PCI class 0x03 |
|
||||||
|
| `40-input.toml` | Input | 40 | Sentinel (vendor=0xFFFF) |
|
||||||
|
| `50-audio.toml` | Audio | 40 | PCI vendor + class |
|
||||||
|
| `60-gpio-i2c.toml` | GPIO/I2C | 30 | ACPI bus matching |
|
||||||
|
| `70-usb-class.toml` | USB class | 20 | Sentinel (vendor=0xFFFF) |
|
||||||
|
|
||||||
|
**Key property**: Priority ordering ensures storage (100) > USB (80) > GPU (60) > network (50) > audio (40). This mirrors Linux's link-order principle.
|
||||||
|
|
||||||
|
### 3.3 lived Disk Fallback Fix
|
||||||
|
|
||||||
|
**Current bug**: `lived` tries `/scheme/disk/0` — but real schemes are named `disk.pci-00-1F-2_ahci`, never just `disk`.
|
||||||
|
|
||||||
|
**Fix**: Replace hardcoded paths with RedoxFS-style dynamic scheme discovery (same pattern as `filesystem_by_uuid` in `redoxfs/src/bin/mount.rs`):
|
||||||
|
|
||||||
|
```rust
|
||||||
|
fn try_open_disk(&self) -> Result<File, String> {
|
||||||
|
for attempt in 0..DISK_OPEN_MAX_RETRIES {
|
||||||
|
// List /scheme/ to find all registered disk schemes
|
||||||
|
if let Ok(entries) = std::fs::read_dir("/scheme") {
|
||||||
|
for entry in entries.flatten() {
|
||||||
|
let name = entry.file_name();
|
||||||
|
let name_str = name.to_string_lossy();
|
||||||
|
|
||||||
|
// All disk schemes start with "disk." (driver-block contract)
|
||||||
|
// Skip our own "disk.live" scheme
|
||||||
|
if name_str.starts_with("disk.") && name_str != "disk.live" {
|
||||||
|
// Try opening disk 0 on this scheme
|
||||||
|
let path = format!("/scheme/{}/0", name_str);
|
||||||
|
if let Ok(file) = File::open(&path) {
|
||||||
|
eprintln!("lived: opened physical disk at {} (attempt {})",
|
||||||
|
path, attempt + 1);
|
||||||
|
return Ok(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if attempt < DISK_OPEN_MAX_RETRIES - 1 {
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(
|
||||||
|
DISK_OPEN_RETRY_INTERVAL_MS
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(format!("no disk scheme found after {} retries", DISK_OPEN_MAX_RETRIES))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**This is the exact pattern RedoxFS uses** in `filesystem_by_uuid()`. It:
|
||||||
|
1. Lists `/scheme/` (all registered schemes)
|
||||||
|
2. Filters to names starting with `"disk."` (the `driver-block` contract)
|
||||||
|
3. Skips `disk.live` (our own RAM-backed scheme)
|
||||||
|
4. Tries opening disk 0 on each discovered scheme
|
||||||
|
|
||||||
|
**Boot timing**: lived starts at service 10, before disk drivers. The retry loop (60 × 500ms = 30s) gives driver-manager and storage drivers time to load and register their schemes. As soon as ANY storage driver registers `disk.*`, lived finds it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. What Needs to Change
|
||||||
|
|
||||||
|
### 4.1 Patches Required
|
||||||
|
|
||||||
|
| Component | Patch | What It Does |
|
||||||
|
|-----------|-------|--------------|
|
||||||
|
| **base** | P60 (new) | Add `virtio-blkd` to BINS + staged files; update lived's `try_open_disk()` with dynamic scheme discovery |
|
||||||
|
| **kernel** | P26 (existing) | DebugDisplay scrolling fix (already done) |
|
||||||
|
| **base** | P26-driver-manager-initfs-conversion.patch (existing, wired but needs application verification) | Replaces pcid-spawner with driver-manager in initfs |
|
||||||
|
|
||||||
|
### 4.2 Changes to `recipes/core/base/recipe.toml`
|
||||||
|
|
||||||
|
1. **Add `virtio-blkd` to BINS** (already done in working tree)
|
||||||
|
2. **Add `virtio-blkd` to staged files list** (already done in working tree)
|
||||||
|
3. **No changes to driver configs** — `initfs-storage.toml` already lists all 4 storage drivers
|
||||||
|
|
||||||
|
### 4.3 Changes to `recipes/core/base/source/drivers/storage/lived/src/main.rs`
|
||||||
|
|
||||||
|
Replace the hardcoded `candidates` array in `try_open_disk()` with `/scheme/` directory enumeration that discovers disk schemes dynamically.
|
||||||
|
|
||||||
|
### 4.4 No Changes Needed
|
||||||
|
|
||||||
|
- **driver-manager** — already does dynamic PCI matching
|
||||||
|
- **initfs-storage.toml** — already has the right 4 storage drivers
|
||||||
|
- **Driver configs** (`/lib/drivers.d/*.toml`) — already data-driven with vendor/class matching
|
||||||
|
- **pcid** — already enumerates PCI bus correctly
|
||||||
|
- **Boot service order** — already correct (lived at 10, driver-manager-initfs at 00, rootfs at 50)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Verification Plan
|
||||||
|
|
||||||
|
### 5.1 QEMU with IDE (default)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
timeout 60 qemu-system-x86_64 \
|
||||||
|
-drive file=build/x86_64/redbear-full.iso,format=raw \
|
||||||
|
-m 4G -smp 4 -serial stdio -no-reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: lived finds `disk.pci-00-01-1_ide` scheme from `ided`, mounts rootfs.
|
||||||
|
|
||||||
|
### 5.2 QEMU with virtio-blk
|
||||||
|
|
||||||
|
```bash
|
||||||
|
timeout 60 qemu-system-x86_64 \
|
||||||
|
-device virtio-blk-pci,drive=drive0 \
|
||||||
|
-drive id=drive0,file=build/x86_64/redbear-full.iso,format=raw,if=none \
|
||||||
|
-m 4G -smp 4 -serial stdio -no-reboot
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: lived finds `disk.pci-00-XX-X_virtio_blk` scheme from `virtio-blkd`, mounts rootfs.
|
||||||
|
|
||||||
|
### 5.3 Bare Metal USB Boot
|
||||||
|
|
||||||
|
Expected: lived finds `disk.usb-xhci+PORT-scsi` scheme from `usbscsid`, mounts rootfs.
|
||||||
|
|
||||||
|
### 5.4 No Unnecessary Drivers
|
||||||
|
|
||||||
|
On QEMU with only virtio-blk (no AHCI), `ahcid` should NOT be spawned. Verify via boot log:
|
||||||
|
```
|
||||||
|
driver-manager: no driver found for pci 0000:00:01.1 # IDE controller — no match
|
||||||
|
driver-manager: bound: 0000:00:04.0 -> virtio-blkd # VirtIO block — matched
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. PCI Class Code Reference
|
||||||
|
|
||||||
|
From Linux `include/linux/pci_ids.h` and our driver configs:
|
||||||
|
|
||||||
|
| Class | Subclass | Prog IF | Device Type | Red Bear Driver |
|
||||||
|
|-------|----------|---------|-------------|-----------------|
|
||||||
|
| 0x01 | 0x01 | — | IDE/PATA | `ided` |
|
||||||
|
| 0x01 | 0x06 | 0x01 | AHCI SATA | `ahcid` |
|
||||||
|
| 0x01 | 0x08 | 0x02 | NVMe | `nvmed` |
|
||||||
|
| 0x01 | 0x00 | — | VirtIO Block (vendor 0x1AF4, device 0x1001) | `virtio-blkd` |
|
||||||
|
| 0x02 | — | — | Ethernet | `e1000d`, `rtl8168d`, etc. |
|
||||||
|
| 0x03 | — | — | Display/GPU | `redox-drm` |
|
||||||
|
| 0x04 | 0x03 | — | Audio (HDA) | `ihdad` |
|
||||||
|
| 0x0C | 0x03 | 0x30 | xHCI USB | `xhcid` |
|
||||||
|
| 0x0C | 0x03 | 0x00 | UHCI USB | `uhcid` |
|
||||||
|
| 0x0C | 0x03 | 0x10 | OHCI USB | `ohcid` |
|
||||||
|
| 0x0C | 0x03 | 0x20 | EHCI USB | `ehcid` |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Boot Timeline (Target State)
|
||||||
|
|
||||||
|
```
|
||||||
|
T+0ms Bootstrap starts, creates initfs/procmgr/namespace schemes
|
||||||
|
T+50ms init starts, launches 00_randd → 00_logd → 00_runtime.target
|
||||||
|
T+200ms lived starts (service 10), loads 128 MiB preload
|
||||||
|
T+300ms vesad starts (FB handoff for text console)
|
||||||
|
T+400ms acpid starts → ACPI interpreter → scheme:acpi
|
||||||
|
T+500ms hwd starts → spawns pcid → PCI bus scan → scheme:pci
|
||||||
|
driver-manager --initfs starts:
|
||||||
|
Loads 00-storage.toml (4 storage drivers)
|
||||||
|
Enumerates PCI bus via /scheme/pci/
|
||||||
|
QEMU: finds 8086:7010 (IDE) → spawns ided
|
||||||
|
finds 1234:1111 (virtio-gpu) → no storage match, skipped
|
||||||
|
finds 1AF4:1050 (virtio-net) → no storage match, skipped
|
||||||
|
T+1500ms ided registers disk.pci-00-01-1_ide
|
||||||
|
lived discovers disk.pci-00-01-1_ide via /scheme/ enumeration
|
||||||
|
lived disk fallback succeeds
|
||||||
|
T+2000ms redoxfs mounts rootfs from lived
|
||||||
|
T+2500ms switchroot → rootfs init starts
|
||||||
|
T+3000ms driver-manager --hotplug starts (rootfs):
|
||||||
|
Loads all /lib/drivers.d/*.toml configs
|
||||||
|
Detects ided already bound → skips
|
||||||
|
Finds 1234:1111 (display class 0x03) → spawns redox-drm
|
||||||
|
Finds 8086:100E (network class 0x02) → spawns e1000d
|
||||||
|
Finds 1AF4:1050 (virtio-net) → spawns virtio-netd
|
||||||
|
T+5000ms All drivers bound, system fully operational
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Principles
|
||||||
|
|
||||||
|
1. **Data-driven, not hardcoded**: Driver matching via TOML configs with vendor/device/class fields. No binary name hardcoding, no path guessing.
|
||||||
|
|
||||||
|
2. **Enumerate first, match second**: PCI bus scan produces ALL devices. Driver matching filters to supported ones. Unknown hardware is logged but doesn't block boot.
|
||||||
|
|
||||||
|
3. **Priority ordering**: Storage (100) before USB (80) before GPU (60) before network (50) before audio (40). Mirrors Linux's link-order principle.
|
||||||
|
|
||||||
|
4. **Stage 1 = minimum viable set**: Initfs loads ONLY storage drivers. Everything else waits for rootfs.
|
||||||
|
|
||||||
|
5. **Dynamic scheme discovery**: lived discovers disk schemes by reading `/scheme/` and filtering for the `"disk."` prefix — the same contract that `driver-block` enforces.
|
||||||
|
|
||||||
|
6. **No unnecessary drivers**: If hardware doesn't exist, the driver is never spawned. `driver-manager` only calls `probe()` for devices that actually exist on the PCI/ACPI bus.
|
||||||
|
|
||||||
|
7. **Deferred retry for timing**: Drivers that start before their dependencies are ready get retried (3 times in initfs, 5 times in hotplug). After max retries, the device is permanently skipped with a logged reason.
|
||||||
@@ -0,0 +1,483 @@
|
|||||||
|
# Live ISO Mount — Architecture, Failure Analysis, and Fix Plan
|
||||||
|
|
||||||
|
**Date:** 2026-05-27
|
||||||
|
**Status:** Draft — fixes not yet implemented
|
||||||
|
**Scope:** Bootloader live preload, lived daemon, RedoxFS mount chain
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Current Architecture
|
||||||
|
|
||||||
|
### 1.1 Boot Flow (Live ISO)
|
||||||
|
|
||||||
|
```
|
||||||
|
UEFI firmware
|
||||||
|
→ Bootloader (recipes/core/bootloader/source/src/main.rs)
|
||||||
|
1. Find RedoxFS partition on disk
|
||||||
|
2. Read filesystem header → get total filesystem size (e.g., 4093 MiB)
|
||||||
|
3. Live preload: read first N MiB of filesystem into RAM
|
||||||
|
- Cap: max_preload = 1024 MiB (line 559)
|
||||||
|
- Set env: DISK_LIVE_ADDR=<phys addr>, DISK_LIVE_SIZE=<preload size>
|
||||||
|
- Set env: REDOXFS_BLOCK=0 (start of partition)
|
||||||
|
4. Load kernel from RedoxFS into memory
|
||||||
|
5. Load initfs from RedoxFS into memory
|
||||||
|
6. Set up paging, pass env to kernel
|
||||||
|
7. Jump to kernel entry point
|
||||||
|
|
||||||
|
Kernel
|
||||||
|
→ bootstrap (initfs)
|
||||||
|
→ init daemon
|
||||||
|
→ lived daemon (10_lived.service)
|
||||||
|
- Reads DISK_LIVE_ADDR + DISK_LIVE_SIZE from env
|
||||||
|
- Maps preloaded RAM as LiveDisk via /scheme/memory/physical
|
||||||
|
- Registers scheme:disk.live
|
||||||
|
- LiveDisk.size() = preloaded size (1024 MiB)
|
||||||
|
- LiveDisk.block_size() = PAGE_SIZE (4096) [P6 patch changes to 512]
|
||||||
|
|
||||||
|
→ redoxfs daemon (50_rootfs.service)
|
||||||
|
- Opens /scheme/disk.live/0 as DiskFile
|
||||||
|
- Calls FileSystem::open(disk, password, block=0, cleanup=true)
|
||||||
|
- Reads header at block 0 (inside preloaded region → works)
|
||||||
|
- Calls fs.reset_allocator() → walks the allocation tree
|
||||||
|
- Calls fs.cleanup() → may read blocks across the entire filesystem
|
||||||
|
- FAILURE: any read beyond preloaded size returns EINVAL
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Component Map
|
||||||
|
|
||||||
|
| Component | Source | Role |
|
||||||
|
|-----------|--------|------|
|
||||||
|
| **Bootloader** | `recipes/core/bootloader/source/src/main.rs` | Preloads filesystem into RAM, passes env vars |
|
||||||
|
| **lived** | `recipes/core/base/source/drivers/storage/lived/src/main.rs` | Maps preloaded RAM as `scheme:disk.live` |
|
||||||
|
| **RedoxFS mount** | `recipes/core/redoxfs/source/src/bin/mount.rs` | Opens disk scheme, calls FileSystem::open |
|
||||||
|
| **RedoxFS lib** | `recipes/core/redoxfs/source/src/filesystem.rs` | Reads header, walks allocator tree |
|
||||||
|
| **driver-block** | `recipes/core/base/source/drivers/storage/driver-block/src/lib.rs` | DiskWrapper with block_size alignment checks |
|
||||||
|
| **P6 patch** | `local/patches/base/P6-lived-block-size-512.patch` | Changes block_size from PAGE_SIZE to 512 |
|
||||||
|
|
||||||
|
### 1.3 The Preload Cap
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// bootloader/src/main.rs:559
|
||||||
|
let max_preload: u64 = 1024 * MIBI as u64; // 1 GiB hard cap
|
||||||
|
let preload_size = if size > max_preload {
|
||||||
|
max_preload // Cap at 1 GiB
|
||||||
|
} else {
|
||||||
|
size // Preload entire filesystem if ≤ 1 GiB
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
For redbear-full (4093 MiB filesystem): preloads 1024 MiB, 3069 MiB must come from disk.
|
||||||
|
For redbear-mini (1533 MiB filesystem): preloads 1024 MiB, 509 MiB must come from disk.
|
||||||
|
|
||||||
|
### 1.4 The lived Disk
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// lived/src/main.rs - LiveDisk::read (CURRENT, unpatched source)
|
||||||
|
fn block_size(&self) -> u32 {
|
||||||
|
PAGE_SIZE as u32 // P6 changes this to 512
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size(&self) -> u64 {
|
||||||
|
self.original.len() as u64 // This is the PRELOADED size, not total filesystem size
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read(&mut self, mut block: u64, buffer: &mut [u8]) -> syscall::Result<usize> {
|
||||||
|
let mut offset = (block as usize) * PAGE_SIZE;
|
||||||
|
if offset + buffer.len() > self.original.len() {
|
||||||
|
return Err(syscall::Error::new(EINVAL)); // ← THIS IS THE FAILURE POINT
|
||||||
|
}
|
||||||
|
// ... read from preloaded buffer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**The fundamental problem:** `lived` only has the preloaded buffer (1024 MiB). It has no
|
||||||
|
access to the remaining filesystem data on the physical disk. When RedoxFS tries to read
|
||||||
|
beyond 1024 MiB, lived returns EINVAL.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. Failure Analysis
|
||||||
|
|
||||||
|
### 2.1 Why Does the Mini ISO Work?
|
||||||
|
|
||||||
|
The mini ISO (1533 MiB) also has 509 MiB beyond the preload. However:
|
||||||
|
|
||||||
|
1. RedoxFS `FileSystem::open` reads the header at block 0 (within preload) → OK
|
||||||
|
2. `reset_allocator` walks the free block tree. For a 1533 MiB filesystem with minimal
|
||||||
|
contents, the allocator metadata is concentrated near the start → likely within 1024 MiB
|
||||||
|
3. `cleanup` reads extent nodes — for a small filesystem, these are also near the start
|
||||||
|
|
||||||
|
For the full ISO (4093 MiB) with hundreds of packages:
|
||||||
|
- The allocator tree and extent nodes span the entire 4093 MiB range
|
||||||
|
- RedoxFS needs to read blocks at offsets > 1024 MiB during `FileSystem::open`
|
||||||
|
- lived rejects those reads → mount fails
|
||||||
|
|
||||||
|
**The mini ISO works by luck** — its metadata happens to fit within the preload window.
|
||||||
|
This is not a reliable design.
|
||||||
|
|
||||||
|
### 2.2 The Exact Error Chain
|
||||||
|
|
||||||
|
```
|
||||||
|
RedoxFS FileSystem::open
|
||||||
|
→ disk.read_at(block_N, &mut header)
|
||||||
|
→ DiskFile::read_at(buffer, block_N * BLOCK_SIZE)
|
||||||
|
→ syscall::read(scheme:disk.live/0, offset=block_N * 512)
|
||||||
|
→ lived::LiveDisk::read(block_N, buffer)
|
||||||
|
→ offset = block_N * PAGE_SIZE // or 512 with P6
|
||||||
|
→ if offset + buffer.len() > self.original.len():
|
||||||
|
return Err(EINVAL) // ← HERE
|
||||||
|
```
|
||||||
|
|
||||||
|
The error propagates:
|
||||||
|
- lived → EINVAL
|
||||||
|
- DiskFile → "RedoxFS: IO ERROR: Invalid argument (os error 22)"
|
||||||
|
- FileSystem::open → Err(EINVAL)
|
||||||
|
- mount.rs → "not able to mount uuid ..."
|
||||||
|
|
||||||
|
### 2.3 The P6 Block Size Patch
|
||||||
|
|
||||||
|
The P6 patch (`local/patches/base/P6-lived-block-size-512.patch`) fixes a different but
|
||||||
|
related issue: the original `block_size()` returned `PAGE_SIZE` (4096), but RedoxFS reads
|
||||||
|
in 512-byte chunks (`BLOCK_SIZE = 4096` but individual reads may be 512). The `DiskWrapper`
|
||||||
|
in `driver-block` rejects misaligned reads. Changing to 512 fixes alignment but does NOT
|
||||||
|
fix the size/out-of-bounds problem.
|
||||||
|
|
||||||
|
**Note:** The current source tree (`recipes/core/base/source/drivers/storage/lived/src/main.rs`)
|
||||||
|
does NOT have the P6 patch applied — it still shows `PAGE_SIZE as u32`. The P6 patch is
|
||||||
|
applied during `repo fetch base` and only exists durably in `local/patches/base/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Fix Strategy
|
||||||
|
|
||||||
|
### 3.1 Design Principle
|
||||||
|
|
||||||
|
> Preload the minimum needed to boot the kernel + initfs. Once the OS is running, mount
|
||||||
|
> the filesystem from the actual disk device, not from the RAM preload.
|
||||||
|
|
||||||
|
The bootloader already loads kernel + initfs from RedoxFS before switching to live mode.
|
||||||
|
After that, the running OS has access to the AHCI driver (ahcid) and can mount the
|
||||||
|
filesystem directly from the physical disk.
|
||||||
|
|
||||||
|
### 3.2 Two-Phase Approach
|
||||||
|
|
||||||
|
**Phase A: Bootloader Changes** (bootloader is UEFI code, runs before the OS)
|
||||||
|
|
||||||
|
1. **Reduce preload to the minimum needed for kernel + initfs discovery**
|
||||||
|
- The bootloader needs to read the RedoxFS superblock + directory tree to find
|
||||||
|
`usr/lib/boot/kernel` and `usr/lib/boot/initfs`. This requires reading the header,
|
||||||
|
the root node, and walking directory entries.
|
||||||
|
- Instead of preloading a fixed 1024 MiB, preload only what's needed to locate and
|
||||||
|
read these two files. In practice, this is the first few MiB of the filesystem.
|
||||||
|
- Fallback: if the filesystem is small enough (≤ 64 MiB?), preload everything.
|
||||||
|
|
||||||
|
2. **Pass the physical disk location to the kernel**
|
||||||
|
- Set `DISK_PHYS_ADDR` and `DISK_PHYS_SIZE` env vars with the full disk geometry
|
||||||
|
- Keep `DISK_LIVE_ADDR` / `DISK_LIVE_SIZE` for the minimal preload
|
||||||
|
- Add `REDOXFS_FULL_SIZE` so the OS knows the true filesystem extent
|
||||||
|
|
||||||
|
**Phase B: lived Daemon Changes** (OS-level, patchable via `local/patches/base/`)
|
||||||
|
|
||||||
|
1. **Accept the full filesystem size as an additional env var**
|
||||||
|
- Read `REDOXFS_FULL_SIZE` or derive from the RedoxFS header
|
||||||
|
- Report `LiveDisk::size()` as the FULL filesystem size, not just the preload
|
||||||
|
|
||||||
|
2. **Fall through to the physical disk for reads beyond the preload**
|
||||||
|
- When `read(block, buffer)` is called with an offset beyond `self.original.len()`:
|
||||||
|
- Open the underlying block device (e.g., `/scheme/disk/0` after ahcid starts)
|
||||||
|
- Read the data from the physical disk
|
||||||
|
- Cache the result in the overlay HashMap
|
||||||
|
- This makes lived act as a write-through cache: preload in RAM, fallback to disk
|
||||||
|
|
||||||
|
3. **Alternative simpler approach: bypass lived entirely for large images**
|
||||||
|
- After ahcid starts and registers `/scheme/disk/0`, the init system could mount
|
||||||
|
RedoxFS directly from `/scheme/disk/0` instead of `/scheme/disk.live/0`
|
||||||
|
- The preload would only be used by the bootloader to load kernel + initfs
|
||||||
|
- Once the OS boots, lived is unnecessary — mount from the real disk
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Concrete Fix Plan
|
||||||
|
|
||||||
|
### 4.1 Fix 1: Reduce Bootloader Preload (bootloader patch)
|
||||||
|
|
||||||
|
**File:** `recipes/core/bootloader/source/src/main.rs`
|
||||||
|
|
||||||
|
**Current:**
|
||||||
|
```rust
|
||||||
|
let max_preload: u64 = 1024 * MIBI as u64;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Proposed change:**
|
||||||
|
```rust
|
||||||
|
// Only preload what the bootloader actually needs:
|
||||||
|
// - RedoxFS header + allocator (first ~1 MiB)
|
||||||
|
// - Root directory tree (typically first 32-64 MiB)
|
||||||
|
// - kernel and initfs files (loaded separately after preload)
|
||||||
|
// 64 MiB is generous for the metadata region of any reasonable filesystem.
|
||||||
|
// The kernel and initfs are loaded separately via fs.disk.read_at() directly
|
||||||
|
// from the physical disk, so they don't need to be in the preload.
|
||||||
|
let max_preload: u64 = 64 * MIBI as u64;
|
||||||
|
```
|
||||||
|
|
||||||
|
Wait — this doesn't work. The bootloader reads kernel and initfs from the RedoxFS
|
||||||
|
filesystem using `load_to_memory(os, &mut fs, "usr/lib/boot/kernel", ...)`. After the
|
||||||
|
preload, the bootloader has already switched the disk to the live buffer. So the kernel
|
||||||
|
and initfs must be within the preload, OR the bootloader must load them before switching
|
||||||
|
to live mode.
|
||||||
|
|
||||||
|
**Looking at the actual bootloader flow:**
|
||||||
|
```
|
||||||
|
1. Open RedoxFS from physical disk → fs
|
||||||
|
2. Preload first N MiB into RAM buffer
|
||||||
|
3. Set LIVE_OPT = Some((fs.block, buffer))
|
||||||
|
4. Load kernel from fs (still using physical disk? or from buffer?)
|
||||||
|
5. Load initfs from fs
|
||||||
|
6. Pass LIVE_OPT to kernel env
|
||||||
|
```
|
||||||
|
|
||||||
|
The live buffer is set in `LIVE_OPT` at line 625, but the kernel and initfs are loaded
|
||||||
|
at lines 642-663, AFTER the live preload. The `load_to_memory` function uses `fs` which
|
||||||
|
still uses the original disk handle. So the kernel and initfs are read from the physical
|
||||||
|
disk, not from the live buffer.
|
||||||
|
|
||||||
|
**This means the preload doesn't need to include kernel or initfs at all.** The preload
|
||||||
|
exists solely so that `lived` can serve the filesystem to the running OS via `scheme:disk.live`.
|
||||||
|
|
||||||
|
**Revised Fix 1:** Reduce max_preload to a small value (e.g., 4-64 MiB) that covers just
|
||||||
|
the RedoxFS metadata needed for initial mount, then rely on the disk fallback for the rest.
|
||||||
|
|
||||||
|
BUT: this only works if `lived` can fall through to the physical disk for out-of-bounds
|
||||||
|
reads. Without the fallback, reducing preload makes the problem worse.
|
||||||
|
|
||||||
|
### 4.2 Fix 2: lived Disk Fallback (base patch)
|
||||||
|
|
||||||
|
**File:** `recipes/core/base/source/drivers/storage/lived/src/main.rs`
|
||||||
|
|
||||||
|
This is the core fix. Make `lived` aware of the full filesystem and able to read from
|
||||||
|
the physical disk when the preload doesn't cover the requested region.
|
||||||
|
|
||||||
|
**Design:**
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct LiveDisk {
|
||||||
|
// Preloaded RAM buffer (may be smaller than total filesystem)
|
||||||
|
preload: &'static [u8],
|
||||||
|
// Full filesystem size (from RedoxFS header or env var)
|
||||||
|
total_size: u64,
|
||||||
|
// Physical disk offset where the filesystem starts
|
||||||
|
disk_block: u64,
|
||||||
|
// Handle to the physical disk (opened after ahcid starts)
|
||||||
|
disk_handle: Option<File>,
|
||||||
|
// Write overlay (same as before)
|
||||||
|
overlay: HashMap<u64, Box<[u8]>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Disk for LiveDisk {
|
||||||
|
fn block_size(&self) -> u32 { 512 }
|
||||||
|
|
||||||
|
fn size(&self) -> u64 { self.total_size }
|
||||||
|
|
||||||
|
async fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<usize> {
|
||||||
|
let bs = self.block_size() as usize;
|
||||||
|
let offset = (block as usize) * bs;
|
||||||
|
|
||||||
|
if offset + buffer.len() > self.total_size as usize {
|
||||||
|
return Err(syscall::Error::new(EINVAL));
|
||||||
|
}
|
||||||
|
|
||||||
|
let preload_bytes = self.preload.len();
|
||||||
|
|
||||||
|
for (i, chunk) in buffer.chunks_mut(bs).enumerate() {
|
||||||
|
let block_i = block + i as u64;
|
||||||
|
let offset_i = offset + i * bs;
|
||||||
|
|
||||||
|
// Check overlay first
|
||||||
|
if let Some(overlay) = self.overlay.get(&block_i) {
|
||||||
|
chunk.copy_from_slice(&overlay[..chunk.len()]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset_i + chunk.len() <= preload_bytes {
|
||||||
|
// Within preload → read from RAM
|
||||||
|
chunk.copy_from_slice(&self.preload[offset_i..offset_i + chunk.len()]);
|
||||||
|
} else {
|
||||||
|
// Beyond preload → read from physical disk
|
||||||
|
self.read_from_disk(block_i, chunk)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(buffer.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_from_disk(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<()> {
|
||||||
|
// Try to open the physical disk if not already open
|
||||||
|
if self.disk_handle.is_none() {
|
||||||
|
// Try common disk scheme paths
|
||||||
|
for path in &["/scheme/disk/0", "/scheme/disk/1"] {
|
||||||
|
if let Ok(file) = OpenOptions::new().read(true).open(path) {
|
||||||
|
self.disk_handle = Some(file);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut disk) = self.disk_handle {
|
||||||
|
// Seek to the correct block (accounting for partition offset)
|
||||||
|
let abs_block = self.disk_block + block;
|
||||||
|
disk.read_at(buffer, abs_block * self.block_size() as u64)
|
||||||
|
.map_err(|_| syscall::Error::new(EIO))?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
// No disk available yet — return what we have from preload
|
||||||
|
// (fill with zeros for regions not in preload)
|
||||||
|
buffer.fill(0);
|
||||||
|
Err(syscall::Error::new(EIO))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Problem with this approach:** `lived` starts before `ahcid` (it's at priority 10 in
|
||||||
|
init.initfs.d, while ahcid is at priority 40). So when lived first starts, there IS no
|
||||||
|
`/scheme/disk/0` to fall back to. The disk fallback would only work after ahcid initializes.
|
||||||
|
|
||||||
|
### 4.3 Fix 3: Two-Stage Mount (Recommended)
|
||||||
|
|
||||||
|
The cleanest fix is to change the init sequence:
|
||||||
|
|
||||||
|
**Stage 1: lived serves the preloaded buffer (for early boot)**
|
||||||
|
- lived starts as before, serves the preload via `scheme:disk.live`
|
||||||
|
- RedoxFS does NOT mount from `disk.live` for the root filesystem
|
||||||
|
- The initfs has everything needed for early boot (lived, ahcid, basic tools)
|
||||||
|
|
||||||
|
**Stage 2: Mount from physical disk (after drivers start)**
|
||||||
|
- After `40_drivers.target` completes, ahcid has registered `/scheme/disk/0`
|
||||||
|
- Init runs `redoxfs --uuid $REDOXFS_UUID file $REDOXFS_BLOCK` pointing to `/scheme/disk/0`
|
||||||
|
- This reads the full filesystem from the physical disk
|
||||||
|
|
||||||
|
**Current init flow:**
|
||||||
|
```
|
||||||
|
10_lived.service → starts lived (scheme:disk.live)
|
||||||
|
40_drivers.target → starts ahcid (scheme:disk/0)
|
||||||
|
50_rootfs.service → redoxfs mounts from... whichever disk scheme it finds first
|
||||||
|
(scans all /scheme/disk/* for matching UUID)
|
||||||
|
```
|
||||||
|
|
||||||
|
**The issue is timing:** `50_rootfs.service` requires `40_drivers.target`, so it should
|
||||||
|
wait for ahcid. But `redoxfs` scans ALL disk schemes, and `disk.live` matches first
|
||||||
|
(since lived starts earlier). RedoxFS finds the UUID in `disk.live` and tries to mount
|
||||||
|
from it, but the disk is too small.
|
||||||
|
|
||||||
|
**Proposed fix:**
|
||||||
|
|
||||||
|
1. **Make lived report the full filesystem size** by reading the RedoxFS header from
|
||||||
|
the preload buffer to determine `total_size`. Report that as `size()`.
|
||||||
|
|
||||||
|
2. **Make lived fall through to disk reads** for out-of-bounds regions. Use a lazy-open
|
||||||
|
approach: when a read goes beyond the preload and no disk handle is open yet, try
|
||||||
|
to open `/scheme/disk/0`. If it fails, return EIO (which RedoxFS will retry).
|
||||||
|
|
||||||
|
3. **Reduce the preload** in the bootloader. Since lived now handles disk fallback,
|
||||||
|
we can preload much less (e.g., 4-64 MiB). The preload just needs to cover the
|
||||||
|
RedoxFS header and enough metadata for the initial mount.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. Recommended Implementation Order
|
||||||
|
|
||||||
|
### Step 1: Fix lived to report full size + disk fallback (base patch)
|
||||||
|
|
||||||
|
Create `local/patches/base/P59-lived-disk-fallback.patch`:
|
||||||
|
|
||||||
|
1. Add `total_size: u64` field to LiveDisk
|
||||||
|
2. Parse RedoxFS header from preload buffer to determine total filesystem size
|
||||||
|
3. Report `total_size` from `size()` instead of `preload.len()`
|
||||||
|
4. For reads beyond preload: attempt to open and read from `/scheme/disk/0`
|
||||||
|
5. Keep overlay for writes
|
||||||
|
6. Keep block_size = 512 (from P6)
|
||||||
|
7. Add env var `DISK_PHYS_BLOCK` for the partition offset on the physical disk
|
||||||
|
|
||||||
|
### Step 2: Reduce bootloader preload cap (bootloader patch)
|
||||||
|
|
||||||
|
Create `local/patches/bootloader/P1-reduce-live-preload.patch`:
|
||||||
|
|
||||||
|
1. Change `max_preload` from 1024 MiB to a calculated minimum:
|
||||||
|
- Read the RedoxFS header to determine filesystem size
|
||||||
|
- Calculate the minimum preload needed: max(header + allocator extent, 4 MiB)
|
||||||
|
- Cap at 128 MiB (generous upper bound for metadata region)
|
||||||
|
2. Add `DISK_PHYS_BLOCK` env var so lived knows where the partition starts on disk
|
||||||
|
|
||||||
|
### Step 3: Verify
|
||||||
|
|
||||||
|
1. Build and test redbear-full ISO in QEMU with virtio-gpu
|
||||||
|
2. Verify RedoxFS mounts the full 4093 MiB filesystem
|
||||||
|
3. Verify login prompt appears
|
||||||
|
4. Verify KDE desktop loads (or at minimum, the greeter starts)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Risk Assessment
|
||||||
|
|
||||||
|
| Risk | Impact | Mitigation |
|
||||||
|
|------|--------|------------|
|
||||||
|
| RedoxFS header format changes between versions | lived parses header incorrectly | Use the same header parsing code as RedoxFS lib |
|
||||||
|
| ahcid not started when lived first needs disk | Read fails with ENOENT | Retry with backoff; RedoxFS mount retries automatically |
|
||||||
|
| Physical disk block offset wrong | Read corrupt data | Pass exact block offset from bootloader via env var |
|
||||||
|
| Preload too small for RedoxFS to find header | Mount fails immediately | Keep minimum preload at 4 MiB (covers any superblock) |
|
||||||
|
| Mini ISO regression | Small images broken | Test mini ISO after every change |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Alternative Approach: Mount From Physical Disk Directly
|
||||||
|
|
||||||
|
Instead of fixing lived, we could modify the init sequence to skip `disk.live` entirely
|
||||||
|
for the root filesystem mount:
|
||||||
|
|
||||||
|
1. Bootloader preloads just enough for kernel + initfs (no change needed)
|
||||||
|
2. lived starts but is only used for early boot I/O
|
||||||
|
3. `50_rootfs.service` is changed to explicitly mount from `/scheme/disk/0` (via ahcid)
|
||||||
|
instead of scanning all disk schemes
|
||||||
|
4. This requires passing the disk path and block offset from bootloader to init
|
||||||
|
|
||||||
|
**Pros:** Simpler lived (no disk fallback), cleaner architecture
|
||||||
|
**Cons:** Requires knowing which disk scheme serves the boot device; may not work if
|
||||||
|
the AHCI driver assigns a different number to the boot disk
|
||||||
|
|
||||||
|
**Verdict:** Fix 3 (lived with disk fallback) is more robust because it works regardless
|
||||||
|
of which disk scheme is assigned. The lived approach acts as a transparent cache layer.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Implementation Notes
|
||||||
|
|
||||||
|
### Bootloader env vars (current)
|
||||||
|
|
||||||
|
```
|
||||||
|
DISK_LIVE_ADDR=<hex phys addr of preload buffer>
|
||||||
|
DISK_LIVE_SIZE=<hex size of preload buffer>
|
||||||
|
REDOXFS_BLOCK=0 (always 0 for live mode)
|
||||||
|
REDOXFS_UUID=<uuid>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bootloader env vars (proposed additions)
|
||||||
|
|
||||||
|
```
|
||||||
|
DISK_PHYS_BLOCK=<hex block offset of partition on physical disk>
|
||||||
|
REDOXFS_FULL_SIZE=<hex total filesystem size>
|
||||||
|
```
|
||||||
|
|
||||||
|
### lived env vars (current)
|
||||||
|
|
||||||
|
```
|
||||||
|
DISK_LIVE_ADDR → phys addr to mmap
|
||||||
|
DISK_LIVE_SIZE → size to mmap (= preload size, NOT total filesystem size)
|
||||||
|
```
|
||||||
|
|
||||||
|
### lived env vars (proposed)
|
||||||
|
|
||||||
|
```
|
||||||
|
DISK_LIVE_ADDR → phys addr of preload buffer
|
||||||
|
DISK_LIVE_SIZE → size of preload buffer
|
||||||
|
DISK_PHYS_BLOCK → block offset for disk fallback reads
|
||||||
|
REDOXFS_FULL_SIZE → total filesystem size (for size() reporting)
|
||||||
|
```
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
diff --git a/init.initfs.d/50_rootfs.service b/init.initfs.d/50_rootfs.service
|
||||||
|
index db7ba429..59f2c61c 100644
|
||||||
|
--- a/init.initfs.d/50_rootfs.service
|
||||||
|
+++ b/init.initfs.d/50_rootfs.service
|
||||||
|
@@ -7 +7 @@ cmd = "redoxfs"
|
||||||
|
-args = ["--uuid" ,"$REDOXFS_UUID", "file", "$REDOXFS_BLOCK"]
|
||||||
|
+args = ["--uuid" ,"$REDOXFS_UUID", "file"]
|
||||||
@@ -0,0 +1,248 @@
|
|||||||
|
diff --git a/drivers/storage/lived/src/main.rs b/drivers/storage/lived/src/main.rs
|
||||||
|
index 2ca1ff27..8582e42a 100644
|
||||||
|
--- a/drivers/storage/lived/src/main.rs
|
||||||
|
+++ b/drivers/storage/lived/src/main.rs
|
||||||
|
@@ -1,0 +2,8 @@
|
||||||
|
+//!
|
||||||
|
+//! For live ISO boot: bootloader preloads the first N MiB of the filesystem into RAM.
|
||||||
|
+//! This daemon serves that preloaded region from RAM, and falls through to the physical
|
||||||
|
+//! disk (USB, AHCI, NVMe) for reads beyond the preload boundary.
|
||||||
|
+//!
|
||||||
|
+//! Boot order: lived(10) → drivers(40) → usbscsid(45) → rootfs(50)
|
||||||
|
+//! Since drivers load AFTER lived starts, the disk fallback is lazy: the physical disk
|
||||||
|
+//! handle is opened on the first out-of-range read, with retry backoff.
|
||||||
|
@@ -4,0 +13 @@
|
||||||
|
+use std::cell::RefCell;
|
||||||
|
@@ -7 +15,0 @@ use std::fs::File;
|
||||||
|
-
|
||||||
|
@@ -8,0 +17 @@ use std::os::fd::AsRawFd;
|
||||||
|
+use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@@ -19,0 +29,11 @@ use anyhow::{anyhow, Context};
|
||||||
|
+/// Block size must be 512 (redoxfs BLOCK_SIZE), not PAGE_SIZE.
|
||||||
|
+/// DiskWrapper::read rejects buffers not aligned to block_size, and redoxfs reads
|
||||||
|
+/// in 512-byte chunks.
|
||||||
|
+const BLOCK_SIZE: usize = 512;
|
||||||
|
+
|
||||||
|
+/// Maximum retries for opening the physical disk before giving up.
|
||||||
|
+/// Drivers (xhcid → usbscsid → /scheme/disk/) load between service 40-45,
|
||||||
|
+/// while lived starts at 10. Give plenty of retries.
|
||||||
|
+const DISK_OPEN_MAX_RETRIES: u32 = 60;
|
||||||
|
+const DISK_OPEN_RETRY_INTERVAL_MS: u64 = 500;
|
||||||
|
+
|
||||||
|
@@ -22 +41,0 @@ struct LiveDisk {
|
||||||
|
- //TODO: drop overlay blocks if they match the original
|
||||||
|
@@ -23,0 +43,4 @@ struct LiveDisk {
|
||||||
|
+ full_size: u64,
|
||||||
|
+ disk_phys_offset: u64,
|
||||||
|
+ disk_file: RefCell<Option<File>>,
|
||||||
|
+ logged_first_fallback: AtomicBool,
|
||||||
|
@@ -27 +50,6 @@ impl LiveDisk {
|
||||||
|
- fn new(phys: usize, size: usize) -> anyhow::Result<LiveDisk> {
|
||||||
|
+ fn new(
|
||||||
|
+ phys: usize,
|
||||||
|
+ preload_size: usize,
|
||||||
|
+ full_size: u64,
|
||||||
|
+ disk_phys_offset: u64,
|
||||||
|
+ ) -> anyhow::Result<LiveDisk> {
|
||||||
|
@@ -30,2 +58,2 @@ impl LiveDisk {
|
||||||
|
- .checked_add(size)
|
||||||
|
- .context("phys + size overflow")?
|
||||||
|
+ .checked_add(preload_size)
|
||||||
|
+ .context("phys + preload_size overflow")?
|
||||||
|
@@ -33 +61 @@ impl LiveDisk {
|
||||||
|
- let size = end - start;
|
||||||
|
+ let mapped_size = end - start;
|
||||||
|
@@ -41 +69 @@ impl LiveDisk {
|
||||||
|
- length: size,
|
||||||
|
+ length: mapped_size,
|
||||||
|
@@ -47 +75 @@ impl LiveDisk {
|
||||||
|
- std::slice::from_raw_parts_mut(base as *mut u8, size)
|
||||||
|
+ std::slice::from_raw_parts_mut(base as *mut u8, mapped_size)
|
||||||
|
@@ -49,0 +78,7 @@ impl LiveDisk {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: preload {} MiB, full filesystem {} MiB, disk_phys_offset {:#x}",
|
||||||
|
+ preload_size / (1024 * 1024),
|
||||||
|
+ full_size / (1024 * 1024),
|
||||||
|
+ disk_phys_offset,
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
@@ -52,0 +88,4 @@ impl LiveDisk {
|
||||||
|
+ full_size,
|
||||||
|
+ disk_phys_offset,
|
||||||
|
+ disk_file: RefCell::new(None),
|
||||||
|
+ logged_first_fallback: AtomicBool::new(false),
|
||||||
|
@@ -54,0 +94,69 @@ impl LiveDisk {
|
||||||
|
+
|
||||||
|
+ fn open_disk(&self) -> syscall::Result<()> {
|
||||||
|
+ if self.disk_file.borrow().is_some() {
|
||||||
|
+ return Ok(());
|
||||||
|
+ }
|
||||||
|
+ match self.try_open_disk() {
|
||||||
|
+ Ok(file) => {
|
||||||
|
+ *self.disk_file.borrow_mut() = Some(file);
|
||||||
|
+ Ok(())
|
||||||
|
+ }
|
||||||
|
+ Err(msg) => {
|
||||||
|
+ eprintln!("lived: disk fallback unavailable: {}", msg);
|
||||||
|
+ Err(syscall::Error::new(EIO))
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fn try_open_disk(&self) -> Result<File, String> {
|
||||||
|
+ // Try common disk scheme paths. USB boot appears as /scheme/disk/0 or /scheme/usbscsi/0.
|
||||||
|
+ // AHCI boot appears as /scheme/disk/0. NVMe appears as /scheme/disk/0.
|
||||||
|
+ let candidates = [
|
||||||
|
+ "/scheme/disk/0",
|
||||||
|
+ "/scheme/usbscsi/0",
|
||||||
|
+ "/scheme/disk/1",
|
||||||
|
+ "/scheme/usbscsi/1",
|
||||||
|
+ ];
|
||||||
|
+
|
||||||
|
+ for attempt in 0..DISK_OPEN_MAX_RETRIES {
|
||||||
|
+ for path in &candidates {
|
||||||
|
+ if let Ok(file) = File::open(path) {
|
||||||
|
+ eprintln!("lived: opened physical disk at {} (attempt {})", path, attempt + 1);
|
||||||
|
+ return Ok(file);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if attempt < DISK_OPEN_MAX_RETRIES - 1 {
|
||||||
|
+ std::thread::sleep(std::time::Duration::from_millis(DISK_OPEN_RETRY_INTERVAL_MS));
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ Err(format!(
|
||||||
|
+ "no /scheme/disk/ found after {} retries",
|
||||||
|
+ DISK_OPEN_MAX_RETRIES
|
||||||
|
+ ))
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fn read_from_disk(&self, offset: u64, buffer: &mut [u8]) -> syscall::Result<usize> {
|
||||||
|
+ let disk_offset = self.disk_phys_offset + offset;
|
||||||
|
+
|
||||||
|
+ if !self.logged_first_fallback.swap(true, Ordering::Relaxed) {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: first disk fallback read at offset {} MiB (disk offset {:#x})",
|
||||||
|
+ offset / (1024 * 1024),
|
||||||
|
+ disk_offset,
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ self.open_disk()?;
|
||||||
|
+
|
||||||
|
+ use std::io::{Read, Seek, SeekFrom};
|
||||||
|
+ let mut disk = self.disk_file.borrow_mut();
|
||||||
|
+ let file = disk.as_mut().unwrap();
|
||||||
|
+ file.seek(SeekFrom::Start(disk_offset))
|
||||||
|
+ .map_err(|_| syscall::Error::new(EIO))?;
|
||||||
|
+ file.read_exact(buffer)
|
||||||
|
+ .map_err(|_| syscall::Error::new(EIO))?;
|
||||||
|
+
|
||||||
|
+ Ok(buffer.len())
|
||||||
|
+ }
|
||||||
|
@@ -59 +167 @@ impl Disk for LiveDisk {
|
||||||
|
- PAGE_SIZE as u32
|
||||||
|
+ BLOCK_SIZE as u32
|
||||||
|
@@ -63 +171 @@ impl Disk for LiveDisk {
|
||||||
|
- self.original.len() as u64
|
||||||
|
+ self.full_size
|
||||||
|
@@ -67,2 +175,4 @@ impl Disk for LiveDisk {
|
||||||
|
- let mut offset = (block as usize) * PAGE_SIZE;
|
||||||
|
- if offset + buffer.len() > self.original.len() {
|
||||||
|
+ let bs = self.block_size() as usize;
|
||||||
|
+ let mut offset = (block as usize) * bs;
|
||||||
|
+
|
||||||
|
+ if offset + buffer.len() > self.full_size as usize {
|
||||||
|
@@ -71 +181,28 @@ impl Disk for LiveDisk {
|
||||||
|
- for chunk in buffer.chunks_mut(PAGE_SIZE) {
|
||||||
|
+
|
||||||
|
+ let preload_len = self.original.len();
|
||||||
|
+
|
||||||
|
+ if offset + buffer.len() <= preload_len {
|
||||||
|
+ for chunk in buffer.chunks_mut(bs) {
|
||||||
|
+ match self.overlay.get(&block) {
|
||||||
|
+ Some(overlay) => {
|
||||||
|
+ chunk.copy_from_slice(&overlay[..chunk.len()]);
|
||||||
|
+ }
|
||||||
|
+ None => {
|
||||||
|
+ chunk.copy_from_slice(&self.original[offset..offset + chunk.len()]);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ block += 1;
|
||||||
|
+ offset += bs;
|
||||||
|
+ }
|
||||||
|
+ return Ok(buffer.len());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if offset >= preload_len {
|
||||||
|
+ let fs_byte_offset = (block as u64) * bs as u64;
|
||||||
|
+ return self.read_from_disk(fs_byte_offset, buffer);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let preload_remaining = preload_len - offset;
|
||||||
|
+ let (ram_part, disk_part) = buffer.split_at_mut(preload_remaining);
|
||||||
|
+
|
||||||
|
+ for chunk in ram_part.chunks_mut(bs) {
|
||||||
|
@@ -81 +218 @@ impl Disk for LiveDisk {
|
||||||
|
- offset += PAGE_SIZE;
|
||||||
|
+ offset += bs;
|
||||||
|
@@ -82,0 +220,4 @@ impl Disk for LiveDisk {
|
||||||
|
+
|
||||||
|
+ let disk_fs_offset = (block as u64) * bs as u64;
|
||||||
|
+ self.read_from_disk(disk_fs_offset, disk_part)?;
|
||||||
|
+
|
||||||
|
@@ -87,2 +228,3 @@ impl Disk for LiveDisk {
|
||||||
|
- let mut offset = (block as usize) * PAGE_SIZE;
|
||||||
|
- if offset + buffer.len() > self.original.len() {
|
||||||
|
+ let bs = self.block_size() as usize;
|
||||||
|
+ let mut offset = (block as usize) * bs;
|
||||||
|
+ if offset + buffer.len() > self.full_size as usize {
|
||||||
|
@@ -91 +233 @@ impl Disk for LiveDisk {
|
||||||
|
- for chunk in buffer.chunks(PAGE_SIZE) {
|
||||||
|
+ for chunk in buffer.chunks(bs) {
|
||||||
|
@@ -93,2 +235,3 @@ impl Disk for LiveDisk {
|
||||||
|
- let offset = (block as usize) * PAGE_SIZE;
|
||||||
|
- self.original[offset..offset + PAGE_SIZE]
|
||||||
|
+ let off = (block as usize) * bs;
|
||||||
|
+ if off + bs <= self.original.len() {
|
||||||
|
+ self.original[off..off + bs]
|
||||||
|
@@ -96,0 +240,3 @@ impl Disk for LiveDisk {
|
||||||
|
+ } else {
|
||||||
|
+ vec![0u8; bs].into_boxed_slice()
|
||||||
|
+ }
|
||||||
|
@@ -100 +246 @@ impl Disk for LiveDisk {
|
||||||
|
- offset += PAGE_SIZE;
|
||||||
|
+ offset += bs;
|
||||||
|
@@ -112 +258,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
- let mut size = 0;
|
||||||
|
+ let mut preload_size = 0;
|
||||||
|
+ let mut full_size = 0u64;
|
||||||
|
+ let mut disk_phys_offset = 0u64;
|
||||||
|
@@ -129 +277 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
- size = usize::from_str_radix(value, 16).unwrap_or(0);
|
||||||
|
+ preload_size = usize::from_str_radix(value, 16).unwrap_or(0);
|
||||||
|
@@ -130,0 +279,3 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
+
|
||||||
|
+ if name == "REDOXFS_FULL_SIZE" {
|
||||||
|
+ full_size = u64::from_str_radix(value, 16).unwrap_or(0);
|
||||||
|
@@ -133,2 +284,6 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
- if phys == 0 || size == 0 {
|
||||||
|
- // No live disk data, no need to say anything or exit with
|
||||||
|
+ if name == "DISK_PHYS_BLOCK" {
|
||||||
|
+ disk_phys_offset = u64::from_str_radix(value, 16).unwrap_or(0) * BLOCK_SIZE as u64;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if phys == 0 || preload_size == 0 {
|
||||||
|
@@ -138,0 +294,4 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
+ if full_size == 0 {
|
||||||
|
+ full_size = preload_size as u64;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
@@ -152 +311 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
- LiveDisk::new(phys, size).unwrap_or_else(|err| {
|
||||||
|
+ LiveDisk::new(phys, preload_size, full_size, disk_phys_offset).unwrap_or_else(|err| {
|
||||||
|
@@ -160 +319 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||||
|
- libredox::call::setrens(0, 0).expect("nvmed: failed to enter null namespace");
|
||||||
|
+ libredox::call::setrens(0, 0).expect("lived: failed to enter null namespace");
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
--- a/drivers/storage/lived/src/main.rs
|
||||||
|
+++ b/drivers/storage/lived/src/main.rs
|
||||||
|
@@ -45 +45 @@
|
||||||
|
- disk_file: RefCell<Option<File>>,
|
||||||
|
+ disk_path: RefCell<Option<String>>,
|
||||||
|
@@ -90 +90 @@
|
||||||
|
- disk_file: RefCell::new(None),
|
||||||
|
+ disk_path: RefCell::new(None),
|
||||||
|
@@ -96 +96 @@
|
||||||
|
- if self.disk_file.borrow().is_some() {
|
||||||
|
+ if self.disk_path.borrow().is_some() {
|
||||||
|
@@ -100,2 +100,2 @@
|
||||||
|
- Ok(file) => {
|
||||||
|
- *self.disk_file.borrow_mut() = Some(file);
|
||||||
|
+ Ok(path) => {
|
||||||
|
+ *self.disk_path.borrow_mut() = Some(path);
|
||||||
|
@@ -111,10 +111 @@
|
||||||
|
- fn try_open_disk(&self) -> Result<File, String> {
|
||||||
|
- // Try common disk scheme paths. USB boot appears as /scheme/disk/0 or /scheme/usbscsi/0.
|
||||||
|
- // AHCI boot appears as /scheme/disk/0. NVMe appears as /scheme/disk/0.
|
||||||
|
- let candidates = [
|
||||||
|
- "/scheme/disk/0",
|
||||||
|
- "/scheme/usbscsi/0",
|
||||||
|
- "/scheme/disk/1",
|
||||||
|
- "/scheme/usbscsi/1",
|
||||||
|
- ];
|
||||||
|
-
|
||||||
|
+ fn try_open_disk(&self) -> Result<String, String> {
|
||||||
|
@@ -122,4 +113,70 @@
|
||||||
|
- for path in &candidates {
|
||||||
|
- if let Ok(file) = File::open(path) {
|
||||||
|
- eprintln!("lived: opened physical disk at {} (attempt {})", path, attempt + 1);
|
||||||
|
- return Ok(file);
|
||||||
|
+ if let Ok(entries) = std::fs::read_dir("/scheme") {
|
||||||
|
+ let all_schemes: Vec<String> = entries
|
||||||
|
+ .flatten()
|
||||||
|
+ .map(|e| e.file_name().to_string_lossy().to_string())
|
||||||
|
+ .collect();
|
||||||
|
+ let has_disk = all_schemes
|
||||||
|
+ .iter()
|
||||||
|
+ .any(|s| s.starts_with("disk.") && s != "disk.live");
|
||||||
|
+ if attempt == 0 || attempt == DISK_OPEN_MAX_RETRIES - 1 || has_disk {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: attempt {} /scheme/ = {:?} (has_disk={})",
|
||||||
|
+ attempt + 1,
|
||||||
|
+ all_schemes,
|
||||||
|
+ has_disk
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ for name_str in &all_schemes {
|
||||||
|
+ if name_str.starts_with("disk.") && name_str != "disk.live" {
|
||||||
|
+ for idx in [0u32, 2, 1, 3, 4, 5] {
|
||||||
|
+ let path = format!("/scheme/{}/{}", name_str, idx);
|
||||||
|
+ if let Ok(mut file) = File::open(&path) {
|
||||||
|
+ use std::io::{Read, Seek, SeekFrom};
|
||||||
|
+ let test_offset = self.disk_phys_offset + self.full_size - 4096;
|
||||||
|
+ let mut probe = vec![0u8; 4096];
|
||||||
|
+ if file.seek(SeekFrom::Start(test_offset)).is_err() {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: skipping {} — seek to {:#x} failed",
|
||||||
|
+ path, test_offset
|
||||||
|
+ );
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ match file.read_exact(&mut probe) {
|
||||||
|
+ Ok(()) => {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: validated physical disk at {} (attempt {}, verified at end {:#x})",
|
||||||
|
+ path,
|
||||||
|
+ attempt + 1,
|
||||||
|
+ test_offset
|
||||||
|
+ );
|
||||||
|
+ return Ok(path);
|
||||||
|
+ }
|
||||||
|
+ Err(e) => {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: skipping {} — read at {:#x}: {}",
|
||||||
|
+ path, test_offset, e
|
||||||
|
+ );
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ } else if attempt == 0 {
|
||||||
|
+ eprintln!("lived: {} not openable", path);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ let path_root = format!("/scheme/{}", name_str);
|
||||||
|
+ if let Ok(mut file) = File::open(&path_root) {
|
||||||
|
+ use std::io::{Read, Seek, SeekFrom};
|
||||||
|
+ let test_offset = self.disk_phys_offset + self.full_size - 4096;
|
||||||
|
+ let mut probe = vec![0u8; 4096];
|
||||||
|
+ if file.seek(SeekFrom::Start(test_offset)).is_ok()
|
||||||
|
+ && file.read_exact(&mut probe).is_ok()
|
||||||
|
+ {
|
||||||
|
+ eprintln!(
|
||||||
|
+ "lived: validated physical disk at {} (attempt {})",
|
||||||
|
+ path_root,
|
||||||
|
+ attempt + 1
|
||||||
|
+ );
|
||||||
|
+ return Ok(path_root);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
@@ -152,0 +210,4 @@
|
||||||
|
+ let path = self.disk_path.borrow();
|
||||||
|
+ let disk_path = path.as_ref().unwrap();
|
||||||
|
+ let mut file = File::open(disk_path).map_err(|_| syscall::Error::new(EIO))?;
|
||||||
|
+
|
||||||
|
@@ -154,2 +214,0 @@
|
||||||
|
- let mut disk = self.disk_file.borrow_mut();
|
||||||
|
- let file = disk.as_mut().unwrap();
|
||||||
|
@@ -319,2 +378,4 @@
|
||||||
|
- libredox::call::setrens(0, 0).expect("lived: failed to enter null namespace");
|
||||||
|
-
|
||||||
|
+ // Lived must NOT call setrens(0, 0). The null namespace only contains
|
||||||
|
+ // "memory" and "pipe" (see relibc redox_setrens_v1). Lived needs
|
||||||
|
+ // ongoing access to /scheme/ for disk scheme discovery after storage
|
||||||
|
+ // drivers register their schemes asynchronously.
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
diff --git a/logd/src/scheme.rs b/logd/src/scheme.rs
|
||||||
|
index 070de3d6..f5c1549a 100644
|
||||||
|
--- a/logd/src/scheme.rs
|
||||||
|
+++ b/logd/src/scheme.rs
|
||||||
|
@@ -1,2 +1,2 @@
|
||||||
|
-use std::collections::{BTreeMap, VecDeque};
|
||||||
|
-use std::fs::{File, OpenOptions};
|
||||||
|
+use std::collections::{BTreeMap, HashMap, VecDeque};
|
||||||
|
+use std::fs::{File, OpenOptions, rename};
|
||||||
|
@@ -5,0 +6 @@ use std::os::fd::{FromRawFd, RawFd};
|
||||||
|
+use std::path::PathBuf;
|
||||||
|
@@ -6,0 +8 @@ use std::sync::mpsc::{self, Sender};
|
||||||
|
+use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
@@ -13,0 +16,5 @@ use syscall::schemev2::NewFdFlags;
|
||||||
|
+const LOG_DIR: &str = "/var/log";
|
||||||
|
+const MAX_LOG_SIZE: u64 = 10 * 1024 * 1024;
|
||||||
|
+const MAX_ROTATED_FILES: u32 = 5;
|
||||||
|
+const MEMORY_LOG_LIMIT: usize = 1000;
|
||||||
|
+
|
||||||
|
@@ -31 +38 @@ enum OutputCmd {
|
||||||
|
- Log(Vec<u8>),
|
||||||
|
+ Log { context: String, line: Vec<u8> },
|
||||||
|
@@ -34,0 +42,96 @@ enum OutputCmd {
|
||||||
|
+fn json_escape(s: &str) -> String {
|
||||||
|
+ let mut out = String::with_capacity(s.len());
|
||||||
|
+ for c in s.chars() {
|
||||||
|
+ match c {
|
||||||
|
+ '\\' => out.push_str("\\\\"),
|
||||||
|
+ '"' => out.push_str("\\\""),
|
||||||
|
+ '\n' => out.push_str("\\n"),
|
||||||
|
+ '\r' => out.push_str("\\r"),
|
||||||
|
+ '\t' => out.push_str("\\t"),
|
||||||
|
+ c if c.is_control() => out.push_str(&format!("\\u{:04x}", c as u32)),
|
||||||
|
+ c => out.push(c),
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ out
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+fn format_json_line(context: &str, line: &[u8]) -> Vec<u8> {
|
||||||
|
+ let now = SystemTime::now()
|
||||||
|
+ .duration_since(UNIX_EPOCH)
|
||||||
|
+ .unwrap_or_default();
|
||||||
|
+ let secs = now.as_secs();
|
||||||
|
+ let timestamp = format!(
|
||||||
|
+ "{:04}-{:02}-{:02}T{:02}:{:02}:{:02}Z",
|
||||||
|
+ 1970 + secs / 31_557_600,
|
||||||
|
+ (secs % 31_557_600) / 2_592_000 + 1,
|
||||||
|
+ (secs % 2_592_000) / 86_400 + 1,
|
||||||
|
+ (secs % 86_400) / 3600,
|
||||||
|
+ (secs % 3600) / 60,
|
||||||
|
+ secs % 60
|
||||||
|
+ );
|
||||||
|
+ let text = String::from_utf8_lossy(line).trim_end_matches('\n').to_string();
|
||||||
|
+ let (source, message) = match text.split_once(": ") {
|
||||||
|
+ Some((s, m)) => (s, m),
|
||||||
|
+ None => (context, text.as_str()),
|
||||||
|
+ };
|
||||||
|
+ let json = format!(
|
||||||
|
+ "{{\"timestamp\":\"{}\",\"source\":\"{}\",\"message\":\"{}\"}}\n",
|
||||||
|
+ json_escape(×tamp),
|
||||||
|
+ json_escape(source),
|
||||||
|
+ json_escape(message)
|
||||||
|
+ );
|
||||||
|
+ json.into_bytes()
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct LogFile {
|
||||||
|
+ file: File,
|
||||||
|
+ path: PathBuf,
|
||||||
|
+ bytes_written: u64,
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+impl LogFile {
|
||||||
|
+ fn open(path: PathBuf) -> std::io::Result<Self> {
|
||||||
|
+ let file = OpenOptions::new()
|
||||||
|
+ .create(true)
|
||||||
|
+ .append(true)
|
||||||
|
+ .open(&path)?;
|
||||||
|
+ let metadata = file.metadata()?;
|
||||||
|
+ Ok(LogFile {
|
||||||
|
+ file,
|
||||||
|
+ path,
|
||||||
|
+ bytes_written: metadata.len(),
|
||||||
|
+ })
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fn write(&mut self, data: &[u8]) -> std::io::Result<()> {
|
||||||
|
+ self.file.write_all(data)?;
|
||||||
|
+ self.file.flush()?;
|
||||||
|
+ self.bytes_written += data.len() as u64;
|
||||||
|
+ Ok(())
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fn maybe_rotate(&mut self) -> std::io::Result<()> {
|
||||||
|
+ if self.bytes_written < MAX_LOG_SIZE {
|
||||||
|
+ return Ok(());
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ drop(std::mem::replace(&mut self.file, unsafe { File::from_raw_fd(-1) }));
|
||||||
|
+
|
||||||
|
+ for i in (1..MAX_ROTATED_FILES).rev() {
|
||||||
|
+ let old_path = self.path.with_extension(format!("log.{}", i));
|
||||||
|
+ let new_path = self.path.with_extension(format!("log.{}", i + 1));
|
||||||
|
+ let _ = rename(&old_path, &new_path);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let backup_path = self.path.with_extension("log.1");
|
||||||
|
+ let _ = rename(&self.path, &backup_path);
|
||||||
|
+
|
||||||
|
+ self.file = OpenOptions::new()
|
||||||
|
+ .create(true)
|
||||||
|
+ .append(true)
|
||||||
|
+ .open(&self.path)?;
|
||||||
|
+ self.bytes_written = 0;
|
||||||
|
+ Ok(())
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
@@ -43,0 +147,13 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
+ let _ = std::fs::create_dir_all("/var/log");
|
||||||
|
+ let persistent_log: Option<File> = OpenOptions::new()
|
||||||
|
+ .create(true)
|
||||||
|
+ .append(true)
|
||||||
|
+ .open("/var/log/system.log")
|
||||||
|
+ .ok();
|
||||||
|
+ let mut service_logs: HashMap<String, LogFile> = HashMap::new();
|
||||||
|
+
|
||||||
|
+ let _ = std::fs::create_dir_all(LOG_DIR);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ let json_format = std::env::var("LOGD_JSON").map_or(false, |v| v == "1");
|
||||||
|
+
|
||||||
|
@@ -48,0 +165,5 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
+ let mut persistent = persistent_log;
|
||||||
|
+ if let Some(ref mut f) = persistent {
|
||||||
|
+ let _ = f.write(b"--- logd started ---
|
||||||
|
+");
|
||||||
|
+ }
|
||||||
|
@@ -51 +172,32 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- OutputCmd::Log(line) => {
|
||||||
|
+ OutputCmd::Log { context, line } => {
|
||||||
|
+ let out_line = if json_format {
|
||||||
|
+ format_json_line(&context, &line)
|
||||||
|
+ } else {
|
||||||
|
+ line.clone()
|
||||||
|
+ };
|
||||||
|
+ if let Some(ref mut f) = persistent {
|
||||||
|
+ let _ = f.write(&out_line);
|
||||||
|
+ let _ = f.flush();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let service_name = context.split(':').next().unwrap_or("unknown");
|
||||||
|
+ if !service_name.is_empty() {
|
||||||
|
+ let log_path = PathBuf::from(LOG_DIR).join(format!("{}.log", service_name));
|
||||||
|
+ let entry = service_logs.entry(service_name.to_string()).or_insert_with(|| {
|
||||||
|
+ LogFile::open(log_path).unwrap_or_else(|_| {
|
||||||
|
+ LogFile::open(PathBuf::from("/dev/null")).unwrap()
|
||||||
|
+ })
|
||||||
|
+ });
|
||||||
|
+ let _ = entry.write(&out_line);
|
||||||
|
+ let _ = entry.maybe_rotate();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let system_path = PathBuf::from(LOG_DIR).join("system.log");
|
||||||
|
+ let system_entry = service_logs.entry("system".to_string()).or_insert_with(|| {
|
||||||
|
+ LogFile::open(system_path).unwrap_or_else(|_| {
|
||||||
|
+ LogFile::open(PathBuf::from("/dev/null")).unwrap()
|
||||||
|
+ })
|
||||||
|
+ });
|
||||||
|
+ let _ = system_entry.write(&out_line);
|
||||||
|
+ let _ = system_entry.maybe_rotate();
|
||||||
|
+
|
||||||
|
@@ -53 +205 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- let _ = file.write(&line);
|
||||||
|
+ let _ = file.write(&out_line);
|
||||||
|
@@ -56,3 +208,2 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- logs.push_back(line);
|
||||||
|
- // Keep a limited amount of logs for backfilling to bound memory usage
|
||||||
|
- while logs.len() > 1000 {
|
||||||
|
+ logs.push_back(out_line);
|
||||||
|
+ while logs.len() > MEMORY_LOG_LIMIT {
|
||||||
|
@@ -68 +218,0 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
-
|
||||||
|
@@ -83 +232,0 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- // FIXME currently possible as /scheme/log/kernel presents a snapshot of the log queue
|
||||||
|
@@ -118 +266,0 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- // Writing to the kernel debug log never blocks
|
||||||
|
@@ -124 +272,4 @@ impl<'sock> LogScheme<'sock> {
|
||||||
|
- .send(OutputCmd::Log(mem::take(handle_buf)))
|
||||||
|
+ .send(OutputCmd::Log {
|
||||||
|
+ context: context.to_string(),
|
||||||
|
+ line: mem::take(handle_buf),
|
||||||
|
+ })
|
||||||
|
@@ -173,3 +323,0 @@ impl<'sock> SchemeSync for LogScheme<'sock> {
|
||||||
|
-
|
||||||
|
- // TODO
|
||||||
|
-
|
||||||
|
@@ -244,3 +391,0 @@ impl<'sock> SchemeSync for LogScheme<'sock> {
|
||||||
|
-
|
||||||
|
- //TODO: flush remaining data?
|
||||||
|
-
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
diff --git a/src/main.rs b/src/main.rs
|
||||||
|
index 78dabb0..a41086e 100644
|
||||||
|
--- a/src/main.rs
|
||||||
|
+++ b/src/main.rs
|
||||||
|
@@ -557,0 +558 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
+ let disk_block = fs.block;
|
||||||
|
@@ -559 +560,13 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- print!("live: 0/{} MiB", size / MIBI as u64);
|
||||||
|
+ let max_preload: u64 = 128 * MIBI as u64;
|
||||||
|
+ let preload_size = if size > max_preload {
|
||||||
|
+ println!(
|
||||||
|
+ "live: filesystem is {} MiB, capping preload at {} MiB",
|
||||||
|
+ size / MIBI as u64,
|
||||||
|
+ max_preload / MIBI as u64
|
||||||
|
+ );
|
||||||
|
+ max_preload
|
||||||
|
+ } else {
|
||||||
|
+ size
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ print!("live: 0/{} MiB", preload_size / MIBI as u64);
|
||||||
|
@@ -561 +574 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- let live_size = match usize::try_from(size) {
|
||||||
|
+ let live_size = match usize::try_from(preload_size) {
|
||||||
|
@@ -593 +606 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- print!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||||
|
+ print!("\rlive: {}/{} MiB", i / MIBI as u64, preload_size / MIBI as u64);
|
||||||
|
@@ -600 +613,10 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- println!("\rlive: {}/{} MiB", i / MIBI as u64, size / MIBI as u64);
|
||||||
|
+ println!("\rlive: {}/{} MiB", i / MIBI as u64, preload_size / MIBI as u64);
|
||||||
|
+
|
||||||
|
+ if preload_size < size {
|
||||||
|
+ println!(
|
||||||
|
+ "live: preloaded {} MiB of {} MiB filesystem (remaining {} MiB from disk)",
|
||||||
|
+ preload_size / MIBI as u64,
|
||||||
|
+ size / MIBI as u64,
|
||||||
|
+ (size - preload_size) / MIBI as u64
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
@@ -613 +635 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- Some(live)
|
||||||
|
+ Some((disk_block, size, live))
|
||||||
|
@@ -672 +694 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- if let Some(live) = live_opt {
|
||||||
|
+ if let Some((disk_block, fs_size, live)) = live_opt {
|
||||||
|
@@ -674,0 +697,2 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
+ writeln!(w, "DISK_PHYS_BLOCK={:016x}", disk_block).unwrap();
|
||||||
|
+ writeln!(w, "REDOXFS_FULL_SIZE={:016x}", fs_size).unwrap();
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
diff --git a/src/arch/x86/x64.rs b/src/arch/x86/x64.rs
|
||||||
|
index a0a275a..cad4592 100644
|
||||||
|
--- a/src/arch/x86/x64.rs
|
||||||
|
+++ b/src/arch/x86/x64.rs
|
||||||
|
@@ -46 +46 @@ pub unsafe fn paging_create(os: &impl Os, kernel_phys: u64, kernel_size: u64) ->
|
||||||
|
- for pdp_i in 0..8 {
|
||||||
|
+ for pdp_i in 0..64 {
|
||||||
|
@@ -103 +103 @@ pub unsafe fn paging_framebuffer(
|
||||||
|
- if framebuffer_phys + framebuffer_size <= 0x2_0000_0000 {
|
||||||
|
+ if framebuffer_phys + framebuffer_size <= 0x10_0000_0000 {
|
||||||
|
diff --git a/src/main.rs b/src/main.rs
|
||||||
|
index a41086e..1ce4bf3 100644
|
||||||
|
--- a/src/main.rs
|
||||||
|
+++ b/src/main.rs
|
||||||
|
@@ -560,11 +560 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- let max_preload: u64 = 128 * MIBI as u64;
|
||||||
|
- let preload_size = if size > max_preload {
|
||||||
|
- println!(
|
||||||
|
- "live: filesystem is {} MiB, capping preload at {} MiB",
|
||||||
|
- size / MIBI as u64,
|
||||||
|
- max_preload / MIBI as u64
|
||||||
|
- );
|
||||||
|
- max_preload
|
||||||
|
- } else {
|
||||||
|
- size
|
||||||
|
- };
|
||||||
|
+ let mut preload_size: u64 = size;
|
||||||
|
@@ -572,4 +562,5 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- print!("live: 0/{} MiB", preload_size / MIBI as u64);
|
||||||
|
-
|
||||||
|
- let live_size = match usize::try_from(preload_size) {
|
||||||
|
- Ok(live_size) => live_size,
|
||||||
|
+ let mut ptr = ptr::null_mut();
|
||||||
|
+ if live {
|
||||||
|
+ ptr = os.alloc_zeroed_page_aligned(
|
||||||
|
+ match usize::try_from(preload_size) {
|
||||||
|
+ Ok(s) => s,
|
||||||
|
@@ -581 +572,19 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- };
|
||||||
|
+ }
|
||||||
|
+ );
|
||||||
|
+ if ptr.is_null() && live {
|
||||||
|
+ println!(
|
||||||
|
+ "\rlive: unable to allocate {} MiB, halving...",
|
||||||
|
+ preload_size / MIBI as u64
|
||||||
|
+ );
|
||||||
|
+ let floor: u64 = 128 * MIBI as u64;
|
||||||
|
+ while preload_size > floor {
|
||||||
|
+ preload_size /= 2;
|
||||||
|
+ if let Ok(smaller) = usize::try_from(preload_size) {
|
||||||
|
+ ptr = os.alloc_zeroed_page_aligned(smaller);
|
||||||
|
+ if !ptr.is_null() {
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
@@ -583,6 +592 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
- let ptr = if live {
|
||||||
|
- os.alloc_zeroed_page_aligned(live_size)
|
||||||
|
- } else {
|
||||||
|
- ptr::null_mut()
|
||||||
|
- };
|
||||||
|
- if live && ptr.is_null() {
|
||||||
|
+ if ptr.is_null() {
|
||||||
|
@@ -595,0 +600,11 @@ fn main(os: &impl Os) -> (usize, u64, KernelArgs) {
|
||||||
|
+ print!("live: 0/{} MiB", preload_size / MIBI as u64);
|
||||||
|
+
|
||||||
|
+ let live_size = match usize::try_from(preload_size) {
|
||||||
|
+ Ok(live_size) => live_size,
|
||||||
|
+ Err(_) => {
|
||||||
|
+ println!("\rlive: disabled (image too large for bootloader address space)");
|
||||||
|
+ live = false;
|
||||||
|
+ 0
|
||||||
|
+ }
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
diff --git a/src/os/uefi/mod.rs b/src/os/uefi/mod.rs
|
||||||
|
index d0b2cf1..dacead6 100644
|
||||||
|
--- a/src/os/uefi/mod.rs
|
||||||
|
+++ b/src/os/uefi/mod.rs
|
||||||
|
@@ -48,2 +48 @@ pub(crate) fn alloc_zeroed_page_aligned(size: usize) -> *mut u8 {
|
||||||
|
- // Max address mapped by src/arch paging code (8 GiB)
|
||||||
|
- let mut ptr = 0x2_0000_0000;
|
||||||
|
+ let mut ptr = 0;
|
||||||
|
@@ -51,2 +50,2 @@ pub(crate) fn alloc_zeroed_page_aligned(size: usize) -> *mut u8 {
|
||||||
|
- 1, // AllocateMaxAddress
|
||||||
|
- MemoryType::EfiRuntimeServicesData, // Keeps this memory out of free space list
|
||||||
|
+ 0, // AllocateAnyPages
|
||||||
|
+ MemoryType::EfiLoaderData, // Valid until ExitBootServices
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
diff --git a/src/devices/graphical_debug/debug.rs b/src/devices/graphical_debug/debug.rs
|
||||||
|
index 4b684c8a..e3fe0472 100644
|
||||||
|
--- a/src/devices/graphical_debug/debug.rs
|
||||||
|
+++ b/src/devices/graphical_debug/debug.rs
|
||||||
|
@@ -29,0 +30,3 @@ impl DebugDisplay {
|
||||||
|
+ const CHAR_WIDTH: usize = 8;
|
||||||
|
+ const CHAR_HEIGHT: usize = 16;
|
||||||
|
+
|
||||||
|
@@ -43,2 +46,2 @@ impl DebugDisplay {
|
||||||
|
- let w = display.width / 8;
|
||||||
|
- let h = display.height / 16;
|
||||||
|
+ let w = display.width / Self::CHAR_WIDTH;
|
||||||
|
+ let h = display.height / Self::CHAR_HEIGHT;
|
||||||
|
@@ -54,0 +58,21 @@ impl DebugDisplay {
|
||||||
|
+ fn scroll_up(&mut self) {
|
||||||
|
+ let stride = self.display.stride;
|
||||||
|
+ let width = self.display.width;
|
||||||
|
+ let total_height = self.display.height;
|
||||||
|
+ let scroll_px = Self::CHAR_HEIGHT;
|
||||||
|
+
|
||||||
|
+ unsafe {
|
||||||
|
+ let ptr = self.display.onscreen_ptr;
|
||||||
|
+ for row in 0..total_height - scroll_px {
|
||||||
|
+ ptr::copy(
|
||||||
|
+ ptr.add((row + scroll_px) * stride),
|
||||||
|
+ ptr.add(row * stride),
|
||||||
|
+ width,
|
||||||
|
+ );
|
||||||
|
+ }
|
||||||
|
+ for row in total_height - scroll_px..total_height {
|
||||||
|
+ ptr::write_bytes(ptr.add(row * stride), 0, width);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
@@ -59 +83,5 @@ impl DebugDisplay {
|
||||||
|
- self.y = (self.y + 1) % self.h;
|
||||||
|
+ self.y += 1;
|
||||||
|
+ if self.y >= self.h {
|
||||||
|
+ self.scroll_up();
|
||||||
|
+ self.y = self.h - 1;
|
||||||
|
+ }
|
||||||
|
@@ -67 +94,0 @@ impl DebugDisplay {
|
||||||
|
- // Byte 0x1B starts ESC sequence
|
||||||
|
@@ -72 +98,0 @@ impl DebugDisplay {
|
||||||
|
- // Ignore other nonprintable characters
|
||||||
|
@@ -77 +102,0 @@ impl DebugDisplay {
|
||||||
|
- // '[' after ESC starts CSI sequence
|
||||||
|
@@ -82 +106,0 @@ impl DebugDisplay {
|
||||||
|
- // Capture any bytes after ESC
|
||||||
|
@@ -87 +110,0 @@ impl DebugDisplay {
|
||||||
|
- // Byte 0x40 to 0x7E ends CSI
|
||||||
|
@@ -92 +114,0 @@ impl DebugDisplay {
|
||||||
|
- // Capture any bytes after CSI
|
||||||
|
@@ -96 +117,0 @@ impl DebugDisplay {
|
||||||
|
- // Allow any other bytes
|
||||||
|
@@ -102 +122,0 @@ impl DebugDisplay {
|
||||||
|
- self.clear_row((self.y + 1) % self.h);
|
||||||
|
@@ -105 +125 @@ impl DebugDisplay {
|
||||||
|
- self.char(self.x * 8, self.y * 16, b as char, 0xFFFFFF);
|
||||||
|
+ self.char(self.x * Self::CHAR_WIDTH, self.y * Self::CHAR_HEIGHT, b as char, 0xFFFFFF);
|
||||||
|
@@ -112 +132 @@ impl DebugDisplay {
|
||||||
|
- for row in y * 16..(y + 1) * 16 {
|
||||||
|
+ for row in y * Self::CHAR_HEIGHT..(y + 1) * Self::CHAR_HEIGHT {
|
||||||
|
@@ -123 +142,0 @@ impl DebugDisplay {
|
||||||
|
- /// Draw a character
|
||||||
|
@@ -125,7 +144,8 @@ impl DebugDisplay {
|
||||||
|
- if x + 8 <= self.display.width && y + 16 <= self.display.height {
|
||||||
|
- let phys_y = y % self.display.height;
|
||||||
|
- let mut dst = unsafe {
|
||||||
|
- self.display
|
||||||
|
- .onscreen_ptr
|
||||||
|
- .add(phys_y * self.display.stride + x)
|
||||||
|
- };
|
||||||
|
+ if x + Self::CHAR_WIDTH > self.display.width || y + Self::CHAR_HEIGHT > self.display.height {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ let font_i = Self::CHAR_HEIGHT * (character as usize);
|
||||||
|
+ if font_i + Self::CHAR_HEIGHT > FONT.len() {
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
@@ -133,6 +152,0 @@ impl DebugDisplay {
|
||||||
|
- let font_i = 16 * (character as usize);
|
||||||
|
- if font_i + 16 <= FONT.len() {
|
||||||
|
- for row in 0..16 {
|
||||||
|
- let row_data = FONT[font_i + row];
|
||||||
|
- for col in 0..8 {
|
||||||
|
- if (row_data >> (7 - col)) & 1 == 1 {
|
||||||
|
@@ -139,0 +154,7 @@ impl DebugDisplay {
|
||||||
|
+ let ptr = self.display.onscreen_ptr;
|
||||||
|
+ let stride = self.display.stride;
|
||||||
|
+ for row in 0..Self::CHAR_HEIGHT {
|
||||||
|
+ let row_data = FONT[font_i + row];
|
||||||
|
+ let dst = ptr.add((y + row) * stride + x);
|
||||||
|
+ for col in 0..Self::CHAR_WIDTH {
|
||||||
|
+ if (row_data >> (Self::CHAR_WIDTH - 1 - col)) & 1 == 1 {
|
||||||
|
@@ -144,9 +164,0 @@ impl DebugDisplay {
|
||||||
|
-
|
||||||
|
- let next_phys_y = (phys_y + row + 1) % self.display.height;
|
||||||
|
- dst = unsafe {
|
||||||
|
- self.display
|
||||||
|
- .onscreen_ptr
|
||||||
|
- .add(next_phys_y * self.display.stride + x)
|
||||||
|
- };
|
||||||
|
- }
|
||||||
|
- }
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
diff --git a/xf86drm.c b/xf86drm.c
|
||||||
|
index 1b206ccd4..c3904caa3 100644
|
||||||
|
--- a/xf86drm.c
|
||||||
|
+++ b/xf86drm.c
|
||||||
|
@@ -1774,0 +1775,23 @@ drm_public drmVersionPtr drmGetVersion(int fd)
|
||||||
|
+
|
||||||
|
+ /* The scheme returns a NUL-terminated driver name in version.name.
|
||||||
|
+ * KWin drm_gpu.cpp dereferences version->name unconditionally
|
||||||
|
+ * (strstr checks for "i915", "amdgpu", "virtio" etc.) so it must
|
||||||
|
+ * never be NULL.
|
||||||
|
+ */
|
||||||
|
+ version.name[sizeof(version.name) - 1] = '\0';
|
||||||
|
+ if (version.name[0] != '\0') {
|
||||||
|
+ size_t len = strlen(version.name);
|
||||||
|
+ retval->name = drmMalloc(len + 1);
|
||||||
|
+ if (retval->name) {
|
||||||
|
+ memcpy(retval->name, version.name, len + 1);
|
||||||
|
+ retval->name_len = len;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ const char fallback[] = "redox-drm";
|
||||||
|
+ retval->name = drmMalloc(sizeof(fallback));
|
||||||
|
+ if (retval->name) {
|
||||||
|
+ memcpy(retval->name, fallback, sizeof(fallback));
|
||||||
|
+ retval->name_len = sizeof(fallback) - 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
diff --git a/xf86drm_redox.h b/xf86drm_redox.h
|
||||||
|
index c1abe8256..7f9d252fa 100644
|
||||||
|
--- a/xf86drm_redox.h
|
||||||
|
+++ b/xf86drm_redox.h
|
||||||
|
@@ -140,0 +141 @@ struct redox_drm_version_wire {
|
||||||
|
+ char name[64];
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
diff --git a/xf86drm.c b/xf86drm.c
|
||||||
|
index c3904caa3..306026e8b 100644
|
||||||
|
--- a/xf86drm.c
|
||||||
|
+++ b/xf86drm.c
|
||||||
|
@@ -4096 +4096 @@ static int drmParseSubsystemType(int maj, int min)
|
||||||
|
-#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
||||||
|
+#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__redox__)
|
||||||
|
@@ -5122,0 +5123,60 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
|
||||||
|
+ return 0;
|
||||||
|
+#elif defined(__redox__)
|
||||||
|
+ /* On Redox there is no /dev/dri/ directory to enumerate.
|
||||||
|
+ * Instead, open /scheme/drm/card0 and query PCI info to
|
||||||
|
+ * construct a single drmDevice that serves as both primary
|
||||||
|
+ * and render node. */
|
||||||
|
+ drmDevicePtr devp;
|
||||||
|
+ char *pptr;
|
||||||
|
+ int max_node_length = 64, i;
|
||||||
|
+ size_t extra, psize;
|
||||||
|
+ uint8_t pbuf[22];
|
||||||
|
+ size_t prsize = 0;
|
||||||
|
+ int pret, fd;
|
||||||
|
+
|
||||||
|
+ if (device == NULL)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ if (drm_device_validate_flags(flags))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ fd = open("/scheme/drm/card0", O_RDWR | O_CLOEXEC);
|
||||||
|
+ if (fd < 0)
|
||||||
|
+ return -errno;
|
||||||
|
+
|
||||||
|
+ pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
|
||||||
|
+ pbuf, sizeof(pbuf), &prsize);
|
||||||
|
+ close(fd);
|
||||||
|
+ if (pret != 0 || prsize < 17)
|
||||||
|
+ return -EIO;
|
||||||
|
+
|
||||||
|
+ extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
|
||||||
|
+ psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
|
||||||
|
+ devp = calloc(1, psize);
|
||||||
|
+ if (!devp)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ devp->bustype = DRM_BUS_PCI;
|
||||||
|
+ /* Advertise both PRIMARY and RENDER — same path on Redox */
|
||||||
|
+ devp->available_nodes = (1 << DRM_NODE_PRIMARY) | (1 << DRM_NODE_RENDER);
|
||||||
|
+ pptr = (char *)devp + sizeof(drmDevice);
|
||||||
|
+ devp->nodes = (char **)pptr;
|
||||||
|
+ pptr += DRM_NODE_MAX * sizeof(void *);
|
||||||
|
+ for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
|
||||||
|
+ snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "/scheme/drm/card0");
|
||||||
|
+ snprintf(devp->nodes[DRM_NODE_RENDER], max_node_length, "/scheme/drm/card0");
|
||||||
|
+
|
||||||
|
+ devp->businfo.pci = (drmPciBusInfoPtr)pptr;
|
||||||
|
+ pptr += sizeof(drmPciBusInfo);
|
||||||
|
+ devp->businfo.pci->domain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
|
||||||
|
+ devp->businfo.pci->bus = pbuf[14];
|
||||||
|
+ devp->businfo.pci->dev = pbuf[15];
|
||||||
|
+ devp->businfo.pci->func = pbuf[16];
|
||||||
|
+
|
||||||
|
+ devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
|
||||||
|
+ devp->deviceinfo.pci->vendor_id = pbuf[0] | (pbuf[1] << 8);
|
||||||
|
+ devp->deviceinfo.pci->device_id = pbuf[2] | (pbuf[3] << 8);
|
||||||
|
+ devp->deviceinfo.pci->subvendor_id = pbuf[4] | (pbuf[5] << 8);
|
||||||
|
+ devp->deviceinfo.pci->subdevice_id = pbuf[6] | (pbuf[7] << 8);
|
||||||
|
+ devp->deviceinfo.pci->revision_id = pbuf[8];
|
||||||
|
+
|
||||||
|
+ *device = devp;
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
diff --git a/src/bin/mount.rs b/src/bin/mount.rs
|
||||||
|
index dba7f3c..70cf661 100644
|
||||||
|
--- a/src/bin/mount.rs
|
||||||
|
+++ b/src/bin/mount.rs
|
||||||
|
@@ -292 +292,19 @@ fn daemon(
|
||||||
|
- DiskId::Uuid(ref uuid) => filesystem_by_uuid(uuid, block_opt),
|
||||||
|
+ DiskId::Uuid(ref uuid) => {
|
||||||
|
+ let max_attempts = 20;
|
||||||
|
+ let mut attempt = 0;
|
||||||
|
+ loop {
|
||||||
|
+ attempt += 1;
|
||||||
|
+ if let Some(result) = filesystem_by_uuid(uuid, block_opt) {
|
||||||
|
+ break Some(result);
|
||||||
|
+ }
|
||||||
|
+ if attempt >= max_attempts {
|
||||||
|
+ log::error!("uuid search exhausted {} attempts", attempt);
|
||||||
|
+ break None;
|
||||||
|
+ }
|
||||||
|
+ #[cfg(target_os = "redox")]
|
||||||
|
+ std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
|
+ #[cfg(not(target_os = "redox"))]
|
||||||
|
+ std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
|
+ log::debug!("uuid search retry {}/{}", attempt, max_attempts);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
diff --git a/src/bin/mount.rs b/src/bin/mount.rs
|
||||||
|
index dba7f3c..8f00a30 100644
|
||||||
|
--- a/src/bin/mount.rs
|
||||||
|
+++ b/src/bin/mount.rs
|
||||||
|
@@ -292 +292,16 @@ fn daemon(
|
||||||
|
- DiskId::Uuid(ref uuid) => filesystem_by_uuid(uuid, block_opt),
|
||||||
|
+ DiskId::Uuid(ref uuid) => {
|
||||||
|
+ let max_attempts = 20;
|
||||||
|
+ let mut attempt = 0;
|
||||||
|
+ loop {
|
||||||
|
+ attempt += 1;
|
||||||
|
+ if let Some(result) = filesystem_by_uuid(uuid, block_opt) {
|
||||||
|
+ break Some(result);
|
||||||
|
+ }
|
||||||
|
+ if attempt >= max_attempts {
|
||||||
|
+ log::error!("uuid search exhausted {} attempts", attempt);
|
||||||
|
+ break None;
|
||||||
|
+ }
|
||||||
|
+ std::thread::sleep(std::time::Duration::from_millis(200));
|
||||||
|
+ log::debug!("uuid search retry {}/{}", attempt, max_attempts);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
# Red Bear OS Custom Recipes — Catalog
|
||||||
|
|
||||||
|
All recipes under `local/recipes/` are Red Bear OS originals or patched forks of upstream
|
||||||
|
Redox recipes. They are symlinked into `recipes/<category>/` at build time via
|
||||||
|
`local/scripts/apply-patches.sh`.
|
||||||
|
|
||||||
|
**Convention**: recipe directories contain `recipe.toml` (build instructions) and optionally
|
||||||
|
`source/` (source code for Rust `cargo` or `custom` templates). Patches for upstream sources
|
||||||
|
live in `local/patches/<component>/`, never here.
|
||||||
|
|
||||||
|
## archives
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| uutils-tar | cargo | Rust | GNU tar compatible archiver from uutils, for creating and extracting tar archives |
|
||||||
|
|
||||||
|
## branding
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| redbear-release | custom | Shell | OS release metadata: `/etc/os-release`, hostname, and branding assets |
|
||||||
|
|
||||||
|
## core
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| ext4d | custom | Rust | ext4 filesystem driver daemon (userspace, scheme-based) |
|
||||||
|
| fatd | custom | Rust | FAT32 filesystem driver daemon (userspace, scheme-based) |
|
||||||
|
| grub | custom | Scripts | GRUB boot manager integration for live ISO and bare-metal installs |
|
||||||
|
| pcid-spawner | cargo | Rust | PCI device spawner — launches driver daemons on PCI device discovery |
|
||||||
|
|
||||||
|
## dev
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| binutils-native | custom | C | GNU binutils (ld, objdump, etc.) built for native Red Bear target |
|
||||||
|
| bison | custom | C | GNU bison parser generator |
|
||||||
|
| cub | custom | Rust | Red Bear build utility — build orchestration helper |
|
||||||
|
| flex | custom | C | Fast lexical analyzer generator |
|
||||||
|
| gcc-native | custom | C | GCC cross-compiler for native Red Bear target |
|
||||||
|
| gnu-make | custom | C | GNU Make build tool |
|
||||||
|
| libtool | custom | C | GNU libtool — generic library support script |
|
||||||
|
| llvm-native | custom | C++ | LLVM/Clang toolchain built for native Red Bear target |
|
||||||
|
| m4 | custom | C | GNU m4 macro processor |
|
||||||
|
| meson | custom | Python | Meson build system |
|
||||||
|
| ninja-build | custom | C | Ninja build system (small, fast build runner) |
|
||||||
|
| rust-native | custom | Rust | Rust toolchain for native Red Bear builds |
|
||||||
|
|
||||||
|
## drivers
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| ehcid | cargo | Rust | EHCI (USB 2.0) host controller driver daemon |
|
||||||
|
| linux-kpi | custom | C headers | Linux Kernel Programming Interface — C header shim translating Linux kernel APIs to redox-driver-sys. **GPU and Wi-Fi only** — no USB support |
|
||||||
|
| ohcid | cargo | Rust | OHCI (USB 1.1) host controller driver daemon |
|
||||||
|
| redbear-btusb | custom | Rust | Bluetooth USB transport driver — sends/receives HCI packets over USB |
|
||||||
|
| redbear-input-headers | custom | C headers | Linux-compatible input event headers (input.h, evdev constants) for driver and compositor use |
|
||||||
|
| redbear-iwlwifi | cargo | Rust | Intel Wi-Fi driver (iwlwifi port) — mac80211-based wireless networking |
|
||||||
|
| redox-driver-acpi | cargo | Rust | ACPI driver — parses RSDP/SDT/MADT/FADT tables, exposes scheme:acpi |
|
||||||
|
| redox-driver-core | cargo | Rust | Core driver traits and types shared across all redox-driver-* crates |
|
||||||
|
| redox-driver-pci | cargo | Rust | PCI bus driver — enumerates PCI devices, exposes scheme:pci, provides config space access |
|
||||||
|
| redox-driver-sys | custom | Rust | Safe Rust FFI wrappers for scheme:memory, scheme:irq, scheme:pci + hardware quirks system |
|
||||||
|
| uhcid | cargo | Rust | UHCI (USB 1.1) host controller driver daemon |
|
||||||
|
| usb-core | cargo | Rust | USB core stack — hub driver, device enumeration, transfer scheduling |
|
||||||
|
|
||||||
|
## gpu
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| amdgpu | custom | C | AMD GPU display core (DC) port with linux-kpi compat shim |
|
||||||
|
| redox-drm | cargo | Rust | DRM/KMS scheme daemon — GPU driver manager, supports virtio-gpu, Intel, AMD. Auto-detects hardware and loads correct driver |
|
||||||
|
|
||||||
|
## groups
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| build-essential-native | custom | Meta | Meta-package group: compiler, linker, make, and core build tools for native development |
|
||||||
|
|
||||||
|
## kde
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| breeze | custom | C++ | KDE Breeze widget style and window decoration theme |
|
||||||
|
| kde-cli-tools | custom | C++ | KDE command-line utilities (kde-open, kioclient, etc.) |
|
||||||
|
| kdecoration | custom | C++ | KDE window decoration library — decoration plugin API for KWin |
|
||||||
|
| kf6-attica | custom | C++ | KDE Frameworks 6 — Open Collaboration Services API (GHNS) |
|
||||||
|
| kf6-extra-cmake-modules | custom | CMake | KDE Frameworks 6 — Extra CMake Modules (build system extensions) |
|
||||||
|
| kf6-karchive | custom | C++ | KDE Frameworks 6 — archive handling (tar, zip, etc.) |
|
||||||
|
| kf6-kauth | custom | C++ | KDE Frameworks 6 — authorization framework (PolicyKit integration) |
|
||||||
|
| kf6-kbookmarks | custom | C++ | KDE Frameworks 6 — bookmark management (XBEL format) |
|
||||||
|
| kf6-kcmutils | custom | C++ | KDE Frameworks 6 — KCModule utilities for System Settings |
|
||||||
|
| kf6-kcodecs | custom | C++ | KDE Frameworks 6 — string encoding/decoding (base64, uuencode, etc.) |
|
||||||
|
| kf6-kcolorscheme | custom | C++ | KDE Frameworks 6 — color scheme management |
|
||||||
|
| kf6-kcompletion | custom | C++ | KDE Frameworks 6 — text completion widgets and utilities |
|
||||||
|
| kf6-kconfig | custom | C++ | KDE Frameworks 6 — configuration file framework (INI, JSON) |
|
||||||
|
| kf6-kconfigwidgets | custom | C++ | KDE Frameworks 6 — configuration-aware widgets |
|
||||||
|
| kf6-kcoreaddons | custom | C++ | KDE Frameworks 6 — core utilities (KAboutData, KJob, KProcess) |
|
||||||
|
| kf6-kcrash | custom | C++ | KDE Frameworks 6 — crash handler with DrKonqi integration |
|
||||||
|
| kf6-kdbusaddons | custom | C++ | KDE Frameworks 6 — D-Bus convenience classes |
|
||||||
|
| kf6-kdeclarative | custom | C++ | KDE Frameworks 6 — KDE QtQuick integration plugins |
|
||||||
|
| kf6-kded6 | custom | C++ | KDE Frameworks 6 — background service daemon (kded6) |
|
||||||
|
| kf6-kglobalaccel | custom | C++ | KDE Frameworks 6 — global keyboard shortcut registration |
|
||||||
|
| kf6-kguiaddons | custom | C++ | KDE Frameworks 6 — GUI utilities (color picker, key sequence) |
|
||||||
|
| kf6-ki18n | custom | C++ | KDE Frameworks 6 — internationalization (gettext integration) |
|
||||||
|
| kf6-kiconthemes | custom | C++ | KDE Frameworks 6 — icon theme management and rendering |
|
||||||
|
| kf6-kidletime | custom | C++ | KDE Frameworks 6 — idle time detection for screensaver/power |
|
||||||
|
| kf6-kio | custom | C++ | KDE Frameworks 6 — I/O framework (KIO slaves for network/FS access) |
|
||||||
|
| kf6-kitemmodels | custom | C++ | KDE Frameworks 6 — Qt model extensions (KRearrangeColumns, KSortFilter) |
|
||||||
|
| kf6-kitemviews | custom | C++ | KDE Frameworks 6 — item view widgets (KFilterProxy, KCategoryDrawer) |
|
||||||
|
| kf6-kjobwidgets | custom | C++ | KDE Frameworks 6 — async job tracking widgets |
|
||||||
|
| kf6-knewstuff | custom | C++ | KDE Frameworks 6 — Get Hot New Stuff (GHNS) download framework |
|
||||||
|
| kf6-knotifications | custom | C++ | KDE Frameworks 6 — system notification framework |
|
||||||
|
| kf6-kpackage | custom | C++ | KDE Frameworks 6 — package/installation framework |
|
||||||
|
| kf6-kservice | custom | C++ | KDE Frameworks 6 — service/plugin framework (mime type, .desktop parsing) |
|
||||||
|
| kf6-ksvg | custom | C++ | KDE Frameworks 6 — SVG rendering with theme support |
|
||||||
|
| kf6-ktextwidgets | custom | C++ | KDE Frameworks 6 — text editing widgets (KTextEdit, find/replace) |
|
||||||
|
| kf6-kwallet | custom | C++ | KDE Frameworks 6 — secure credential storage |
|
||||||
|
| kf6-kwayland | custom | C++ | KDE Frameworks 6 — Wayland protocol bindings for Qt/KDE |
|
||||||
|
| kf6-kwidgetsaddons | custom | C++ | KDE Frameworks 6 — extra Qt widgets (KComboBox, KPageWidget) |
|
||||||
|
| kf6-kwindowsystem | custom | C++ | KDE Frameworks 6 — window system integration (window info, stacking) |
|
||||||
|
| kf6-kxmlgui | custom | C++ | KDE Frameworks 6 — XML-defined GUI (menus, toolbars, actions) |
|
||||||
|
| kf6-notifyconfig | custom | C++ | KDE Frameworks 6 — notification configuration widgets |
|
||||||
|
| kf6-parts | custom | C++ | KDE Frameworks 6 — embeddable document/viewer parts (KParts) |
|
||||||
|
| kf6-prison | custom | C++ | KDE Frameworks 6 — barcode/QR code generation (QRencode wrapper) |
|
||||||
|
| kf6-pty | custom | C++ | KDE Frameworks 6 — pseudoterminal (PTY) management |
|
||||||
|
| kf6-solid | custom | C++ | KDE Frameworks 6 — hardware abstraction (storage, power, network) |
|
||||||
|
| kf6-sonnet | custom | C++ | KDE Frameworks 6 — spell checking framework |
|
||||||
|
| kf6-syntaxhighlighting | custom | C++ | KDE Frameworks 6 — syntax highlighting engine (Kate definitions) |
|
||||||
|
| kglobalacceld | custom | C++ | KDE global shortcut daemon — handles keyboard shortcut registration |
|
||||||
|
| kirigami | custom | C++ | KDE Kirigami — responsive QtQuick UI framework (convergent apps) |
|
||||||
|
| konsole | custom | C++ | KDE Konsole — terminal emulator |
|
||||||
|
| kwin | custom | C++ | KDE KWin — Wayland compositor and window manager |
|
||||||
|
| plasma-desktop | custom | C++ | KDE Plasma Desktop — panels, desktop containment, applets |
|
||||||
|
| plasma-framework | custom | C++ | KDE Plasma Framework — libplasma for Plasma shell and applets |
|
||||||
|
| plasma-wayland-protocols | custom | C++ | KDE Plasma Wayland protocol extensions |
|
||||||
|
| plasma-workspace | custom | C++ | KDE Plasma Workspace — plasma-shell, data engines, runners |
|
||||||
|
|
||||||
|
## libs
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| freetype2 | custom | C | FreeType 2 font rendering library |
|
||||||
|
| glib | custom | C | GLib — core event loop, type system, utility functions |
|
||||||
|
| icu | custom | C++ | ICU — Unicode and internationalization support |
|
||||||
|
| lcms2 | custom | C | Little CMS 2 — color management library |
|
||||||
|
| lcms2-stub | custom | C | Minimal lcms2 stub — provides symbols without implementation |
|
||||||
|
| libdisplay-info | custom | C | EDID and display descriptor parsing library |
|
||||||
|
| libdisplay-info-stub | custom | C | Minimal libdisplay-info stub for compile-time satisfaction |
|
||||||
|
| libdrm | meson | C | libdrm — DRM/KMS user-space library with Red Bear patches for render node and virtio-gpu support |
|
||||||
|
| libepoxy | custom | C | Epoxy — OpenGL function pointer manager (cross-platform GL loader) |
|
||||||
|
| libepoxy-stub | custom | C | Minimal libepoxy stub — provides symbols without implementation |
|
||||||
|
| libevdev | meson | C | libevdev — evdev device wrapper library for input handling |
|
||||||
|
| libinput | meson | C | libinput — input device management (keyboard, pointer, touch) |
|
||||||
|
| libqrencode | cmake | C | libqrencode — QR code encoding library |
|
||||||
|
| libudev-stub | custom | C | Minimal libudev stub — provides symbols for udev-dependent builds |
|
||||||
|
| libxcvt | custom | C | libxcvt — VESA CVT mode timing calculation |
|
||||||
|
| libxcvt-stub | custom | C | Minimal libxcvt stub — provides symbols without implementation |
|
||||||
|
| zbus | custom | Rust | zbus crate — Rust D-Bus message bus library (library-only, custom build) |
|
||||||
|
|
||||||
|
## qt
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| qt6-sensors | custom | C++ | Qt 6 Sensors module — hardware sensor access (accel, gyro, etc.) |
|
||||||
|
| qtbase | custom | C++ | Qt 6 Base — core, gui, widgets, network modules |
|
||||||
|
| qtdeclarative | custom | C++ | Qt 6 QML/QtQuick — declarative UI framework |
|
||||||
|
| qtsvg | custom | C++ | Qt 6 SVG — SVG rendering support for Qt |
|
||||||
|
| qtwayland | custom | C++ | Qt 6 Wayland — Wayland compositor/client integration |
|
||||||
|
|
||||||
|
## system
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| coretempd | cargo | Rust | CPU core temperature monitoring daemon |
|
||||||
|
| cpufreqd | cargo | Rust | CPU frequency scaling daemon |
|
||||||
|
| cub | custom | Rust | Red Bear build utility (same as dev/cub, system-installed copy) |
|
||||||
|
| dbus | meson | C | D-Bus reference implementation — system and session message bus |
|
||||||
|
| driver-manager | custom | Rust | Driver lifecycle manager — loads/unloads drivers based on hardware |
|
||||||
|
| driver-params | cargo | Rust | Driver parameter service — exposes driver configuration via scheme |
|
||||||
|
| evdevd | custom | Rust | evdev event daemon — translates input events to evdev protocol |
|
||||||
|
| firmware-loader | cargo | Rust | Firmware loading daemon — serves GPU/device firmware blobs via scheme:firmware |
|
||||||
|
| hwrngd | cargo | Rust | Hardware RNG daemon — exposes entropy from hardware random number generator |
|
||||||
|
| iommu | cargo | Rust | IOMMU daemon — manages I/O memory mapping for device DMA |
|
||||||
|
| numad | cargo | Rust | NUMA topology daemon — exposes NUMA node information |
|
||||||
|
| redbear-accessibility | custom | Rust | Accessibility service — screen reader and input assistance bridge |
|
||||||
|
| redbear-acmd | cargo | Rust | Red Bear admin CLI — system administration commands |
|
||||||
|
| redbear-authd | cargo | Rust | Authentication daemon — PAM-like auth with scheme:auth |
|
||||||
|
| redbear-btctl | custom | Rust | Bluetooth control utility — scan, pair, connect Bluetooth devices |
|
||||||
|
| redbear-dbus-services | custom | Config | D-Bus service activation files and XML policy files for system/session buses |
|
||||||
|
| redbear-ecmd | cargo | Rust | Extended command-line tool — system diagnostics and info |
|
||||||
|
| redbear-firmware | custom | Scripts | Firmware management utility — list, extract, verify firmware blobs |
|
||||||
|
| redbear-greeter | custom | Rust | Login greeter daemon — displays graphical login prompt |
|
||||||
|
| redbear-hwutils | cargo | Rust | Hardware utility library and CLI — PCI, USB, sensor information |
|
||||||
|
| redbear-ime | custom | Rust | Input method engine — multilingual text input framework |
|
||||||
|
| redbear-info | cargo | Rust | System information daemon — hardware and OS state queries |
|
||||||
|
| redbear-keymapd | custom | Rust | Keyboard layout daemon — manages keymaps and input layouts |
|
||||||
|
| redbear-login-protocol | cargo | Rust | Login protocol crate — shared types for auth session management |
|
||||||
|
| redbear-meta | custom | Meta | Meta-package — ensures core Red Bear system packages are installed |
|
||||||
|
| redbear-mtr | cargo | Rust | MTR network diagnostic tool — traceroute + ping combined |
|
||||||
|
| redbear-netctl | cargo | Rust | Network control daemon — manages network interfaces and connections |
|
||||||
|
| redbear-netctl-console | cargo | Rust | Network control console UI — TUI for redbear-netctl |
|
||||||
|
| redbear-netstat | cargo | Rust | Network statistics tool — socket, interface, and routing info |
|
||||||
|
| redbear-nmap | cargo | Rust | Network mapper — port scanning and host discovery |
|
||||||
|
| redbear-notifications | cargo | Rust | Notification daemon — freedesktop.org notification spec implementation |
|
||||||
|
| redbear-passwd | cargo | Rust | Password management utility — change passwords, manage shadow |
|
||||||
|
| redbear-polkit | cargo | Rust | PolicyKit daemon — authorization framework for privileged operations |
|
||||||
|
| redbear-quirks | custom | Config | Hardware quirks database — TOML quirk definitions for known issues |
|
||||||
|
| redbear-sessiond | cargo | Rust | Session manager daemon — D-Bus login1 subset for KWin/Wayland |
|
||||||
|
| redbear-session-launch | cargo | Rust | Session launcher — starts desktop session compositor and services |
|
||||||
|
| redbear-statusnotifierwatcher | cargo | Rust | Status Notifier Watcher — freedesktop.org system tray spec |
|
||||||
|
| redbear-traceroute | cargo | Rust | Traceroute utility — network path discovery |
|
||||||
|
| redbear-udisks | cargo | Rust | UDisks2 daemon — storage device management via D-Bus |
|
||||||
|
| redbear-upower | cargo | Rust | UPower daemon — power management and battery status via D-Bus |
|
||||||
|
| redbear-usbaudiod | cargo | Rust | USB audio daemon — USB audio class device driver |
|
||||||
|
| redbear-wayland-guard | custom | Rust | Wayland security guard — validates compositor/client permissions |
|
||||||
|
| redbear-wifictl | cargo | Rust | Wi-Fi control utility — scan, connect, manage wireless networks |
|
||||||
|
| seatd | meson | C | seatd — seat management daemon for DRM master access |
|
||||||
|
| thermald | cargo | Rust | Thermal management daemon — monitors and controls CPU temperature |
|
||||||
|
| udev-shim | cargo | Rust | udev compatibility shim — translates libudev calls to Red Bear schemes |
|
||||||
|
|
||||||
|
## tests
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| redox-drm-prime-test | custom | Rust | DRM PRIME buffer sharing test — validates GPU buffer import/export |
|
||||||
|
| relibc-phase1-tests | custom | C | relibc POSIX compliance tests — validates syscall wrappers and C library functions |
|
||||||
|
|
||||||
|
## tools
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| diffutils | custom | C | GNU diffutils — diff, diff3, sdiff, cmp |
|
||||||
|
|
||||||
|
## tui
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| mc | custom | C | GNU Midnight Commander — file manager with TUI |
|
||||||
|
|
||||||
|
## wayland
|
||||||
|
|
||||||
|
| Recipe | Template | Language | Description |
|
||||||
|
|--------|----------|----------|-------------|
|
||||||
|
| libwayland | custom | C | libwayland — Wayland protocol client/server library |
|
||||||
|
| qt6-wayland-smoke | custom | C++ | Qt 6 Wayland smoke test — minimal QML window on Wayland |
|
||||||
|
| redbear-compositor | cargo | Rust | Red Bear Wayland compositor — compositor shell for DRM/KMS output |
|
||||||
|
| seatd-redox | meson | C | seatd Redox backend — seat management for Red Bear's scheme system |
|
||||||
|
| smallvil | cargo | C | Smallvil — minimal wlroots-based Wayland compositor for testing |
|
||||||
|
| wayland-protocols | custom | C | Wayland protocol extensions — stable and staging protocol XML files |
|
||||||
@@ -138,36 +138,6 @@ impl VirtioDriver {
|
|||||||
};
|
};
|
||||||
let (connectors, crtcs) = load_display_topology(&mut device)?;
|
let (connectors, crtcs) = load_display_topology(&mut device)?;
|
||||||
|
|
||||||
// Probe 1: resource_unref for non-existent ID — tests VirtQueue mechanism
|
|
||||||
match device.resource_unref(1) {
|
|
||||||
Ok(()) => info!("redox-drm: VirtIO diag resource_unref(1) returned OK (unexpected — ID 1 should not exist)"),
|
|
||||||
Err(e) => info!("redox-drm: VirtIO diag resource_unref(1) returned {:?}", e),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Probe 2: invalid format=0 — if QEMU returns ERR_INVALID_PARAMETER it reads the full
|
|
||||||
// command; if ERR_INVALID_RESOURCE_ID it's only seeing the header or resource_id field.
|
|
||||||
{
|
|
||||||
let probe = VirtioGpuResourceCreate2d {
|
|
||||||
hdr: VirtioGpuCtrlHeader::command(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D),
|
|
||||||
resource_id: 99,
|
|
||||||
format: 0,
|
|
||||||
width: 64,
|
|
||||||
height: 64,
|
|
||||||
};
|
|
||||||
let probe_bytes = bytes_of(&probe);
|
|
||||||
info!("redox-drm: VirtIO diag probe: resource_create_2d(rid=99, fmt=0, w=64, h=64)");
|
|
||||||
match device.submit_request(probe_bytes, core::mem::size_of::<VirtioGpuCtrlHeader>()) {
|
|
||||||
Ok(resp) => {
|
|
||||||
let hdr = read_struct::<VirtioGpuCtrlHeader>(&resp)?;
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO diag probe response: type={:#06x} ({})",
|
|
||||||
hdr.type_, response_type_name(hdr.type_)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Err(e) => info!("redox-drm: VirtIO diag probe submit_request error: {:?}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"redox-drm: VirtIO GPU ready for {} with {} connector(s), {} CRTC(s), EDID={} VIRGL={} IRQ mode {}",
|
"redox-drm: VirtIO GPU ready for {} with {} connector(s), {} CRTC(s), EDID={} VIRGL={} IRQ mode {}",
|
||||||
info.location,
|
info.location,
|
||||||
@@ -895,59 +865,11 @@ impl VirtioGpuDevice {
|
|||||||
})?;
|
})?;
|
||||||
|
|
||||||
let request_ptr = dma.as_mut_ptr();
|
let request_ptr = dma.as_mut_ptr();
|
||||||
// SAFETY: `dma` is at least `total` bytes, and `request`/response ranges do not overlap.
|
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(request.as_ptr(), request_ptr, request.len());
|
core::ptr::copy_nonoverlapping(request.as_ptr(), request_ptr, request.len());
|
||||||
core::ptr::write_bytes(request_ptr.add(request.len()), 0, response_len);
|
core::ptr::write_bytes(request_ptr.add(request.len()), 0, response_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut verify_mismatch = false;
|
|
||||||
unsafe {
|
|
||||||
for (i, &expected) in request.iter().enumerate().take(8) {
|
|
||||||
if *request_ptr.add(i) != expected {
|
|
||||||
verify_mismatch = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if verify_mismatch {
|
|
||||||
let readback: Vec<u8> = unsafe { core::slice::from_raw_parts(request_ptr, request.len().min(40)) }.to_vec();
|
|
||||||
warn!(
|
|
||||||
"redox-drm: VirtIO DMA VERIFY MISMATCH! written={:02x?} readback={:02x?}",
|
|
||||||
&request[..request.len().min(40)],
|
|
||||||
readback
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO submit_request dma_phys={:#x} req_len={} resp_addr={:#x} resp_len={}",
|
|
||||||
dma.physical_address(),
|
|
||||||
request.len(),
|
|
||||||
dma.physical_address() + request.len(),
|
|
||||||
response_len
|
|
||||||
);
|
|
||||||
|
|
||||||
// Full DMA buffer hex dump BEFORE push_avail — confirms physical memory contains
|
|
||||||
// correct bytes that QEMU should read. Dumps request area + first 8 bytes of
|
|
||||||
// response area (should be zeroed).
|
|
||||||
{
|
|
||||||
let full_len = total.min(128);
|
|
||||||
let dma_slice: &[u8] = unsafe { core::slice::from_raw_parts(request_ptr, full_len) };
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO DMA BUFFER BEFORE SUBMIT ({} bytes): {:02x?}",
|
|
||||||
full_len, dma_slice
|
|
||||||
);
|
|
||||||
// Also dump the raw descriptor that QEMU will see — addr, len, flags, next
|
|
||||||
// desc[0] = request (F_NEXT), desc[1] = response (F_WRITE)
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO DESC[0] addr={:#x} len={} flags=F_NEXT next=1 | DESC[1] addr={:#x} len={} flags=F_WRITE next=0",
|
|
||||||
dma.physical_address(),
|
|
||||||
request.len(),
|
|
||||||
dma.physical_address() + request.len(),
|
|
||||||
response_len,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.ctrlq.submit_request(
|
self.ctrlq.submit_request(
|
||||||
&self.transport,
|
&self.transport,
|
||||||
dma.physical_address() as u64,
|
dma.physical_address() as u64,
|
||||||
@@ -957,15 +879,6 @@ impl VirtioGpuDevice {
|
|||||||
COMMAND_TIMEOUT,
|
COMMAND_TIMEOUT,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
{
|
|
||||||
let full_len = total.min(128);
|
|
||||||
let dma_slice: &[u8] = unsafe { core::slice::from_raw_parts(request_ptr, full_len) };
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO DMA BUFFER AFTER RESPONSE ({} bytes): {:02x?}",
|
|
||||||
full_len, dma_slice
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut response = vec![0u8; response_len];
|
let mut response = vec![0u8; response_len];
|
||||||
unsafe {
|
unsafe {
|
||||||
core::ptr::copy_nonoverlapping(
|
core::ptr::copy_nonoverlapping(
|
||||||
@@ -976,14 +889,6 @@ impl VirtioGpuDevice {
|
|||||||
}
|
}
|
||||||
if response_len >= core::mem::size_of::<VirtioGpuCtrlHeader>() {
|
if response_len >= core::mem::size_of::<VirtioGpuCtrlHeader>() {
|
||||||
let hdr = unsafe { (response.as_ptr() as *const VirtioGpuCtrlHeader).read_unaligned() };
|
let hdr = unsafe { (response.as_ptr() as *const VirtioGpuCtrlHeader).read_unaligned() };
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO submit_request response type={:#06x} ({}) flags={:#x} fence_id={} ctx_id={}",
|
|
||||||
hdr.type_,
|
|
||||||
response_type_name(hdr.type_),
|
|
||||||
hdr.flags,
|
|
||||||
hdr.fence_id,
|
|
||||||
hdr.ctx_id,
|
|
||||||
);
|
|
||||||
if hdr.type_ != VIRTIO_GPU_RESP_OK_NODATA
|
if hdr.type_ != VIRTIO_GPU_RESP_OK_NODATA
|
||||||
&& hdr.type_ != VIRTIO_GPU_RESP_OK_DISPLAY_INFO
|
&& hdr.type_ != VIRTIO_GPU_RESP_OK_DISPLAY_INFO
|
||||||
&& hdr.type_ != VIRTIO_GPU_RESP_OK_EDID
|
&& hdr.type_ != VIRTIO_GPU_RESP_OK_EDID
|
||||||
@@ -992,7 +897,9 @@ impl VirtioGpuDevice {
|
|||||||
&& hdr.type_ != VIRTIO_GPU_RESP_OK_MAP_INFO
|
&& hdr.type_ != VIRTIO_GPU_RESP_OK_MAP_INFO
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"redox-drm: VirtIO unexpected response header bytes: {:02x?}",
|
"redox-drm: VirtIO unexpected response type={:#06x} ({}) header: {:02x?}",
|
||||||
|
hdr.type_,
|
||||||
|
response_type_name(hdr.type_),
|
||||||
&response[..response_len.min(24)]
|
&response[..response_len.min(24)]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1047,23 +954,8 @@ impl VirtioGpuDevice {
|
|||||||
height,
|
height,
|
||||||
};
|
};
|
||||||
|
|
||||||
let request_bytes = bytes_of(&request);
|
let response = self.submit_request(bytes_of(&request), core::mem::size_of::<VirtioGpuCtrlHeader>())?;
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO resource_create_2d rid={} fmt={} w={} h={} cmd_bytes={:02x?}",
|
|
||||||
resource_id,
|
|
||||||
VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
&request_bytes[..request_bytes.len().min(48)]
|
|
||||||
);
|
|
||||||
|
|
||||||
let response = self.submit_request(request_bytes, core::mem::size_of::<VirtioGpuCtrlHeader>())?;
|
|
||||||
let header = read_struct::<VirtioGpuCtrlHeader>(&response)?;
|
let header = read_struct::<VirtioGpuCtrlHeader>(&response)?;
|
||||||
info!(
|
|
||||||
"redox-drm: VirtIO resource_create_2d response type={:#06x} ({})",
|
|
||||||
header.type_,
|
|
||||||
response_type_name(header.type_)
|
|
||||||
);
|
|
||||||
validate_response_type(&header, VIRTIO_GPU_RESP_OK_NODATA)
|
validate_response_type(&header, VIRTIO_GPU_RESP_OK_NODATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1102,10 +994,7 @@ impl VirtioGpuDevice {
|
|||||||
resource_id,
|
resource_id,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
};
|
};
|
||||||
info!("redox-drm: VirtIO resource_unref rid={} cmd_bytes={:02x?}", resource_id, bytes_of(&request));
|
self.submit_nodata(&request)
|
||||||
let result = self.submit_nodata(&request);
|
|
||||||
info!("redox-drm: VirtIO resource_unref rid={} result={:?}", resource_id, &result);
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_scanout(
|
fn set_scanout(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use std::sync::atomic::{fence, Ordering};
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use log::info;
|
|
||||||
use redox_driver_sys::dma::DmaBuffer;
|
use redox_driver_sys::dma::DmaBuffer;
|
||||||
|
|
||||||
use crate::driver::{DriverError, Result};
|
use crate::driver::{DriverError, Result};
|
||||||
@@ -39,7 +38,6 @@ pub struct Virtqueue {
|
|||||||
free_list: Vec<u16>,
|
free_list: Vec<u16>,
|
||||||
pending: BTreeMap<u16, Vec<u16>>,
|
pending: BTreeMap<u16, Vec<u16>>,
|
||||||
last_used_idx: u16,
|
last_used_idx: u16,
|
||||||
failed: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Virtqueue {
|
impl Virtqueue {
|
||||||
@@ -65,7 +63,6 @@ impl Virtqueue {
|
|||||||
free_list: (0..size).rev().collect(),
|
free_list: (0..size).rev().collect(),
|
||||||
pending: BTreeMap::new(),
|
pending: BTreeMap::new(),
|
||||||
last_used_idx: 0,
|
last_used_idx: 0,
|
||||||
failed: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,13 +99,6 @@ impl Virtqueue {
|
|||||||
response_len: u32,
|
response_len: u32,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if self.failed {
|
|
||||||
return Err(DriverError::Io(format!(
|
|
||||||
"VirtIO queue {} is failed and cannot accept more requests",
|
|
||||||
self.index
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let head = self.alloc_desc()?;
|
let head = self.alloc_desc()?;
|
||||||
let tail = self.alloc_desc()?;
|
let tail = self.alloc_desc()?;
|
||||||
self.write_desc(
|
self.write_desc(
|
||||||
@@ -132,26 +122,6 @@ impl Virtqueue {
|
|||||||
|
|
||||||
self.pending.insert(head, vec![head, tail]);
|
self.pending.insert(head, vec![head, tail]);
|
||||||
|
|
||||||
{
|
|
||||||
let desc_ptr = self.desc.as_ptr() as *const u8;
|
|
||||||
let desc0_bytes: &[u8] = unsafe {
|
|
||||||
core::slice::from_raw_parts(desc_ptr.add((head as usize) * 16), 16)
|
|
||||||
};
|
|
||||||
let desc1_bytes: &[u8] = unsafe {
|
|
||||||
core::slice::from_raw_parts(desc_ptr.add((tail as usize) * 16), 16)
|
|
||||||
};
|
|
||||||
let avail_ptr = self.avail.as_ptr();
|
|
||||||
let avail_idx_val = unsafe { (avail_ptr.add(2) as *const u16).read_unaligned() };
|
|
||||||
let used_idx_val = {
|
|
||||||
let used_ptr = self.used.as_ptr();
|
|
||||||
unsafe { (used_ptr.add(2) as *const u16).read_unaligned() }
|
|
||||||
};
|
|
||||||
info!(
|
|
||||||
"redox-drm: VirtQueue desc[{}]={:02x?} desc[{}]={:02x?} avail_idx={} used_idx={} last_used={}",
|
|
||||||
head, desc0_bytes, tail, desc1_bytes, avail_idx_val, used_idx_val, self.last_used_idx
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fence(Ordering::SeqCst);
|
fence(Ordering::SeqCst);
|
||||||
|
|
||||||
self.push_avail(head);
|
self.push_avail(head);
|
||||||
@@ -161,7 +131,6 @@ impl Virtqueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Err(error) = self.wait_used(head, timeout) {
|
if let Err(error) = self.wait_used(head, timeout) {
|
||||||
self.failed = true;
|
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +157,10 @@ impl Virtqueue {
|
|||||||
fn wait_used(&mut self, expected_head: u16, timeout: Duration) -> Result<()> {
|
fn wait_used(&mut self, expected_head: u16, timeout: Duration) -> Result<()> {
|
||||||
let deadline = Instant::now() + timeout;
|
let deadline = Instant::now() + timeout;
|
||||||
loop {
|
loop {
|
||||||
|
// Ensure we see QEMU's DMA writes to the used ring.
|
||||||
|
// Without this fence, the CPU may read a stale used_idx from
|
||||||
|
// its cache while QEMU has already written the completion via DMA.
|
||||||
|
fence(Ordering::SeqCst);
|
||||||
let used_idx = self.read_used_idx();
|
let used_idx = self.read_used_idx();
|
||||||
if used_idx != self.last_used_idx {
|
if used_idx != self.last_used_idx {
|
||||||
let slot = usize::from(self.last_used_idx % self.size);
|
let slot = usize::from(self.last_used_idx % self.size);
|
||||||
@@ -195,7 +168,8 @@ impl Virtqueue {
|
|||||||
self.last_used_idx = self.last_used_idx.wrapping_add(1);
|
self.last_used_idx = self.last_used_idx.wrapping_add(1);
|
||||||
self.free_chain(elem.id as u16)?;
|
self.free_chain(elem.id as u16)?;
|
||||||
if elem.id as u16 != expected_head {
|
if elem.id as u16 != expected_head {
|
||||||
self.failed = true;
|
// Out-of-order completion — log but don't permanently fail.
|
||||||
|
// The descriptor chain has been freed; the caller will retry or propagate.
|
||||||
return Err(DriverError::Io(format!(
|
return Err(DriverError::Io(format!(
|
||||||
"VirtIO queue {} completed descriptor head {} while waiting for {}",
|
"VirtIO queue {} completed descriptor head {} while waiting for {}",
|
||||||
self.index, elem.id, expected_head
|
self.index, elem.id, expected_head
|
||||||
@@ -205,6 +179,10 @@ impl Virtqueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if Instant::now() >= deadline {
|
if Instant::now() >= deadline {
|
||||||
|
// Timeout: reclaim the pending chain so the queue stays usable.
|
||||||
|
// Do NOT set self.failed — a single timeout should not permanently
|
||||||
|
// disable the entire queue.
|
||||||
|
self.reclaim_pending_chain(expected_head);
|
||||||
return Err(DriverError::Io(format!(
|
return Err(DriverError::Io(format!(
|
||||||
"VirtIO queue {} timed out waiting for descriptor head {}",
|
"VirtIO queue {} timed out waiting for descriptor head {}",
|
||||||
self.index, expected_head
|
self.index, expected_head
|
||||||
|
|||||||
@@ -125,6 +125,8 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
|
|||||||
daemon.ready();
|
daemon.ready();
|
||||||
|
|
||||||
let mut handler = ReadinessBased::new(&socket, 16);
|
let mut handler = ReadinessBased::new(&socket, 16);
|
||||||
|
let mut scheme_err_logged = false;
|
||||||
|
let mut response_err_logged = false;
|
||||||
loop {
|
loop {
|
||||||
match handler.read_requests() {
|
match handler.read_requests() {
|
||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
@@ -133,7 +135,10 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("redox-drm: failed to receive scheme request: {}", e);
|
if !scheme_err_logged {
|
||||||
|
error!("redox-drm: failed to receive scheme request: {} (suppressing further errors)", e);
|
||||||
|
scheme_err_logged = true;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +146,10 @@ fn run(daemon: daemon::Daemon) -> Result<()> {
|
|||||||
handler.process_requests(|| drm_scheme.lock().expect("DRM scheme state poisoned"));
|
handler.process_requests(|| drm_scheme.lock().expect("DRM scheme state poisoned"));
|
||||||
|
|
||||||
if let Err(e) = handler.write_responses() {
|
if let Err(e) = handler.write_responses() {
|
||||||
error!("redox-drm: failed to write scheme responses: {}", e);
|
if !response_err_logged {
|
||||||
|
error!("redox-drm: failed to write scheme responses: {} (suppressing further errors)", e);
|
||||||
|
response_err_logged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ add_subdirectory(src)
|
|||||||
|
|
||||||
# Enable unit testing
|
# Enable unit testing
|
||||||
if (BUILD_TESTING)
|
if (BUILD_TESTING)
|
||||||
############################################################ add_subdirectory(autotests)
|
################################################################## add_subdirectory(autotests)
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ cmake "${COOKBOOK_SOURCE}" \
|
|||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_PREFIX_PATH="${COOKBOOK_SYSROOT}" \
|
-DCMAKE_PREFIX_PATH="${COOKBOOK_SYSROOT}" \
|
||||||
-DBUILD_TESTING=OFF \
|
-DBUILD_TESTING=OFF \
|
||||||
|
-DBUILD_DOC=OFF \
|
||||||
-DBUILD_QCH=OFF \
|
-DBUILD_QCH=OFF \
|
||||||
-Wno-dev
|
-Wno-dev
|
||||||
|
|
||||||
|
|||||||
@@ -144,6 +144,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
# shall we use DBus?
|
# shall we use DBus?
|
||||||
# enabled per default on Linux & BSD systems
|
# enabled per default on Linux & BSD systems
|
||||||
|
|||||||
@@ -122,6 +122,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
||||||
|
|
||||||
|
|||||||
@@ -113,6 +113,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
find_package(KF6Codecs ${KF_DEP_VERSION} REQUIRED)
|
find_package(KF6Codecs ${KF_DEP_VERSION} REQUIRED)
|
||||||
find_package(KF6Config ${KF_DEP_VERSION} REQUIRED)
|
find_package(KF6Config ${KF_DEP_VERSION} REQUIRED)
|
||||||
|
|||||||
@@ -116,6 +116,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
# shall we use DBus?
|
# shall we use DBus?
|
||||||
# enabled per default on Linux & BSD systems
|
# enabled per default on Linux & BSD systems
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ find_package(KF6GuiAddons ${KF_DEP_VERSION} REQUIRED)
|
|||||||
|
|
||||||
|
|
||||||
if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT REDOX)
|
if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT REDOX)
|
||||||
################################################################################### find_package(KF6GlobalAccel ${KF_DEP_VERSION} REQUIRED)
|
######################################################################################### find_package(KF6GlobalAccel ${KF_DEP_VERSION} REQUIRED)
|
||||||
set(HAVE_KGLOBALACCEL TRUE)
|
set(HAVE_KGLOBALACCEL TRUE)
|
||||||
else()
|
else()
|
||||||
set(HAVE_KGLOBALACCEL FALSE)
|
set(HAVE_KGLOBALACCEL FALSE)
|
||||||
|
|||||||
@@ -136,6 +136,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6Svg ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt6Svg ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
# shall we use DBus?
|
# shall we use DBus?
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ set_package_properties(Qt6Qml PROPERTIES
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (TARGET Qt6::Qml)
|
if (TARGET Qt6::Qml)
|
||||||
############################################################## include(ECMQmlModule)
|
#################################################################### include(ECMQmlModule)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
if (TARGET Qt6::Qml)
|
if (TARGET Qt6::Qml)
|
||||||
############################################################# add_subdirectory(qml)
|
################################################################### add_subdirectory(qml)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
ecm_qt_install_logging_categories(
|
ecm_qt_install_logging_categories(
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
set(EXCLUDE_DEPRECATED_BEFORE_AND_AT 0 CACHE STRING "Control the range of deprecated API excluded from the build [default=0].")
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT HAIKU)
|
||||||
option(WITH_X11 "Build with support for QX11Info::appUserTime()" ON)
|
option(WITH_X11 "Build with support for QX11Info::appUserTime()" ON)
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
|||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED)
|
||||||
|
|
||||||
if (WITH_TEXT_TO_SPEECH)
|
if (WITH_TEXT_TO_SPEECH)
|
||||||
find_package(Qt6 ${REQUIRED_QT_VERSION} CONFIG REQUIRED TextToSpeech)
|
find_package(Qt6 ${REQUIRED_QT_VERSION} CONFIG REQUIRED TextToSpeech)
|
||||||
|
|||||||
@@ -122,6 +122,12 @@ find_package(Qt6WaylandClientPrivate REQUIRED)
|
|||||||
find_package(Qt6WaylandClientPrivate REQUIRED)
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
find_package(Qt6WaylandClientPrivate REQUIRED)
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
find_package(Qt6WaylandClientPrivate REQUIRED)
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
|
find_package(Qt6WaylandClientPrivate REQUIRED)
|
||||||
set_package_properties(Wayland PROPERTIES
|
set_package_properties(Wayland PROPERTIES
|
||||||
TYPE REQUIRED
|
TYPE REQUIRED
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ void initializeLanguages()
|
|||||||
// Ideally setting the LANGUAGE would change the default QLocale too
|
// Ideally setting the LANGUAGE would change the default QLocale too
|
||||||
// but unfortunately this is too late since the QCoreApplication constructor
|
// but unfortunately this is too late since the QCoreApplication constructor
|
||||||
// already created a QLocale at this stage so we need to set the reset it
|
// already created a QLocale at this stage so we need to set the reset it
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // by triggering the creation and destruction of a QSystemLocale
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // by triggering the creation and destruction of a QSystemLocale
|
||||||
// this is highly dependent on Qt internals, so may break, but oh well
|
// this is highly dependent on Qt internals, so may break, but oh well
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QSystemLocale *dummy = new QSystemLocale();
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// QSystemLocale *dummy = new QSystemLocale();
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// delete dummy;
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// delete dummy;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ ecm_set_disabled_deprecation_versions(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory( src )
|
add_subdirectory( src )
|
||||||
#################################if (BUILD_TESTING)
|
#######################################if (BUILD_TESTING)
|
||||||
################################# add_subdirectory( autotests )
|
####################################### add_subdirectory( autotests )
|
||||||
#################################endif()
|
#######################################endif()
|
||||||
|
|
||||||
if (BUILD_QCH)
|
if (BUILD_QCH)
|
||||||
ecm_install_qch_export(
|
ecm_install_qch_export(
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ set_package_properties(PList PROPERTIES
|
|||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME MATCHES Linux)
|
if (CMAKE_SYSTEM_NAME MATCHES Linux)
|
||||||
# Used by the UDisks backend on Linux
|
# Used by the UDisks backend on Linux
|
||||||
####################################################################################################find_package(LibMount)
|
##########################################################################################################find_package(LibMount)
|
||||||
set_package_properties(LibMount PROPERTIES
|
set_package_properties(LibMount PROPERTIES
|
||||||
TYPE REQUIRED)
|
TYPE REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -124,6 +124,14 @@
|
|||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
|
||||||
#include "config-kwin.h"
|
#include "config-kwin.h"
|
||||||
|
|
||||||
|
|||||||
@@ -110,34 +110,12 @@ static bool activate(const QString &sessionPath)
|
|||||||
|
|
||||||
std::unique_ptr<ConsoleKitSession> ConsoleKitSession::create()
|
std::unique_ptr<ConsoleKitSession> ConsoleKitSession::create()
|
||||||
{
|
{
|
||||||
if (!QDBusConnection::systemBus().interface()->isServiceRegistered(s_serviceName)) {
|
// Red Bear OS: No ConsoleKit. Skip ConsoleKitSession entirely so Session::create()
|
||||||
return nullptr;
|
// falls through to NoopSession, which opens DRM devices directly via ::open().
|
||||||
}
|
// Connecting to the system bus to check isServiceRegistered() can block
|
||||||
|
// indefinitely if the D-Bus daemon accepts the connection but doesn't implement
|
||||||
const QString sessionPath = findProcessSessionPath();
|
// the org.freedesktop.DBus interface methods Qt expects.
|
||||||
if (sessionPath.isEmpty()) {
|
return nullptr;
|
||||||
qCWarning(KWIN_CORE) << "Could not determine the active graphical session";
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!activate(sessionPath)) {
|
|
||||||
qCWarning(KWIN_CORE, "Failed to activate %s session. Maybe another compositor is running?",
|
|
||||||
qPrintable(sessionPath));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!takeControl(sessionPath)) {
|
|
||||||
qCWarning(KWIN_CORE, "Failed to take control of %s session. Maybe another compositor is running?",
|
|
||||||
qPrintable(sessionPath));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<ConsoleKitSession> session{new ConsoleKitSession(sessionPath)};
|
|
||||||
if (session->initialize()) {
|
|
||||||
return session;
|
|
||||||
} else {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConsoleKitSession::isActive() const
|
bool ConsoleKitSession::isActive() const
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
#####################################################################################################################add_subdirectory(killer) # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only
|
#############################################################################################################################add_subdirectory(killer) # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only # disabled: X11-only
|
||||||
add_subdirectory(wayland_wrapper)
|
add_subdirectory(wayland_wrapper)
|
||||||
|
|||||||
@@ -349,6 +349,30 @@
|
|||||||
#ifndef SUN_LEN
|
#ifndef SUN_LEN
|
||||||
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
|
#ifndef SUN_LEN
|
||||||
|
#define SUN_LEN(s) (sizeof(*(s)) - sizeof((s)->sun_path) + strnlen((s)->sun_path, sizeof((s)->sun_path)))
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
KWin - the KDE window manager
|
KWin - the KDE window manager
|
||||||
This file is part of the KDE project.
|
This file is part of the KDE project.
|
||||||
|
|||||||
@@ -272,9 +272,17 @@ XwaylandInterface *ApplicationWayland::xwayland() const
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] main() entered, pid=%d\n", getpid());
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
KWin::Application::setupMalloc();
|
KWin::Application::setupMalloc();
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] setupMalloc done\n"); fflush(stderr);
|
||||||
|
|
||||||
KWin::Application::setupLocalizedString();
|
KWin::Application::setupLocalizedString();
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] setupLocalizedString done\n"); fflush(stderr);
|
||||||
|
|
||||||
KWin::gainRealTime();
|
KWin::gainRealTime();
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] gainRealTime done\n"); fflush(stderr);
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
|
||||||
@@ -285,6 +293,8 @@ int main(int argc, char *argv[])
|
|||||||
pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit);
|
pthread_atfork(nullptr, nullptr, KWin::restoreNofileLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] nofile limit bumped\n"); fflush(stderr);
|
||||||
|
|
||||||
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
|
||||||
|
|
||||||
// enforce our internal qpa plugin, unfortunately command line switch has precedence
|
// enforce our internal qpa plugin, unfortunately command line switch has precedence
|
||||||
@@ -295,8 +305,13 @@ int main(int argc, char *argv[])
|
|||||||
// The gains are minimal, disable until it's fixed
|
// The gains are minimal, disable until it's fixed
|
||||||
QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache);
|
QCoreApplication::setAttribute(Qt::AA_DisableShaderDiskCache);
|
||||||
|
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] about to construct ApplicationWayland, QT_QPA_PLATFORM=%s\n", getenv("QT_QPA_PLATFORM"));
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
KWin::ApplicationWayland a(argc, argv);
|
KWin::ApplicationWayland a(argc, argv);
|
||||||
|
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] ApplicationWayland constructed OK\n"); fflush(stderr);
|
||||||
|
|
||||||
// reset QT_QPA_PLATFORM so we don't propagate it to our children (e.g. apps launched from the overview effect)
|
// reset QT_QPA_PLATFORM so we don't propagate it to our children (e.g. apps launched from the overview effect)
|
||||||
qunsetenv("QT_QPA_PLATFORM");
|
qunsetenv("QT_QPA_PLATFORM");
|
||||||
|
|
||||||
@@ -512,14 +527,20 @@ int main(int argc, char *argv[])
|
|||||||
outputCount = std::max(1, count);
|
outputCount = std::max(1, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] backend type selected: %d (Kms=0,X11=1,Wayland=2,Virtual=3)\n", (int)backendType);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
switch (backendType) {
|
switch (backendType) {
|
||||||
case BackendType::Kms:
|
case BackendType::Kms:
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] creating session...\n"); fflush(stderr);
|
||||||
a.setSession(KWin::Session::create());
|
a.setSession(KWin::Session::create());
|
||||||
if (!a.session()) {
|
if (!a.session()) {
|
||||||
std::cerr << "FATAl ERROR: could not acquire a session" << std::endl;
|
std::cerr << "FATAl ERROR: could not acquire a session" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] session created, creating DrmBackend...\n"); fflush(stderr);
|
||||||
a.setOutputBackend(std::make_unique<KWin::DrmBackend>(a.session()));
|
a.setOutputBackend(std::make_unique<KWin::DrmBackend>(a.session()));
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] DrmBackend created\n"); fflush(stderr);
|
||||||
break;
|
break;
|
||||||
case BackendType::Virtual: {
|
case BackendType::Virtual: {
|
||||||
auto outputBackend = std::make_unique<KWin::VirtualBackend>();
|
auto outputBackend = std::make_unique<KWin::VirtualBackend>();
|
||||||
@@ -636,7 +657,9 @@ int main(int argc, char *argv[])
|
|||||||
a.setProcessStartupEnvironment(environment);
|
a.setProcessStartupEnvironment(environment);
|
||||||
a.setApplicationsToStart(parser.positionalArguments());
|
a.setApplicationsToStart(parser.positionalArguments());
|
||||||
a.setInputMethodServerToStart(parser.value(inputMethodOption));
|
a.setInputMethodServerToStart(parser.value(inputMethodOption));
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] about to call a.start()\n"); fflush(stderr);
|
||||||
a.start();
|
a.start();
|
||||||
|
fprintf(stderr, "[REDBEAR-KWIN] a.start() done, entering event loop\n"); fflush(stderr);
|
||||||
|
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ target_link_libraries(systembell PRIVATE
|
|||||||
|
|
||||||
KF6::GlobalAccel
|
KF6::GlobalAccel
|
||||||
KF6::I18n
|
KF6::I18n
|
||||||
$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,Canberra::Canberra,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>
|
$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,$<IF:$<BOOL:${Canberra_FOUND}>,Canberra::Canberra,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>,>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -124,6 +124,14 @@
|
|||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
#include <libudev.h>
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
#include <libudev.h>
|
||||||
|
|
||||||
#include "backends/libinput/device.h"
|
#include "backends/libinput/device.h"
|
||||||
#include "core/inputdevice.h"
|
#include "core/inputdevice.h"
|
||||||
|
|||||||
@@ -700,6 +700,54 @@
|
|||||||
#define F_SEAL_SHRINK 0x0002
|
#define F_SEAL_SHRINK 0x0002
|
||||||
#define F_SEAL_GROW 0x0004
|
#define F_SEAL_GROW 0x0004
|
||||||
#define F_SEAL_WRITE 0x0008
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
|
#define F_ADD_SEALS 1033
|
||||||
|
#define F_GET_SEALS 1034
|
||||||
|
#define F_SEAL_SEAL 0x0001
|
||||||
|
#define F_SEAL_SHRINK 0x0002
|
||||||
|
#define F_SEAL_GROW 0x0004
|
||||||
|
#define F_SEAL_WRITE 0x0008
|
||||||
/*
|
/*
|
||||||
KWin - the KDE window manager
|
KWin - the KDE window manager
|
||||||
This file is part of the KDE project.
|
This file is part of the KDE project.
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
#TODO: SDDM display manager — Wayland-only build. PAM provided by pam-redbear shim.
|
||||||
|
# X11/XCB/XAUTH fully excluded via wayland-patch.sh (NO_X11 ifdef guards).
|
||||||
|
# XcbKeyboardBackend removed from greeter; XorgDisplayServer/XorgUserDisplayServer/XAuth
|
||||||
|
# removed from daemon. Default display server fallback is Wayland.
|
||||||
|
[source]
|
||||||
|
git = "https://github.com/sddm/sddm.git"
|
||||||
|
rev = "bc9eee8280275723767213220e88f6b14157ba1f"
|
||||||
|
patches = []
|
||||||
|
|
||||||
|
[build]
|
||||||
|
template = "custom"
|
||||||
|
dependencies = [
|
||||||
|
"qtbase",
|
||||||
|
"qtdeclarative",
|
||||||
|
"qtwayland",
|
||||||
|
"qtsvg",
|
||||||
|
"kf6-extra-cmake-modules",
|
||||||
|
"kf6-kcoreaddons",
|
||||||
|
"kf6-ki18n",
|
||||||
|
"kf6-kcrash",
|
||||||
|
"kf6-kdbusaddons",
|
||||||
|
"kf6-kconfig",
|
||||||
|
"kf6-kwindowsystem",
|
||||||
|
"kf6-kguiaddons",
|
||||||
|
"wayland-protocols",
|
||||||
|
"libwayland",
|
||||||
|
"pam-redbear",
|
||||||
|
]
|
||||||
|
script = """
|
||||||
|
DYNAMIC_INIT
|
||||||
|
|
||||||
|
HOST_BUILD="${COOKBOOK_ROOT}/build/qt-host-build"
|
||||||
|
STAGE="${COOKBOOK_STAGE}/usr"
|
||||||
|
|
||||||
|
source "${COOKBOOK_ROOT}/local/scripts/lib/qt-sysroot.sh"
|
||||||
|
redbear_qt_link_sysroot_dirs "${COOKBOOK_SYSROOT}" plugins mkspecs metatypes modules
|
||||||
|
|
||||||
|
if [ -d "${COOKBOOK_SYSROOT}/plugins" ] && [ ! -L "${COOKBOOK_SYSROOT}/plugins" ]; then
|
||||||
|
if [ -d "${COOKBOOK_SYSROOT}/usr/plugins" ]; then
|
||||||
|
cp -an "${COOKBOOK_SYSROOT}/plugins/." "${COOKBOOK_SYSROOT}/usr/plugins/" 2>/dev/null || true
|
||||||
|
rm -rf "${COOKBOOK_SYSROOT}/plugins"
|
||||||
|
ln -s usr/plugins "${COOKBOOK_SYSROOT}/plugins"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
CROSS_PKGCONFIG="${COOKBOOK_ROOT}/bin/x86_64-unknown-redox-pkg-config"
|
||||||
|
|
||||||
|
sed -i 's/find_package(XCB REQUIRED)/find_package(XCB QUIET)/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/find_package(XKB REQUIRED)/find_package(XKB QUIET)/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/pkg_check_modules(LIBXAU REQUIRED "xau")/pkg_check_modules(LIBXAU QUIET "xau")/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/find_package(Qt${QT_MAJOR_VERSION}.*CONFIG REQUIRED.*/find_package(Qt${QT_MAJOR_VERSION} 5.15.0 CONFIG REQUIRED Core Network DBus Gui Qml Quick)/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/find_package(Qt${QT_MAJOR_VERSION}Test)/find_package(Qt${QT_MAJOR_VERSION}Test QUIET)/' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i '/add_subdirectory(test)/d' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i '/enable_testing/d' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i '/qt_add_translation/d' {} + 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i '/LIBXCB_INCLUDE_DIR/d' {} + 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i 's/${LIBXCB_LIBRARIES}//' {} + 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i 's/${LIBXKB_LIBRARIES}//' {} + 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i 's/${LIBXAU_LIBRARIES}//' {} + 2>/dev/null || true
|
||||||
|
find "${COOKBOOK_SOURCE}" -name "CMakeLists.txt" -exec sed -i 's/${LIBXAU_INCLUDE_DIRS}//' {} + 2>/dev/null || true
|
||||||
|
|
||||||
|
if grep -q 'find_package(LibJournald' "${COOKBOOK_SOURCE}/CMakeLists.txt" 2>/dev/null; then
|
||||||
|
sed -i 's/find_package(LibJournald REQUIRED)/find_package(LibJournald QUIET)/' "${COOKBOOK_SOURCE}/CMakeLists.txt"
|
||||||
|
fi
|
||||||
|
|
||||||
|
sed -i '/XAuth\\.cpp/d' "${COOKBOOK_SOURCE}/src/helper/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/${LIBXAU_LINK_LIBRARIES}//' "${COOKBOOK_SOURCE}/src/helper/CMakeLists.txt" 2>/dev/null || true
|
||||||
|
sed -i 's/ioctl(STDIN_FILENO, TIOCSCTTY)/ioctl(STDIN_FILENO, TIOCSCTTY, NULL)/' "${COOKBOOK_SOURCE}/src/helper/UserSession.cpp" 2>/dev/null || true
|
||||||
|
sed -i 's/XAuth::writeCookieToFile(display, m_xauthFile.fileName(), cookie)/true/' "${COOKBOOK_SOURCE}/src/helper/UserSession.cpp" 2>/dev/null || true
|
||||||
|
sed -i '/#include "XAuth.h"/d' "${COOKBOOK_SOURCE}/src/helper/UserSession.cpp" 2>/dev/null || true
|
||||||
|
python3 "${COOKBOOK_RECIPE}/remove-x11user-helper.py" "${COOKBOOK_SOURCE}/src/helper/CMakeLists.txt"
|
||||||
|
|
||||||
|
cp -r "${COOKBOOK_RECIPE}/stubs/"* "${COOKBOOK_SYSROOT}/usr/include/"
|
||||||
|
|
||||||
|
chmod +x "${COOKBOOK_RECIPE}/wayland-patch.sh"
|
||||||
|
"${COOKBOOK_RECIPE}/wayland-patch.sh" "${COOKBOOK_SOURCE}"
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
|
||||||
|
rm -f CMakeCache.txt
|
||||||
|
rm -rf CMakeFiles
|
||||||
|
|
||||||
|
cmake "${COOKBOOK_SOURCE}" \
|
||||||
|
-DCMAKE_TOOLCHAIN_FILE="${COOKBOOK_ROOT}/local/recipes/qt/redox-toolchain.cmake" \
|
||||||
|
-DQT_HOST_PATH="${HOST_BUILD}" \
|
||||||
|
-DKF6_HOST_TOOLING="${HOST_BUILD}/lib/cmake" \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_PREFIX_PATH="${COOKBOOK_SYSROOT}/usr;${COOKBOOK_SYSROOT}" \
|
||||||
|
-DPKG_CONFIG_EXECUTABLE="${CROSS_PKGCONFIG}" \
|
||||||
|
-DBUILD_TESTING=OFF \
|
||||||
|
-DBUILD_WITH_QT6=ON \
|
||||||
|
-DNO_SYSTEMD=ON \
|
||||||
|
-DENABLE_JOURNALD=OFF \
|
||||||
|
-DENABLE_PAM=ON \
|
||||||
|
-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE \
|
||||||
|
-DCMAKE_INSTALL_RPATH="/usr/lib" \
|
||||||
|
-Wno-dev
|
||||||
|
|
||||||
|
cmake --build . -j${COOKBOOK_MAKE_JOBS}
|
||||||
|
DESTDIR="${COOKBOOK_STAGE}" cmake --install . --prefix /usr
|
||||||
|
|
||||||
|
for bin in "${STAGE}/bin/"* "${STAGE}/lib/"lib*.so.*; do
|
||||||
|
[ -f "${bin}" ] || continue
|
||||||
|
patchelf --set-rpath "/usr/lib" "${bin}" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
"""
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import re, sys
|
||||||
|
|
||||||
|
path = sys.argv[1]
|
||||||
|
with open(path) as f:
|
||||||
|
c = f.read()
|
||||||
|
|
||||||
|
c = re.sub(
|
||||||
|
r'\nadd_executable\(sddm-helper-start-x11user.*?\ninstall\(TARGETS sddm-helper-start-x11user[^)]*\)',
|
||||||
|
'', c, flags=re.DOTALL
|
||||||
|
)
|
||||||
|
c = c.replace(
|
||||||
|
' target_link_libraries(sddm-helper-start-x11user ${JOURNALD_LIBRARIES})\n', ''
|
||||||
|
)
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(c)
|
||||||
Submodule
+1
Submodule local/recipes/kde/sddm/source added at bc9eee8280
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _X11_XAUTH_H
|
||||||
|
#define _X11_XAUTH_H
|
||||||
|
|
||||||
|
typedef unsigned short Family;
|
||||||
|
#define FamilyLocal 256
|
||||||
|
|
||||||
|
typedef struct _Xauth {
|
||||||
|
unsigned short family;
|
||||||
|
unsigned short address_length;
|
||||||
|
char *address;
|
||||||
|
unsigned short number_length;
|
||||||
|
char *number;
|
||||||
|
unsigned short name_length;
|
||||||
|
char *name;
|
||||||
|
unsigned short data_length;
|
||||||
|
char *data;
|
||||||
|
} Xauth;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _LINUX_KD_H
|
||||||
|
#define _LINUX_KD_H
|
||||||
|
|
||||||
|
#define KDSETMODE 0x4B3A
|
||||||
|
#define KDGETMODE 0x4B3B
|
||||||
|
#define KD_TEXT 0x00
|
||||||
|
#define KD_GRAPHICS 0x01
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef _LINUX_VT_H
|
||||||
|
#define _LINUX_VT_H
|
||||||
|
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#define VT_OPENQRY 0x5600
|
||||||
|
#define VT_GETMODE 0x5601
|
||||||
|
#define VT_SETMODE 0x5602
|
||||||
|
#define VT_GETSTATE 0x5603
|
||||||
|
#define VT_SENDSIG 0x5604
|
||||||
|
#define VT_RELDISP 0x5605
|
||||||
|
#define VT_ACTIVATE 0x5606
|
||||||
|
#define VT_WAITACTIVE 0x5607
|
||||||
|
#define VT_DISALLOCATE 0x5608
|
||||||
|
#define VT_GETACTIVE 0x5609
|
||||||
|
|
||||||
|
#define VT_AUTO 0x00
|
||||||
|
#define VT_PROCESS 0x01
|
||||||
|
|
||||||
|
#define VT_ACKACQ 2
|
||||||
|
|
||||||
|
#define KDSETMODE 0x4B3A
|
||||||
|
#define KDGETMODE 0x4B3B
|
||||||
|
#define KD_TEXT 0x00
|
||||||
|
#define KD_GRAPHICS 0x01
|
||||||
|
|
||||||
|
struct vt_stat {
|
||||||
|
unsigned short v_active;
|
||||||
|
unsigned short v_signal;
|
||||||
|
unsigned short v_state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vt_mode {
|
||||||
|
unsigned char mode;
|
||||||
|
unsigned char waitv;
|
||||||
|
unsigned short relsig;
|
||||||
|
unsigned short acqsig;
|
||||||
|
unsigned short frsig;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#ifndef _UTMPX_H
|
||||||
|
#define _UTMPX_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define UTMPX_FILE "/var/run/utmpx"
|
||||||
|
|
||||||
|
#define EMPTY 0
|
||||||
|
#define RUN_LVL 1
|
||||||
|
#define BOOT_TIME 2
|
||||||
|
#define NEW_TIME 3
|
||||||
|
#define OLD_TIME 4
|
||||||
|
#define INIT_PROCESS 5
|
||||||
|
#define LOGIN_PROCESS 6
|
||||||
|
#define USER_PROCESS 7
|
||||||
|
#define DEAD_PROCESS 8
|
||||||
|
|
||||||
|
struct utmpx {
|
||||||
|
short ut_type;
|
||||||
|
pid_t ut_pid;
|
||||||
|
char ut_line[32];
|
||||||
|
char ut_id[4];
|
||||||
|
char ut_user[32];
|
||||||
|
char ut_host[256];
|
||||||
|
struct timeval ut_tv;
|
||||||
|
struct {
|
||||||
|
int32_t __e_termination;
|
||||||
|
int32_t __e_exit;
|
||||||
|
} ut_exit;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void setutxent(void) {}
|
||||||
|
static inline void endutxent(void) {}
|
||||||
|
static inline struct utmpx *getutxent(void) { return NULL; }
|
||||||
|
static inline struct utmpx *getutxid(const struct utmpx *id) { (void)id; return NULL; }
|
||||||
|
static inline struct utmpx *getutxline(const struct utmpx *line) { (void)line; return NULL; }
|
||||||
|
static inline int pututxline(const struct utmpx *ut) { (void)ut; return -1; }
|
||||||
|
static inline int utmpxname(const char *file) { (void)file; return -1; }
|
||||||
|
|
||||||
|
#endif
|
||||||
Executable
+245
@@ -0,0 +1,245 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SRC="$1"
|
||||||
|
if [ -z "$SRC" ]; then
|
||||||
|
echo "Usage: $0 <source-directory>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "=== Applying Wayland-only patches to SDDM ==="
|
||||||
|
|
||||||
|
# === CMakeLists.txt: add NO_X11 compile definition ===
|
||||||
|
sed -i 's/^add_definitions(-Wall/add_definitions(-DNO_X11 -Wall/' "${SRC}/CMakeLists.txt"
|
||||||
|
|
||||||
|
# === Daemon CMakeLists: remove X11-only source files ===
|
||||||
|
sed -i '/XAuth\.cpp/d' "${SRC}/src/daemon/CMakeLists.txt"
|
||||||
|
sed -i '/XorgDisplayServer\.cpp/d' "${SRC}/src/daemon/CMakeLists.txt"
|
||||||
|
sed -i '/XorgUserDisplayServer/d' "${SRC}/src/daemon/CMakeLists.txt"
|
||||||
|
sed -i '/LIBXAU_LINK_LIBRARIES/d' "${SRC}/src/daemon/CMakeLists.txt"
|
||||||
|
|
||||||
|
# === Greeter CMakeLists: remove XCB keyboard backend ===
|
||||||
|
sed -i '/XcbKeyboardBackend\.cpp/d' "${SRC}/src/greeter/CMakeLists.txt"
|
||||||
|
|
||||||
|
# === Greeter CMakeLists: add Qt6::Network for QLocalSocket ===
|
||||||
|
sed -i 's|Qt\${QT_MAJOR_VERSION}::Quick[[:space:]]*$|Qt${QT_MAJOR_VERSION}::Quick\n Qt${QT_MAJOR_VERSION}::Network|' \
|
||||||
|
"${SRC}/src/greeter/CMakeLists.txt"
|
||||||
|
|
||||||
|
# === Multiline patches via Python ===
|
||||||
|
SDDM_SRC="$SRC" python3 << 'PYEOF'
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
|
||||||
|
def patch_file(path, replacements):
|
||||||
|
with open(path, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
for pattern, repl, desc in replacements:
|
||||||
|
new_content = re.sub(pattern, repl, content, flags=re.DOTALL)
|
||||||
|
if new_content == content:
|
||||||
|
print(f" WARNING: pattern not matched in {path}: {desc}")
|
||||||
|
content = new_content
|
||||||
|
with open(path, 'w') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
src = os.environ.get('SDDM_SRC', '.')
|
||||||
|
|
||||||
|
# ---- KeyboardModel.cpp ----
|
||||||
|
patch_file(f"{src}/src/greeter/KeyboardModel.cpp", [
|
||||||
|
(r'#include "XcbKeyboardBackend\.h"',
|
||||||
|
'#ifndef NO_X11\n#include "XcbKeyboardBackend.h"\n#endif',
|
||||||
|
"XcbKeyboardBackend include"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(QGuiApplication::platformName\(\) == QLatin1String\("xcb"\)\) \{\n'
|
||||||
|
r'\s+m_backend = new XcbKeyboardBackend\(d\);\n'
|
||||||
|
r'\s+m_backend->init\(\);\n'
|
||||||
|
r'\s+m_backend->connectEventsDispatcher\(this\);\n'
|
||||||
|
r'\s+\} else (if)',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 if (QGuiApplication::platformName() == QLatin1String("xcb")) {\n'
|
||||||
|
r'\1 m_backend = new XcbKeyboardBackend(d);\n'
|
||||||
|
r'\1 m_backend->init();\n'
|
||||||
|
r'\1 m_backend->connectEventsDispatcher(this);\n'
|
||||||
|
r'\1 } else\n'
|
||||||
|
r'\1#endif\n'
|
||||||
|
r'\1 \2',
|
||||||
|
"XCB branch in constructor"),
|
||||||
|
])
|
||||||
|
|
||||||
|
# ---- Display.cpp ----
|
||||||
|
patch_file(f"{src}/src/daemon/Display.cpp", [
|
||||||
|
(r'#include "XorgDisplayServer\.h"\n#include "XorgUserDisplayServer\.h"',
|
||||||
|
'#ifndef NO_X11\n#include "XorgDisplayServer.h"\n#include "XorgUserDisplayServer.h"\n#endif',
|
||||||
|
"Xorg includes"),
|
||||||
|
|
||||||
|
(r'(\s+)case X11DisplayServerType:\n'
|
||||||
|
r'(\s+)if \(seat\(\)->canTTY\(\)\) \{\n'
|
||||||
|
r'\s+m_terminalId = VirtualTerminal::setUpNewVt\(\);\n'
|
||||||
|
r'\s+\}\n'
|
||||||
|
r'\s+m_displayServer = new XorgDisplayServer\(this\);\n'
|
||||||
|
r'\s+break;\n'
|
||||||
|
r'(\s+)case X11UserDisplayServerType:\n'
|
||||||
|
r'\s+if \(seat\(\)->canTTY\(\)\) \{\n'
|
||||||
|
r'\s+m_terminalId = fetchAvailableVt\(\);\n'
|
||||||
|
r'\s+\}\n'
|
||||||
|
r'\s+m_displayServer = new XorgUserDisplayServer\(this\);\n'
|
||||||
|
r'\s+m_greeter->setDisplayServerCommand\(XorgUserDisplayServer::command\(this\)\);\n'
|
||||||
|
r'\s+break;',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 case X11DisplayServerType:\n'
|
||||||
|
r'\2 if (seat()->canTTY()) {\n'
|
||||||
|
r' m_terminalId = VirtualTerminal::setUpNewVt();\n'
|
||||||
|
r' }\n'
|
||||||
|
r' m_displayServer = new XorgDisplayServer(this);\n'
|
||||||
|
r' break;\n'
|
||||||
|
r'\3 case X11UserDisplayServerType:\n'
|
||||||
|
r' if (seat()->canTTY()) {\n'
|
||||||
|
r' m_terminalId = fetchAvailableVt();\n'
|
||||||
|
r' }\n'
|
||||||
|
r' m_displayServer = new XorgUserDisplayServer(this);\n'
|
||||||
|
r' m_greeter->setDisplayServerCommand(XorgUserDisplayServer::command(this));\n'
|
||||||
|
r' break;\n'
|
||||||
|
r'\1#endif',
|
||||||
|
"X11 cases in constructor switch"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(session\.xdgSessionType\(\) == QLatin1String\("x11"\)\) \{\n'
|
||||||
|
r'(\s+)if \(m_displayServerType == X11DisplayServerType\)\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("DISPLAY"\), name\(\)\);\n'
|
||||||
|
r'(\s+)else\n'
|
||||||
|
r'(\s+)m_auth->setDisplayServerCommand\(XorgUserDisplayServer::command\(this\)\);\n'
|
||||||
|
r'(\s+)\} else \{',
|
||||||
|
r'\1if (session.xdgSessionType() == QLatin1String("x11")) {\n'
|
||||||
|
r'#ifndef NO_X11\n'
|
||||||
|
r'\2 if (m_displayServerType == X11DisplayServerType)\n'
|
||||||
|
r'\3 env.insert(QStringLiteral("DISPLAY"), name());\n'
|
||||||
|
r'\4 else\n'
|
||||||
|
r'\5 m_auth->setDisplayServerCommand(XorgUserDisplayServer::command(this));\n'
|
||||||
|
r'#endif\n'
|
||||||
|
r'\6} else {',
|
||||||
|
"XorgUserDisplayServer::command in startAuth"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(qobject_cast<XorgDisplayServer \*>\(m_displayServer\)\)\n'
|
||||||
|
r'(\s+)m_auth->setCookie\(qobject_cast<XorgDisplayServer \*>\(m_displayServer\)->cookie\(\)\);',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 if (qobject_cast<XorgDisplayServer *>(m_displayServer))\n'
|
||||||
|
r'\2 m_auth->setCookie(qobject_cast<XorgDisplayServer *>(m_displayServer)->cookie());\n'
|
||||||
|
r'\1#endif',
|
||||||
|
"XorgDisplayServer cookie in slotAuthenticationFinished"),
|
||||||
|
|
||||||
|
(r'(\s+qPrintable\(displayServerType\)\));\n'
|
||||||
|
r'(\s+)\}\n'
|
||||||
|
r'(\s+)ret = X11DisplayServerType;',
|
||||||
|
r'\1;\n'
|
||||||
|
r'\2}\n'
|
||||||
|
r'#ifndef NO_X11\n'
|
||||||
|
r'\3ret = X11DisplayServerType;\n'
|
||||||
|
r'#else\n'
|
||||||
|
r'\3ret = WaylandDisplayServerType;\n'
|
||||||
|
r'#endif',
|
||||||
|
"defaultDisplayServerType fallback"),
|
||||||
|
])
|
||||||
|
|
||||||
|
# ---- Greeter.cpp ----
|
||||||
|
patch_file(f"{src}/src/daemon/Greeter.cpp", [
|
||||||
|
(r'#include "XorgDisplayServer\.h"\n#include "XorgUserDisplayServer\.h"',
|
||||||
|
'#ifndef NO_X11\n#include "XorgDisplayServer.h"\n#include "XorgUserDisplayServer.h"\n#endif',
|
||||||
|
"Xorg includes"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(m_display->displayServerType\(\) == Display::X11DisplayServerType\) \{\n'
|
||||||
|
r'(\s+)// set process environment\n'
|
||||||
|
r'(\s+)QProcessEnvironment env = QProcessEnvironment::systemEnvironment\(\);\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("DISPLAY"\), m_display->name\(\)\);\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("XAUTHORITY"\), qobject_cast<XorgDisplayServer\*>\(displayServer\)->authPath\(\)\);\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("XCURSOR_THEME"\), xcursorTheme\);\n'
|
||||||
|
r'(\s+)if \(!xcursorSize\.isEmpty\(\)\)\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("XCURSOR_SIZE"\), xcursorSize\);\n'
|
||||||
|
r'(\s+)m_process->setProcessEnvironment\(env\);\n'
|
||||||
|
r'(\s+)\}',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 if (m_display->displayServerType() == Display::X11DisplayServerType) {\n'
|
||||||
|
r'\2 // set process environment\n'
|
||||||
|
r'\3 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();\n'
|
||||||
|
r'\4 env.insert(QStringLiteral("DISPLAY"), m_display->name());\n'
|
||||||
|
r'\5 env.insert(QStringLiteral("XAUTHORITY"), qobject_cast<XorgDisplayServer*>(displayServer)->authPath());\n'
|
||||||
|
r'\6 env.insert(QStringLiteral("XCURSOR_THEME"), xcursorTheme);\n'
|
||||||
|
r'\7 if (!xcursorSize.isEmpty())\n'
|
||||||
|
r'\8 env.insert(QStringLiteral("XCURSOR_SIZE"), xcursorSize);\n'
|
||||||
|
r'\9 m_process->setProcessEnvironment(env);\n'
|
||||||
|
r'\1 }\n'
|
||||||
|
r'\1#endif',
|
||||||
|
"X11 env in testing mode"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(m_display->displayServerType\(\) == Display::X11DisplayServerType\) \{\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("DISPLAY"\), m_display->name\(\)\);\n'
|
||||||
|
r'(\s+)env\.insert\(QStringLiteral\("QT_QPA_PLATFORM"\), QStringLiteral\("xcb"\)\);\n'
|
||||||
|
r'(\s+)m_auth->setCookie\(qobject_cast<XorgDisplayServer\*>\(displayServer\)->cookie\(\)\);\n'
|
||||||
|
r'(\s+)\} else if',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 if (m_display->displayServerType() == Display::X11DisplayServerType) {\n'
|
||||||
|
r'\2 env.insert(QStringLiteral("DISPLAY"), m_display->name());\n'
|
||||||
|
r'\3 env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("xcb"));\n'
|
||||||
|
r'\4 m_auth->setCookie(qobject_cast<XorgDisplayServer*>(displayServer)->cookie());\n'
|
||||||
|
r'\1 } else\n'
|
||||||
|
r'\1#endif\n'
|
||||||
|
r'\1 if',
|
||||||
|
"X11 env/cookie in non-testing mode"),
|
||||||
|
|
||||||
|
(r'(\s+)auto \*xorgUser = qobject_cast<XorgUserDisplayServer \*>\(displayServer\);\n'
|
||||||
|
r'(\s+)if \(xorgUser\)\n'
|
||||||
|
r'(\s+)xorgUser->setDisplayName\(displayName\);\n',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 auto *xorgUser = qobject_cast<XorgUserDisplayServer *>(displayServer);\n'
|
||||||
|
r'\2 if (xorgUser)\n'
|
||||||
|
r'\3 xorgUser->setDisplayName(displayName);\n'
|
||||||
|
r'\1#endif\n',
|
||||||
|
"XorgUserDisplayServer in onDisplayServerReady"),
|
||||||
|
])
|
||||||
|
|
||||||
|
# ---- Seat.cpp ----
|
||||||
|
patch_file(f"{src}/src/daemon/Seat.cpp", [
|
||||||
|
(r'#include "XorgDisplayServer\.h"\n',
|
||||||
|
'#ifndef NO_X11\n#include "XorgDisplayServer.h"\n#endif\n',
|
||||||
|
"Xorg include"),
|
||||||
|
|
||||||
|
(r'(\s+)// If we failed to create a display with wayland or rootful x11.*\n'
|
||||||
|
r'(\s+)// x11-user.*\n'
|
||||||
|
r'(\s+)// since.*\n'
|
||||||
|
r'(\s+)if \(display->displayServerType\(\) != Display::X11UserDisplayServerType\) \{\n'
|
||||||
|
r'(\s+)qWarning\(\) << "Failed to launch the display server, falling back to DisplayServer=x11-user";\n'
|
||||||
|
r'(\s+)createDisplay\(Display::X11UserDisplayServerType\);\n'
|
||||||
|
r'(\s+)\} else',
|
||||||
|
r'\1// Wayland-only: no X11 fallback available\n'
|
||||||
|
r'#ifndef NO_X11\n'
|
||||||
|
r'\1 // If we failed to create a display with wayland or rootful x11, try with\n'
|
||||||
|
r'\1 // x11-user. There\'s a chance it might work. It\'s a handy fallback\n'
|
||||||
|
r'\1 // since the alternative is a black screen\n'
|
||||||
|
r'\4 if (display->displayServerType() != Display::X11UserDisplayServerType) {\n'
|
||||||
|
r'\5 qWarning() << "Failed to launch the display server, falling back to DisplayServer=x11-user";\n'
|
||||||
|
r'\6 createDisplay(Display::X11UserDisplayServerType);\n'
|
||||||
|
r'\7 } else\n'
|
||||||
|
r'#endif\n',
|
||||||
|
"X11 fallback in Seat"),
|
||||||
|
])
|
||||||
|
|
||||||
|
# ---- UserSession.cpp ----
|
||||||
|
patch_file(f"{src}/src/helper/UserSession.cpp", [
|
||||||
|
(r'#include "XAuth\.h"',
|
||||||
|
'#ifndef NO_X11\n#include "XAuth.h"\n#endif',
|
||||||
|
"XAuth include"),
|
||||||
|
|
||||||
|
(r'(\s+)if \(!XAuth::writeCookieToFile\(display, m_xauthFile\.fileName\(\), cookie\)\) \{\n'
|
||||||
|
r'(\s+)const auto error = strerror\(errno\);\n'
|
||||||
|
r'(\s+)qCritical\(\) << .*;\n'
|
||||||
|
r'(\s+)_exit\(Auth::HELPER_AUTH_ERROR\);\n'
|
||||||
|
r'(\s+)\}',
|
||||||
|
r'\1#ifndef NO_X11\n'
|
||||||
|
r'\1 if (!XAuth::writeCookieToFile(display, m_xauthFile.fileName(), cookie)) {\n'
|
||||||
|
r'\2 const auto error = strerror(errno);\n'
|
||||||
|
r'\3 qCritical() << "Failed to write xauth cookie: " << error;\n'
|
||||||
|
r'\4 _exit(Auth::HELPER_AUTH_ERROR);\n'
|
||||||
|
r'\5 }\n'
|
||||||
|
r'\1#endif',
|
||||||
|
"XAuth cookie write"),
|
||||||
|
])
|
||||||
|
|
||||||
|
print("=== Wayland-only patches applied ===")
|
||||||
|
PYEOF
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[source]
|
[source]
|
||||||
tar = "https://gitlab.freedesktop.org/mesa/libdrm/-/archive/libdrm-2.4.125/libdrm-libdrm-2.4.125.tar.gz"
|
tar = "https://gitlab.freedesktop.org/mesa/libdrm/-/archive/libdrm-2.4.125/libdrm-libdrm-2.4.125.tar.gz"
|
||||||
blake3 = "33e6448252639f4ff8a8cd30129b335c5d85356c1c93f8d77a79221003b14f66"
|
blake3 = "33e6448252639f4ff8a8cd30129b335c5d85356c1c93f8d77a79221003b14f66"
|
||||||
patches = ["redox.patch", "../../../patches/libdrm/P1-drm-ioctl-bridge.patch", "../../../patches/libdrm/P2-drm-get-pci-info.patch"]
|
patches = ["redox.patch", "../../../local/patches/libdrm/P1-drm-ioctl-bridge.patch", "../../../local/patches/libdrm/P2-drm-get-pci-info.patch", "../../../local/patches/libdrm/P3-drm-get-version-driver-name.patch", "../../../local/patches/libdrm/P4-drmGetDeviceFromDevId-redox.patch"]
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
template = "meson"
|
template = "meson"
|
||||||
|
|||||||
@@ -0,0 +1,132 @@
|
|||||||
|
#ifndef _VIRTGPU_DRM_H_
|
||||||
|
#define _VIRTGPU_DRM_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define DRM_VIRTGPU_MAP 0x41
|
||||||
|
#define DRM_VIRTGPU_EXECBUFFER 0x42
|
||||||
|
#define DRM_VIRTGPU_GETPARAM 0x43
|
||||||
|
#define DRM_VIRTGPU_RESOURCE_CREATE 0x44
|
||||||
|
#define DRM_VIRTGPU_RESOURCE_INFO 0x45
|
||||||
|
#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x46
|
||||||
|
#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x47
|
||||||
|
#define DRM_VIRTGPU_WAIT 0x48
|
||||||
|
#define DRM_VIRTGPU_GET_CAPS 0x49
|
||||||
|
#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x4A
|
||||||
|
#define DRM_VIRTGPU_CONTEXT_INIT 0x4B
|
||||||
|
|
||||||
|
#define drm_virtgpu_resource_create drm_virtgpu_resource_create_3d
|
||||||
|
#define drm_virtgpu_3d_transfer_to_host drm_virtgpu_transfer_to_host
|
||||||
|
#define drm_virtgpu_3d_transfer_from_host drm_virtgpu_transfer_from_host
|
||||||
|
#define drm_virtgpu_3d_wait drm_virtgpu_wait_3d
|
||||||
|
#define ctx_set_params_ptr ctx_set_params
|
||||||
|
#define resource_id res_handle
|
||||||
|
|
||||||
|
struct drm_virtgpu_3d_box {
|
||||||
|
uint32_t x;
|
||||||
|
uint32_t y;
|
||||||
|
uint32_t z;
|
||||||
|
uint32_t w;
|
||||||
|
uint32_t h;
|
||||||
|
uint32_t d;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_execbuffer {
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t size;
|
||||||
|
uint64_t command;
|
||||||
|
uint64_t bo_handles;
|
||||||
|
uint32_t num_bo_handles;
|
||||||
|
int32_t fence_fd;
|
||||||
|
uint32_t ring_idx;
|
||||||
|
uint32_t syncobj_stride;
|
||||||
|
uint32_t num_in_syncobjs;
|
||||||
|
uint32_t num_out_syncobjs;
|
||||||
|
uint64_t in_syncobjs;
|
||||||
|
uint64_t out_syncobjs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_getparam {
|
||||||
|
uint64_t param;
|
||||||
|
uint64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_resource_create_3d {
|
||||||
|
uint32_t target;
|
||||||
|
uint32_t format;
|
||||||
|
uint32_t bind;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
uint32_t depth;
|
||||||
|
uint32_t array_size;
|
||||||
|
uint32_t last_level;
|
||||||
|
uint32_t nr_samples;
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t bo_handle;
|
||||||
|
uint32_t res_handle;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_resource_info {
|
||||||
|
uint32_t bo_handle;
|
||||||
|
uint32_t res_handle;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t blob_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_transfer_to_host {
|
||||||
|
uint32_t bo_handle;
|
||||||
|
struct drm_virtgpu_3d_box box;
|
||||||
|
uint32_t level;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t layer_stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_transfer_from_host {
|
||||||
|
uint32_t bo_handle;
|
||||||
|
struct drm_virtgpu_3d_box box;
|
||||||
|
uint32_t level;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t stride;
|
||||||
|
uint32_t layer_stride;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_wait_3d {
|
||||||
|
uint32_t handle;
|
||||||
|
uint32_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_get_caps {
|
||||||
|
uint32_t cap_set_id;
|
||||||
|
uint32_t cap_set_ver;
|
||||||
|
uint64_t addr;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_resource_create_blob {
|
||||||
|
uint32_t blob_mem;
|
||||||
|
uint32_t blob_flags;
|
||||||
|
uint32_t bo_handle;
|
||||||
|
uint32_t res_handle;
|
||||||
|
uint64_t size;
|
||||||
|
uint32_t pad;
|
||||||
|
uint32_t cmd_size;
|
||||||
|
uint64_t cmd;
|
||||||
|
uint64_t blob_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_context_set_param {
|
||||||
|
uint64_t param;
|
||||||
|
uint64_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_virtgpu_context_init {
|
||||||
|
uint32_t num_params;
|
||||||
|
uint32_t pad;
|
||||||
|
uint64_t ctx_set_params;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1772,6 +1772,29 @@ drm_public drmVersionPtr drmGetVersion(int fd)
|
|||||||
retval->version_major = version.major;
|
retval->version_major = version.major;
|
||||||
retval->version_minor = version.minor;
|
retval->version_minor = version.minor;
|
||||||
retval->version_patchlevel = version.patch;
|
retval->version_patchlevel = version.patch;
|
||||||
|
|
||||||
|
/* The scheme returns a NUL-terminated driver name in version.name.
|
||||||
|
* KWin drm_gpu.cpp dereferences version->name unconditionally
|
||||||
|
* (strstr checks for "i915", "amdgpu", "virtio" etc.) so it must
|
||||||
|
* never be NULL.
|
||||||
|
*/
|
||||||
|
version.name[sizeof(version.name) - 1] = '\0';
|
||||||
|
if (version.name[0] != '\0') {
|
||||||
|
size_t len = strlen(version.name);
|
||||||
|
retval->name = drmMalloc(len + 1);
|
||||||
|
if (retval->name) {
|
||||||
|
memcpy(retval->name, version.name, len + 1);
|
||||||
|
retval->name_len = len;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const char fallback[] = "redox-drm";
|
||||||
|
retval->name = drmMalloc(sizeof(fallback));
|
||||||
|
if (retval->name) {
|
||||||
|
memcpy(retval->name, fallback, sizeof(fallback));
|
||||||
|
retval->name_len = sizeof(fallback) - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
#else
|
#else
|
||||||
drmVersionPtr retval;
|
drmVersionPtr retval;
|
||||||
@@ -4070,7 +4093,7 @@ static int drmParseSubsystemType(int maj, int min)
|
|||||||
return DRM_BUS_VIRTIO;
|
return DRM_BUS_VIRTIO;
|
||||||
}
|
}
|
||||||
return subsystem_type;
|
return subsystem_type;
|
||||||
#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__)
|
#elif defined(__OpenBSD__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__redox__)
|
||||||
return DRM_BUS_PCI;
|
return DRM_BUS_PCI;
|
||||||
#else
|
#else
|
||||||
#warning "Missing implementation of drmParseSubsystemType"
|
#warning "Missing implementation of drmParseSubsystemType"
|
||||||
@@ -5097,6 +5120,66 @@ drm_public int drmGetDeviceFromDevId(dev_t find_rdev, uint32_t flags, drmDeviceP
|
|||||||
|
|
||||||
*device = d;
|
*device = d;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
#elif defined(__redox__)
|
||||||
|
/* On Redox there is no /dev/dri/ directory to enumerate.
|
||||||
|
* Instead, open /scheme/drm/card0 and query PCI info to
|
||||||
|
* construct a single drmDevice that serves as both primary
|
||||||
|
* and render node. */
|
||||||
|
drmDevicePtr devp;
|
||||||
|
char *pptr;
|
||||||
|
int max_node_length = 64, i;
|
||||||
|
size_t extra, psize;
|
||||||
|
uint8_t pbuf[22];
|
||||||
|
size_t prsize = 0;
|
||||||
|
int pret, fd;
|
||||||
|
|
||||||
|
if (device == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
if (drm_device_validate_flags(flags))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
fd = open("/scheme/drm/card0", O_RDWR | O_CLOEXEC);
|
||||||
|
if (fd < 0)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
pret = redox_drm_exchange(fd, REDOX_DRM_IOCTL_GET_PCI_INFO, NULL, 0,
|
||||||
|
pbuf, sizeof(pbuf), &prsize);
|
||||||
|
close(fd);
|
||||||
|
if (pret != 0 || prsize < 17)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
|
extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
|
||||||
|
psize = sizeof(drmDevice) + extra + sizeof(drmPciBusInfo) + sizeof(drmPciDeviceInfo);
|
||||||
|
devp = calloc(1, psize);
|
||||||
|
if (!devp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
devp->bustype = DRM_BUS_PCI;
|
||||||
|
/* Advertise both PRIMARY and RENDER — same path on Redox */
|
||||||
|
devp->available_nodes = (1 << DRM_NODE_PRIMARY) | (1 << DRM_NODE_RENDER);
|
||||||
|
pptr = (char *)devp + sizeof(drmDevice);
|
||||||
|
devp->nodes = (char **)pptr;
|
||||||
|
pptr += DRM_NODE_MAX * sizeof(void *);
|
||||||
|
for (i = 0; i < DRM_NODE_MAX; i++) { devp->nodes[i] = pptr; pptr += max_node_length; }
|
||||||
|
snprintf(devp->nodes[DRM_NODE_PRIMARY], max_node_length, "/scheme/drm/card0");
|
||||||
|
snprintf(devp->nodes[DRM_NODE_RENDER], max_node_length, "/scheme/drm/card0");
|
||||||
|
|
||||||
|
devp->businfo.pci = (drmPciBusInfoPtr)pptr;
|
||||||
|
pptr += sizeof(drmPciBusInfo);
|
||||||
|
devp->businfo.pci->domain = pbuf[10] | (pbuf[11] << 8) | (pbuf[12] << 16) | (pbuf[13] << 24);
|
||||||
|
devp->businfo.pci->bus = pbuf[14];
|
||||||
|
devp->businfo.pci->dev = pbuf[15];
|
||||||
|
devp->businfo.pci->func = pbuf[16];
|
||||||
|
|
||||||
|
devp->deviceinfo.pci = (drmPciDeviceInfoPtr)pptr;
|
||||||
|
devp->deviceinfo.pci->vendor_id = pbuf[0] | (pbuf[1] << 8);
|
||||||
|
devp->deviceinfo.pci->device_id = pbuf[2] | (pbuf[3] << 8);
|
||||||
|
devp->deviceinfo.pci->subvendor_id = pbuf[4] | (pbuf[5] << 8);
|
||||||
|
devp->deviceinfo.pci->subdevice_id = pbuf[6] | (pbuf[7] << 8);
|
||||||
|
devp->deviceinfo.pci->revision_id = pbuf[8];
|
||||||
|
|
||||||
|
*device = devp;
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
drmDevicePtr local_devices[MAX_DRM_NODES];
|
drmDevicePtr local_devices[MAX_DRM_NODES];
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ struct redox_drm_version_wire {
|
|||||||
int32_t major;
|
int32_t major;
|
||||||
int32_t minor;
|
int32_t minor;
|
||||||
int32_t patch;
|
int32_t patch;
|
||||||
|
char name[64];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct redox_drm_prime_handle_to_fd_wire {
|
struct redox_drm_prime_handle_to_fd_wire {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# PAM compatibility shim — implements the PAM API by delegating authentication
|
||||||
|
# to redbear-authd via Unix socket JSON protocol. Provides libpam.so and
|
||||||
|
# security/pam_appl.h for SDDM and other PAM-consuming software.
|
||||||
|
[source]
|
||||||
|
path = "source"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
template = "custom"
|
||||||
|
dependencies = [
|
||||||
|
"redbear-authd",
|
||||||
|
]
|
||||||
|
script = """
|
||||||
|
DYNAMIC_INIT
|
||||||
|
|
||||||
|
mkdir -p "${COOKBOOK_STAGE}/usr/lib"
|
||||||
|
mkdir -p "${COOKBOOK_STAGE}/usr/include/security"
|
||||||
|
|
||||||
|
x86_64-unknown-redox-gcc \
|
||||||
|
-shared \
|
||||||
|
-fPIC \
|
||||||
|
-std=c11 \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Wl,-soname,libpam.so.0 \
|
||||||
|
-I"${COOKBOOK_SOURCE}" \
|
||||||
|
-o "${COOKBOOK_STAGE}/usr/lib/libpam.so.0.99.0" \
|
||||||
|
"${COOKBOOK_SOURCE}/pam_redbear.c"
|
||||||
|
|
||||||
|
ln -sf libpam.so.0.99.0 "${COOKBOOK_STAGE}/usr/lib/libpam.so.0"
|
||||||
|
ln -sf libpam.so.0 "${COOKBOOK_STAGE}/usr/lib/libpam.so"
|
||||||
|
|
||||||
|
cp "${COOKBOOK_SOURCE}/security/pam_appl.h" "${COOKBOOK_STAGE}/usr/include/security/pam_appl.h"
|
||||||
|
|
||||||
|
# pkg-config for downstream cmake/find_package lookups
|
||||||
|
mkdir -p "${COOKBOOK_STAGE}/usr/lib/pkgconfig"
|
||||||
|
cat > "${COOKBOOK_STAGE}/usr/lib/pkgconfig/pam.pc" << 'EOF'
|
||||||
|
prefix=/usr
|
||||||
|
exec_prefix=${prefix}
|
||||||
|
libdir=${exec_prefix}/lib
|
||||||
|
includedir=${prefix}/include
|
||||||
|
|
||||||
|
Name: pam
|
||||||
|
Description: PAM compatibility shim (redbear-authd backend)
|
||||||
|
Version: 0.99.0
|
||||||
|
Libs: -L${libdir} -lpam
|
||||||
|
Cflags: -I${includedir}
|
||||||
|
EOF
|
||||||
|
"""
|
||||||
@@ -0,0 +1,342 @@
|
|||||||
|
#include <security/pam_appl.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#define AUTHD_SOCK_PATH "/run/redbear-authd.sock"
|
||||||
|
#define AUTHD_BUF_SIZE 4096
|
||||||
|
#define AUTHD_RESP_MAX 1024
|
||||||
|
|
||||||
|
struct pam_handle {
|
||||||
|
char *service;
|
||||||
|
char *user;
|
||||||
|
char *tty;
|
||||||
|
char *rhost;
|
||||||
|
char *ruser;
|
||||||
|
struct pam_conv conv;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int connect_authd(void)
|
||||||
|
{
|
||||||
|
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
|
if (fd < 0) return -1;
|
||||||
|
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sun_family = AF_UNIX;
|
||||||
|
strncpy(addr.sun_path, AUTHD_SOCK_PATH, sizeof(addr.sun_path) - 1);
|
||||||
|
|
||||||
|
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t send_all(int fd, const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t sent = 0;
|
||||||
|
while (sent < len) {
|
||||||
|
ssize_t n = send(fd, buf + sent, len - sent, 0);
|
||||||
|
if (n < 0) return -1;
|
||||||
|
sent += (size_t)n;
|
||||||
|
}
|
||||||
|
return (ssize_t)sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t recv_line(int fd, char *buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
size_t total = 0;
|
||||||
|
while (total < bufsize - 1) {
|
||||||
|
ssize_t n = recv(fd, buf + total, 1, 0);
|
||||||
|
if (n <= 0) return n < 0 ? -1 : (ssize_t)total;
|
||||||
|
total += (size_t)n;
|
||||||
|
if (buf[total - 1] == '\n') break;
|
||||||
|
}
|
||||||
|
buf[total] = '\0';
|
||||||
|
return (ssize_t)total;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((unused))
|
||||||
|
static char *json_extract_string(const char *json, const char *key)
|
||||||
|
{
|
||||||
|
char search[128];
|
||||||
|
snprintf(search, sizeof(search), "\"%s\":", key);
|
||||||
|
|
||||||
|
const char *pos = strstr(json, search);
|
||||||
|
if (!pos) return NULL;
|
||||||
|
|
||||||
|
pos += strlen(search);
|
||||||
|
while (*pos == ' ' || *pos == '\t') pos++;
|
||||||
|
|
||||||
|
if (*pos != '"') return NULL;
|
||||||
|
pos++;
|
||||||
|
|
||||||
|
size_t klen = strlen(key);
|
||||||
|
(void)klen;
|
||||||
|
const char *end = strchr(pos, '"');
|
||||||
|
if (!end) return NULL;
|
||||||
|
|
||||||
|
size_t vlen = (size_t)(end - pos);
|
||||||
|
char *val = malloc(vlen + 1);
|
||||||
|
if (!val) return NULL;
|
||||||
|
memcpy(val, pos, vlen);
|
||||||
|
val[vlen] = '\0';
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int json_extract_bool(const char *json, const char *key)
|
||||||
|
{
|
||||||
|
char search[128];
|
||||||
|
snprintf(search, sizeof(search), "\"%s\":", key);
|
||||||
|
|
||||||
|
const char *pos = strstr(json, search);
|
||||||
|
if (!pos) return -1;
|
||||||
|
|
||||||
|
pos += strlen(search);
|
||||||
|
while (*pos == ' ' || *pos == '\t') pos++;
|
||||||
|
|
||||||
|
if (strncmp(pos, "true", 4) == 0) return 1;
|
||||||
|
if (strncmp(pos, "false", 5) == 0) return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_start(const char *service, const char *user,
|
||||||
|
const struct pam_conv *conv, pam_handle_t **pamh)
|
||||||
|
{
|
||||||
|
if (!pamh) return PAM_SYSTEM_ERR;
|
||||||
|
|
||||||
|
pam_handle_t *h = calloc(1, sizeof(*h));
|
||||||
|
if (!h) return PAM_BUF_ERR;
|
||||||
|
|
||||||
|
if (service) {
|
||||||
|
h->service = strdup(service);
|
||||||
|
if (!h->service) { free(h); return PAM_BUF_ERR; }
|
||||||
|
}
|
||||||
|
if (user) {
|
||||||
|
h->user = strdup(user);
|
||||||
|
if (!h->user) { free(h->service); free(h); return PAM_BUF_ERR; }
|
||||||
|
}
|
||||||
|
if (conv) {
|
||||||
|
h->conv = *conv;
|
||||||
|
}
|
||||||
|
|
||||||
|
*pamh = h;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_end(pam_handle_t *pamh, int pam_status)
|
||||||
|
{
|
||||||
|
(void)pam_status;
|
||||||
|
if (!pamh) return PAM_SYSTEM_ERR;
|
||||||
|
|
||||||
|
free(pamh->service);
|
||||||
|
free(pamh->user);
|
||||||
|
free(pamh->tty);
|
||||||
|
free(pamh->rhost);
|
||||||
|
free(pamh->ruser);
|
||||||
|
free(pamh);
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
|
||||||
|
{
|
||||||
|
if (!pamh) return PAM_SYSTEM_ERR;
|
||||||
|
|
||||||
|
char **target = NULL;
|
||||||
|
switch (item_type) {
|
||||||
|
case PAM_SERVICE: target = &pamh->service; break;
|
||||||
|
case PAM_USER: target = &pamh->user; break;
|
||||||
|
case PAM_TTY: target = &pamh->tty; break;
|
||||||
|
case PAM_RHOST: target = &pamh->rhost; break;
|
||||||
|
case PAM_RUSER: target = &pamh->ruser; break;
|
||||||
|
case PAM_CONV:
|
||||||
|
if (item) pamh->conv = *(const struct pam_conv *)item;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
default:
|
||||||
|
return PAM_BAD_ITEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!target) return PAM_BAD_ITEM;
|
||||||
|
|
||||||
|
free(*target);
|
||||||
|
*target = NULL;
|
||||||
|
if (item) {
|
||||||
|
*target = strdup((const char *)item);
|
||||||
|
if (!*target) return PAM_BUF_ERR;
|
||||||
|
}
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
|
||||||
|
{
|
||||||
|
if (!pamh || !item) return PAM_SYSTEM_ERR;
|
||||||
|
|
||||||
|
switch (item_type) {
|
||||||
|
case PAM_SERVICE: *item = pamh->service; break;
|
||||||
|
case PAM_USER: *item = pamh->user; break;
|
||||||
|
case PAM_TTY: *item = pamh->tty; break;
|
||||||
|
case PAM_RHOST: *item = pamh->rhost; break;
|
||||||
|
case PAM_RUSER: *item = pamh->ruser; break;
|
||||||
|
case PAM_CONV: *item = &pamh->conv; break;
|
||||||
|
default:
|
||||||
|
*item = NULL;
|
||||||
|
return PAM_BAD_ITEM;
|
||||||
|
}
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_authenticate(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
|
if (!pamh) return PAM_SYSTEM_ERR;
|
||||||
|
if (!pamh->conv.conv) return PAM_SYSTEM_ERR;
|
||||||
|
|
||||||
|
const char *username = pamh->user;
|
||||||
|
if (!username) return PAM_AUTH_ERR;
|
||||||
|
|
||||||
|
const struct pam_message msg = {
|
||||||
|
.msg_style = PAM_PROMPT_ECHO_OFF,
|
||||||
|
.msg = "Password: "
|
||||||
|
};
|
||||||
|
const struct pam_message *msg_ptr = &msg;
|
||||||
|
struct pam_response *resp = NULL;
|
||||||
|
|
||||||
|
int rc = pamh->conv.conv(1, &msg_ptr, &resp, pamh->conv.appdata_ptr);
|
||||||
|
if (rc != PAM_SUCCESS || !resp || !resp[0].resp) return PAM_CONV_ERR;
|
||||||
|
|
||||||
|
const char *password = resp[0].resp;
|
||||||
|
|
||||||
|
int fd = connect_authd();
|
||||||
|
if (fd < 0) {
|
||||||
|
if (resp[0].resp) { memset(resp[0].resp, 0, strlen(resp[0].resp)); free(resp[0].resp); }
|
||||||
|
free(resp);
|
||||||
|
return PAM_AUTHINFO_UNAVAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char request[AUTHD_BUF_SIZE];
|
||||||
|
int n = snprintf(request, sizeof(request),
|
||||||
|
"{\"type\":\"Authenticate\",\"username\":\"%s\",\"password\":\"",
|
||||||
|
username);
|
||||||
|
|
||||||
|
for (const char *p = password; *p && (size_t)n < sizeof(request) - 4; p++) {
|
||||||
|
if (*p == '"' || *p == '\\') {
|
||||||
|
request[n++] = '\\';
|
||||||
|
if ((size_t)n >= sizeof(request) - 3) break;
|
||||||
|
}
|
||||||
|
request[n++] = *p;
|
||||||
|
}
|
||||||
|
n += snprintf(request + n, sizeof(request) - (size_t)n, "\",\"vt\":0}\n");
|
||||||
|
|
||||||
|
memset((void *)password, 0, strlen(password));
|
||||||
|
free(resp[0].resp);
|
||||||
|
free(resp);
|
||||||
|
|
||||||
|
if (send_all(fd, request, (size_t)n) < 0) {
|
||||||
|
close(fd);
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
char response[AUTHD_RESP_MAX];
|
||||||
|
ssize_t rlen = recv_line(fd, response, sizeof(response));
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (rlen <= 0) return PAM_AUTH_ERR;
|
||||||
|
|
||||||
|
int ok = json_extract_bool(response, "ok");
|
||||||
|
if (ok == 1) return PAM_SUCCESS;
|
||||||
|
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_acct_mgmt(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)flags;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_open_session(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)flags;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_close_session(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)flags;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pam_strerror(pam_handle_t *pamh, int errnum)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
switch (errnum) {
|
||||||
|
case PAM_SUCCESS: return "Success";
|
||||||
|
case PAM_OPEN_ERR: return "Failed to load module";
|
||||||
|
case PAM_SYMBOL_ERR: return "Invalid symbol";
|
||||||
|
case PAM_SERVICE_ERR: return "Error in service module";
|
||||||
|
case PAM_SYSTEM_ERR: return "System error";
|
||||||
|
case PAM_BUF_ERR: return "Memory buffer error";
|
||||||
|
case PAM_PERM_DENIED: return "Permission denied";
|
||||||
|
case PAM_AUTH_ERR: return "Authentication failure";
|
||||||
|
case PAM_CRED_INSUFFICIENT: return "Insufficient credentials";
|
||||||
|
case PAM_AUTHINFO_UNAVAIL: return "Authentication information unavailable";
|
||||||
|
case PAM_USER_UNKNOWN: return "User not known to the underlying module";
|
||||||
|
case PAM_MAXTRIES: return "Have exhausted maximum number of retries";
|
||||||
|
case PAM_NEW_AUTHTOK_REQD: return "Authentication token is no longer valid";
|
||||||
|
case PAM_ACCT_EXPIRED: return "Account expired";
|
||||||
|
case PAM_SESSION_ERR: return "Cannot make/remove an entry for the session";
|
||||||
|
case PAM_CRED_UNAVAIL: return "Authentication credentials unavailable";
|
||||||
|
case PAM_CRED_EXPIRED: return "Authentication credentials expired";
|
||||||
|
case PAM_CRED_ERR: return "Authentication credentials error";
|
||||||
|
case PAM_CONV_ERR: return "Conversation error";
|
||||||
|
case PAM_ABORT: return "Critical error - immediate abort";
|
||||||
|
default: return "Unknown PAM error";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_setcred(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)flags;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_chauthtok(pam_handle_t *pamh, int flags)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)flags;
|
||||||
|
return PAM_AUTHTOK_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pam_putenv(pam_handle_t *pamh, const char *name_value)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)name_value;
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **pam_getenvlist(pam_handle_t *pamh)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
char **envlist = malloc(sizeof(char *));
|
||||||
|
if (envlist) envlist[0] = NULL;
|
||||||
|
return envlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *pam_getenv(pam_handle_t *pamh, const char *name)
|
||||||
|
{
|
||||||
|
(void)pamh;
|
||||||
|
(void)name;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
#ifndef PAM_APPL_H
|
||||||
|
#define PAM_APPL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int pam_item_type;
|
||||||
|
|
||||||
|
#define PAM_SUCCESS 0
|
||||||
|
#define PAM_OPEN_ERR 1
|
||||||
|
#define PAM_SYMBOL_ERR 2
|
||||||
|
#define PAM_SERVICE_ERR 3
|
||||||
|
#define PAM_SYSTEM_ERR 4
|
||||||
|
#define PAM_BUF_ERR 5
|
||||||
|
#define PAM_PERM_DENIED 6
|
||||||
|
#define PAM_AUTH_ERR 7
|
||||||
|
#define PAM_CRED_INSUFFICIENT 8
|
||||||
|
#define PAM_AUTHINFO_UNAVAIL 9
|
||||||
|
#define PAM_USER_UNKNOWN 10
|
||||||
|
#define PAM_MAXTRIES 11
|
||||||
|
#define PAM_NEW_AUTHTOK_REQD 12
|
||||||
|
#define PAM_ACCT_EXPIRED 13
|
||||||
|
#define PAM_SESSION_ERR 14
|
||||||
|
#define PAM_CRED_UNAVAIL 15
|
||||||
|
#define PAM_CRED_EXPIRED 16
|
||||||
|
#define PAM_CRED_ERR 17
|
||||||
|
#define PAM_NO_MODULE_DATA 18
|
||||||
|
#define PAM_CONV_ERR 19
|
||||||
|
#define PAM_AUTHTOK_ERR 20
|
||||||
|
#define PAM_ABORT 21
|
||||||
|
#define PAM_AUTHTOK_RECOVER_ERR 22
|
||||||
|
#define PAM_AUTHTOK_LOCK_BUSY 23
|
||||||
|
#define PAM_AUTHTOK_DISABLE_AGING 24
|
||||||
|
#define PAM_TRY_AGAIN 25
|
||||||
|
#define PAM_IGNORE 26
|
||||||
|
#define PAM_MODULE_UNKNOWN 27
|
||||||
|
#define PAM_AUTHTOK_EXPIRED 28
|
||||||
|
#define PAM_BAD_ITEM 29
|
||||||
|
|
||||||
|
#define PAM_SERVICE 1
|
||||||
|
#define PAM_USER 2
|
||||||
|
#define PAM_TTY 3
|
||||||
|
#define PAM_RHOST 4
|
||||||
|
#define PAM_CONV 5
|
||||||
|
#define PAM_RUSER 8
|
||||||
|
|
||||||
|
#define PAM_SILENT 0x8000
|
||||||
|
#define PAM_DISALLOW_NULL_AUTHTOK 0x0001
|
||||||
|
#define PAM_ESTABLISH_CRED 0x0002
|
||||||
|
#define PAM_DELETE_CRED 0x0004
|
||||||
|
#define PAM_REINITIALIZE_CRED 0x0008
|
||||||
|
#define PAM_REFRESH_CRED 0x0010
|
||||||
|
#define PAM_CHANGE_EXPIRED_AUTHTOK 0x0020
|
||||||
|
|
||||||
|
#define PAM_MAX_NUM_MSG 32
|
||||||
|
|
||||||
|
#define PAM_PROMPT_ECHO_OFF 1
|
||||||
|
#define PAM_PROMPT_ECHO_ON 2
|
||||||
|
#define PAM_ERROR_MSG 3
|
||||||
|
#define PAM_TEXT_INFO 4
|
||||||
|
|
||||||
|
struct pam_message {
|
||||||
|
int msg_style;
|
||||||
|
const char *msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pam_response {
|
||||||
|
char *resp;
|
||||||
|
int resp_retcode;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pam_conv {
|
||||||
|
int (*conv)(int num_msg, const struct pam_message **msg,
|
||||||
|
struct pam_response **resp, void *appdata_ptr);
|
||||||
|
void *appdata_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct pam_handle pam_handle_t;
|
||||||
|
|
||||||
|
int pam_start(const char *service, const char *user,
|
||||||
|
const struct pam_conv *conv, pam_handle_t **pamh);
|
||||||
|
|
||||||
|
int pam_end(pam_handle_t *pamh, int pam_status);
|
||||||
|
|
||||||
|
int pam_set_item(pam_handle_t *pamh, int item_type, const void *item);
|
||||||
|
|
||||||
|
int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item);
|
||||||
|
|
||||||
|
int pam_authenticate(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
int pam_acct_mgmt(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
int pam_open_session(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
int pam_close_session(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
const char *pam_strerror(pam_handle_t *pamh, int errnum);
|
||||||
|
|
||||||
|
int pam_setcred(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
int pam_chauthtok(pam_handle_t *pamh, int flags);
|
||||||
|
|
||||||
|
int pam_putenv(pam_handle_t *pamh, const char *name_value);
|
||||||
|
|
||||||
|
char **pam_getenvlist(pam_handle_t *pamh);
|
||||||
|
|
||||||
|
const char *pam_getenv(pam_handle_t *pamh, const char *name);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -198,6 +198,54 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Q_OS_REDOX
|
||||||
|
#undef QT_USE_XOPEN_LFS_EXTENSIONS
|
||||||
|
#undef QT_LARGEFILE_SUPPORT
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// Copyright (C) 2016 The Qt Company Ltd.
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
|||||||
@@ -1375,6 +1375,48 @@ qt_internal_extend_target(Core CONDITION REDOX
|
|||||||
io/qstorageinfo_unix.cpp
|
io/qstorageinfo_unix.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_cpp_winrt
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_cpp_winrt
|
||||||
SOURCES
|
SOURCES
|
||||||
platform/windows/qfactorycacheregistration_p.h
|
platform/windows/qfactorycacheregistration_p.h
|
||||||
@@ -1578,6 +1620,48 @@ qt_internal_extend_target(Core CONDITION REDOX
|
|||||||
io/qstorageinfo_unix.cpp
|
io/qstorageinfo_unix.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# Redox: POSIX statvfs, not Linux statfs
|
||||||
|
qt_internal_extend_target(Core CONDITION REDOX
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_unix.cpp
|
||||||
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
||||||
SOURCES
|
SOURCES
|
||||||
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
||||||
|
|||||||
@@ -202,6 +202,12 @@ static_assert(std::is_signed_v<qint128>,
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <assert.h>
|
||||||
#ifndef static_assert
|
#ifndef static_assert
|
||||||
#define static_assert _Static_assert
|
#define static_assert _Static_assert
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1146,6 +1146,12 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
|
|||||||
#ifdef IPV6_HOPLIMIT
|
#ifdef IPV6_HOPLIMIT
|
||||||
#ifdef IPV6_HOPLIMIT
|
#ifdef IPV6_HOPLIMIT
|
||||||
#ifdef IPV6_HOPLIMIT
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
|
#ifdef IPV6_HOPLIMIT
|
||||||
#ifdef IPV6_HOPLIMIT
|
#ifdef IPV6_HOPLIMIT
|
||||||
if (header.hopLimit != -1) {
|
if (header.hopLimit != -1) {
|
||||||
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
msg.msg_controllen += CMSG_SPACE(sizeof(int));
|
||||||
@@ -1179,6 +1185,12 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
if (header.ifindex != 0 || !header.senderAddress.isNull()) {
|
if (header.ifindex != 0 || !header.senderAddress.isNull()) {
|
||||||
struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
|
struct in6_pktinfo *data = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));
|
||||||
|
|||||||
@@ -46,6 +46,12 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#if defined(Q_OS_VXWORKS)
|
#if defined(Q_OS_VXWORKS)
|
||||||
|
|||||||
+24
@@ -76,6 +76,12 @@ public:
|
|||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0;
|
virtual QPlatformOpenGLContext *createPlatformOpenGLContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share) const = 0;
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
@@ -102,6 +108,12 @@ public:
|
|||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
virtual bool canCreatePlatformOffscreenSurface() const { return false; }
|
virtual bool canCreatePlatformOffscreenSurface() const { return false; }
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
@@ -139,6 +151,12 @@ public:
|
|||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
|
#if QT_CONFIG(opengl)
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
virtual void *nativeResourceForContext(NativeResource /*resource*/, QPlatformOpenGLContext */*context*/) { return nullptr; }
|
virtual void *nativeResourceForContext(NativeResource /*resource*/, QPlatformOpenGLContext */*context*/) { return nullptr; }
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
@@ -166,6 +184,12 @@ public:
|
|||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
#endif /* QT_CONFIG(opengl) */
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
|
#endif /* QT_CONFIG(opengl) */
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,42 @@ impl log::Log for StderrLogger {
|
|||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wait for a scheme to become available by polling `/scheme/{name}`.
|
||||||
|
/// Returns true if the scheme appeared within the timeout, false otherwise.
|
||||||
|
///
|
||||||
|
/// In initfs mode, driver-manager starts before pcid and acpid. The PCI bus
|
||||||
|
/// scheme (`/scheme/pci`) is registered by pcid, which is spawned by hwd
|
||||||
|
/// (service 40). The ACPI bus scheme (`/scheme/acpi`) is registered by acpid
|
||||||
|
/// (service 41). Without waiting, enumeration fails with 0 devices and the
|
||||||
|
/// deferred retry loop (3 × 500ms) is too short.
|
||||||
|
fn wait_for_scheme(name: &str, timeout: Duration) -> bool {
|
||||||
|
let path = format!("/scheme/{}", name);
|
||||||
|
let start = Instant::now();
|
||||||
|
let poll_interval = Duration::from_millis(100);
|
||||||
|
|
||||||
|
while start.elapsed() < timeout {
|
||||||
|
// Use read_dir instead of Path::exists() — Redox scheme paths
|
||||||
|
// may not respond to exists()/metadata() while still being
|
||||||
|
// functional for directory enumeration.
|
||||||
|
if fs::read_dir(&path).is_ok() {
|
||||||
|
log::info!(
|
||||||
|
"scheme {} available after {}ms",
|
||||||
|
name,
|
||||||
|
start.elapsed().as_millis()
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
thread::sleep(poll_interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
log::warn!(
|
||||||
|
"scheme {} not available after {}ms",
|
||||||
|
name,
|
||||||
|
timeout.as_millis()
|
||||||
|
);
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn run_enumeration(
|
fn run_enumeration(
|
||||||
manager: &Arc<Mutex<DeviceManager>>,
|
manager: &Arc<Mutex<DeviceManager>>,
|
||||||
scheme: &DriverManagerScheme,
|
scheme: &DriverManagerScheme,
|
||||||
@@ -421,6 +457,14 @@ fn main() {
|
|||||||
|
|
||||||
reset_timeline_log();
|
reset_timeline_log();
|
||||||
|
|
||||||
|
// In initfs mode, pcid (spawned by hwd at service 40) may not have
|
||||||
|
// registered /scheme/pci yet when driver-manager starts at service 00.
|
||||||
|
// Wait for required bus schemes to appear before enumerating.
|
||||||
|
if initfs {
|
||||||
|
wait_for_scheme("pci", Duration::from_secs(30));
|
||||||
|
wait_for_scheme("acpi", Duration::from_secs(10));
|
||||||
|
}
|
||||||
|
|
||||||
if manager_config.async_probe {
|
if manager_config.async_probe {
|
||||||
let handle = thread::spawn(move || {
|
let handle = thread::spawn(move || {
|
||||||
let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), initfs);
|
let (bound, deferred) = run_enumeration(&mgr_clone, scheme_clone.as_ref(), initfs);
|
||||||
@@ -454,7 +498,7 @@ fn main() {
|
|||||||
idle_forever();
|
idle_forever();
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_retries = 3u32;
|
let max_retries = if initfs { 10u32 } else { 3u32 };
|
||||||
for retry in 1..=max_retries {
|
for retry in 1..=max_retries {
|
||||||
if SHUTDOWN_REQUESTED.load(Ordering::SeqCst) {
|
if SHUTDOWN_REQUESTED.load(Ordering::SeqCst) {
|
||||||
log::info!("driver-manager: SIGTERM received during deferred retry, shutting down");
|
log::info!("driver-manager: SIGTERM received during deferred retry, shutting down");
|
||||||
|
|||||||
@@ -212,17 +212,6 @@ fn main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let firmware_dir_str = firmware_dir.to_string_lossy().into_owned();
|
let firmware_dir_str = firmware_dir.to_string_lossy().into_owned();
|
||||||
match manifest::generate_manifest(&firmware_dir_str) {
|
|
||||||
Ok(()) => info!(
|
|
||||||
"firmware-loader: generated firmware manifest at {}/MANIFEST.txt",
|
|
||||||
firmware_dir.display()
|
|
||||||
),
|
|
||||||
Err(err) => warn!(
|
|
||||||
"firmware-loader: failed to generate firmware manifest for {}: {}",
|
|
||||||
firmware_dir.display(),
|
|
||||||
err
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
let registry = match FirmwareRegistry::new(&firmware_dir) {
|
let registry = match FirmwareRegistry::new(&firmware_dir) {
|
||||||
Ok(registry) => registry,
|
Ok(registry) => registry,
|
||||||
@@ -245,6 +234,14 @@ fn main() {
|
|||||||
firmware_dir.display()
|
firmware_dir.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Manifest generation is a host-side verification tool — skip it at runtime.
|
||||||
|
// The background thread would produce thousands of ENODEV warnings after
|
||||||
|
// setrens(0,0) makes the filesystem inaccessible, and the manifest is not
|
||||||
|
// consumed by any runtime path.
|
||||||
|
// std::thread::spawn(move || {
|
||||||
|
// let _ = manifest::generate_manifest(&firmware_dir_str);
|
||||||
|
// });
|
||||||
|
|
||||||
if args.first().map(String::as_str) == Some("--probe") {
|
if args.first().map(String::as_str) == Some("--probe") {
|
||||||
println!("count={}", registry.len());
|
println!("count={}", registry.len());
|
||||||
let mut keys = registry.list_keys();
|
let mut keys = registry.list_keys();
|
||||||
|
|||||||
@@ -25,24 +25,18 @@ tar -xf "${ARCHIVE}" -C "${EXTRACTED}" --strip-components=1
|
|||||||
mkdir -p "${COOKBOOK_STAGE}/lib/firmware"
|
mkdir -p "${COOKBOOK_STAGE}/lib/firmware"
|
||||||
mkdir -p "${COOKBOOK_STAGE}/lib/firmware/LICENSES"
|
mkdir -p "${COOKBOOK_STAGE}/lib/firmware/LICENSES"
|
||||||
|
|
||||||
# Install all firmware payloads from linux-firmware while keeping license metadata separate.
|
install -Dm0644 "${EXTRACTED}/WHENCE" "${COOKBOOK_STAGE}/lib/firmware/LICENSES/WHENCE"
|
||||||
while IFS= read -r -d '' file; do
|
for lic in "${EXTRACTED}"/LICENCE* "${EXTRACTED}"/LICENSE*; do
|
||||||
rel="${file#${EXTRACTED}/}"
|
[ -f "$lic" ] && install -Dm0644 "$lic" "${COOKBOOK_STAGE}/lib/firmware/LICENSES/$(basename "$lic")"
|
||||||
case "$(basename "$rel")" in
|
done
|
||||||
README|README.md|Makefile|check_whence.py)
|
|
||||||
continue
|
FIRMWARE_DIRS="amdgpu radeon i915 iwlwifi"
|
||||||
;;
|
for dir in ${FIRMWARE_DIRS}; do
|
||||||
LICENCE*|LICENSE*)
|
if [ -d "${EXTRACTED}/${dir}" ]; then
|
||||||
install -Dm0644 "$file" "${COOKBOOK_STAGE}/lib/firmware/LICENSES/$(basename "$rel")"
|
mkdir -p "${COOKBOOK_STAGE}/lib/firmware/${dir}"
|
||||||
continue
|
find "${EXTRACTED}/${dir}" -type f -exec install -Dm0644 {} "${COOKBOOK_STAGE}/lib/firmware/{}" \\;
|
||||||
;;
|
fi
|
||||||
WHENCE)
|
done
|
||||||
install -Dm0644 "$file" "${COOKBOOK_STAGE}/lib/firmware/LICENSES/WHENCE"
|
|
||||||
continue
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
install -Dm0644 "$file" "${COOKBOOK_STAGE}/lib/firmware/${rel}"
|
|
||||||
done < <(find "${EXTRACTED}" -type f -print0)
|
|
||||||
|
|
||||||
cat > "${COOKBOOK_STAGE}/lib/firmware/LICENSES/index.txt" <<'EOF'
|
cat > "${COOKBOOK_STAGE}/lib/firmware/LICENSES/index.txt" <<'EOF'
|
||||||
Red Bear firmware bundle
|
Red Bear firmware bundle
|
||||||
|
|||||||
@@ -30,10 +30,12 @@ fi
|
|||||||
mkdir -p "$XDG_RUNTIME_DIR"
|
mkdir -p "$XDG_RUNTIME_DIR"
|
||||||
|
|
||||||
drm_scheme_ready() {
|
drm_scheme_ready() {
|
||||||
# Try to open /scheme/drm/card0 via read (head -c 1).
|
# Check if /scheme/drm/card0 can be opened. On Redox, stat and test -e
|
||||||
# On Redox, stat and test -e are unreliable for scheme paths,
|
# are unreliable for scheme paths. Opening the scheme path with redir
|
||||||
# but opening the scheme file descriptor works.
|
# succeeds if the scheme daemon has registered the device, fails otherwise.
|
||||||
( head -c 1 "/scheme/drm/card0" ) >/dev/null 2>&1
|
# Do NOT read from it (head -c 1) — DRM scheme fds are request/response,
|
||||||
|
# not streaming, so a read would block waiting for a request response.
|
||||||
|
( exec 3<"/scheme/drm/card0" && exec 3>&- ) >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_drm_scheme() {
|
wait_for_drm_scheme() {
|
||||||
@@ -90,7 +92,8 @@ if wait_for_drm_scheme; then
|
|||||||
|
|
||||||
echo "redbear-greeter-compositor: env DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS:-unset} DBUS_SYSTEM_BUS_ADDRESS=${DBUS_SYSTEM_BUS_ADDRESS:-unset}" >&2
|
echo "redbear-greeter-compositor: env DBUS_SESSION_BUS_ADDRESS=${DBUS_SESSION_BUS_ADDRESS:-unset} DBUS_SYSTEM_BUS_ADDRESS=${DBUS_SYSTEM_BUS_ADDRESS:-unset}" >&2
|
||||||
echo "redbear-greeter-compositor: launching $COMPOSITOR" >&2
|
echo "redbear-greeter-compositor: launching $COMPOSITOR" >&2
|
||||||
QT_QPA_PLATFORM=offscreen "$COMPOSITOR"
|
unset QT_QPA_PLATFORM
|
||||||
|
"$COMPOSITOR"
|
||||||
EXIT_CODE=$?
|
EXIT_CODE=$?
|
||||||
echo "redbear-greeter-compositor: compositor exited with code $EXIT_CODE" >&2
|
echo "redbear-greeter-compositor: compositor exited with code $EXIT_CODE" >&2
|
||||||
exit $EXIT_CODE
|
exit $EXIT_CODE
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ kwin_mode="virtual"
|
|||||||
# Redox scheme paths do not respond to stat()/test -e, but opening and
|
# Redox scheme paths do not respond to stat()/test -e, but opening and
|
||||||
# reading a byte works. Use the same probe the compositor wrapper uses.
|
# reading a byte works. Use the same probe the compositor wrapper uses.
|
||||||
drm_scheme_ready() {
|
drm_scheme_ready() {
|
||||||
( head -c 1 "/scheme/drm/card0" ) >/dev/null 2>&1
|
( exec 3<"/scheme/drm/card0" && exec 3>&- ) >/dev/null 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
set_kwin_mode() {
|
set_kwin_mode() {
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# apply-patches.sh — Apply all Red Bear OS overlays on top of upstream Redox build system.
|
# apply-patches.sh — Apply all Red Bear OS overlays on top of upstream Redox build system.
|
||||||
#
|
#
|
||||||
|
# DEPRECATION NOTICE: Patches are now applied atomically by 'repo fetch' via recipe.toml.
|
||||||
|
# This script is retained for: (1) build-system git patches, (2) recipe symlinks.
|
||||||
|
# Do NOT use this for recipe source patching — that is handled by the cookbook.
|
||||||
|
#
|
||||||
# Usage: ./local/scripts/apply-patches.sh [--force] [--dry-run]
|
# Usage: ./local/scripts/apply-patches.sh [--force] [--dry-run]
|
||||||
#
|
#
|
||||||
# This script:
|
# This script:
|
||||||
|
|||||||
@@ -124,57 +124,8 @@ stash_nested_repo_if_dirty() {
|
|||||||
stash_nested_repo_if_dirty "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
stash_nested_repo_if_dirty "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
||||||
|
|
||||||
if [ "$APPLY_PATCHES" = "1" ] && [ -z "${REDBEAR_RELEASE:-}" ]; then
|
if [ "$APPLY_PATCHES" = "1" ] && [ -z "${REDBEAR_RELEASE:-}" ]; then
|
||||||
echo ">>> Applying local patches..."
|
echo ">>> Patches are applied by 'repo fetch' via recipe.toml (atomic mechanism)"
|
||||||
|
echo ">>> Skipping direct patch application (was bypassing cookbook atomicity)"
|
||||||
apply_patch_dir() {
|
|
||||||
local patch_dir="$1"
|
|
||||||
local target_dir="$2"
|
|
||||||
local label="$3"
|
|
||||||
|
|
||||||
if [ "$label" = "relibc" ] && [ -d "$target_dir/.git" ]; then
|
|
||||||
if ! git -C "$target_dir" diff --quiet || ! git -C "$target_dir" diff --cached --quiet || [ -n "$(git -C "$target_dir" ls-files --others --exclude-standard)" ]; then
|
|
||||||
echo " STASH relibc source (dirty nested checkout)"
|
|
||||||
rm -f "$target_dir/.git/index.lock"
|
|
||||||
git -C "$target_dir" stash push --all -m "build-redbear-auto-stash" > /dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
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 [ "$label" = "base" ] && [ "$patch_name" = "P0-acpid-power-methods.patch" ]; then
|
|
||||||
acpid_file="$target_dir/drivers/acpid/src/acpi.rs"
|
|
||||||
if [ -f "$acpid_file" ] && grep -q "pub fn evaluate_acpi_method(" "$acpid_file"; then
|
|
||||||
echo " SKIP $patch_name (ACPI power helper methods already present)"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
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"
|
|
||||||
|
|
||||||
stash_nested_repo_if_dirty "$PROJECT_ROOT/recipes/core/relibc/source" "relibc"
|
|
||||||
echo ""
|
echo ""
|
||||||
elif [ -n "${REDBEAR_RELEASE:-}" ]; then
|
elif [ -n "${REDBEAR_RELEASE:-}" ]; then
|
||||||
echo ">>> Release mode: skipping patch application (patches pre-applied in archived sources)"
|
echo ">>> Release mode: skipping patch application (patches pre-applied in archived sources)"
|
||||||
|
|||||||
@@ -12,6 +12,15 @@ VENDOR="amd"
|
|||||||
SUBSET="all"
|
SUBSET="all"
|
||||||
COPIED_COUNT=0
|
COPIED_COUNT=0
|
||||||
|
|
||||||
|
# Offline gate: this script downloads from the network.
|
||||||
|
# Block if REPO_OFFLINE=1 (the default during builds).
|
||||||
|
if [ "${REPO_OFFLINE:-1}" = "1" ] && [ -z "${REDBEAR_ALLOW_UPSTREAM:-}" ]; then
|
||||||
|
echo "ERROR: fetch-firmware.sh requires network access but REPO_OFFLINE=1." >&2
|
||||||
|
echo " Set REPO_OFFLINE=0 or pass REDBEAR_ALLOW_UPSTREAM=1 to override." >&2
|
||||||
|
echo " This script is manual-only — it is never called by 'make all' or 'make live'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $(basename "$0") [--vendor amd|intel] [--subset all|rdna|dmc|wifi|bluetooth]
|
Usage: $(basename "$0") [--vendor amd|intel] [--subset all|rdna|dmc|wifi|bluetooth]
|
||||||
|
|||||||
@@ -134,101 +134,39 @@ echo "Tag: $REDBEAR_TAG"
|
|||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
section "Ensuring custom recipe symlinks..."
|
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
|
# Auto-discover all local/recipes/<category>/<name>/ directories and symlink
|
||||||
mkdir -p recipes/kde
|
# into recipes/<category>/<name>. This replaces the previous 95-line manual
|
||||||
symlink "../../local/recipes/kde/plasma-desktop" "recipes/kde/plasma-desktop"
|
# symlink list which was perpetually out of sync with local/recipes/.
|
||||||
symlink "../../local/recipes/kde/plasma-workspace" "recipes/kde/plasma-workspace"
|
linked_count=0
|
||||||
symlink "../../local/recipes/kde/plasma-framework" "recipes/kde/plasma-framework"
|
skipped_count=0
|
||||||
symlink "../../local/recipes/kde/plasma-wayland-protocols" "recipes/kde/plasma-wayland-protocols"
|
|
||||||
symlink "../../local/recipes/kde/kwin" "recipes/kde/kwin"
|
while IFS= read -r -d '' recipe_dir; do
|
||||||
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kirigami"
|
rel_path="${recipe_dir#local/recipes/}"
|
||||||
|
category="${rel_path%%/*}"
|
||||||
|
name="${rel_path#*/}"
|
||||||
|
link="recipes/${category}/${name}"
|
||||||
|
|
||||||
|
# Compute relative path from link to target
|
||||||
|
# recipes/<cat>/<name> → ../../local/recipes/<cat>/<name>
|
||||||
|
target="../../local/recipes/${rel_path}"
|
||||||
|
|
||||||
|
if symlink "$target" "$link"; then
|
||||||
|
linked_count=$((linked_count + 1))
|
||||||
|
else
|
||||||
|
skipped_count=$((skipped_count + 1))
|
||||||
|
fi
|
||||||
|
done < <(find local/recipes -mindepth 2 -maxdepth 2 -type d -print0 2>/dev/null | sort -z)
|
||||||
|
|
||||||
|
# Special alias: kf6-kirigami → kirigami (KDE expects both names)
|
||||||
symlink "../../local/recipes/kde/kirigami" "recipes/kde/kf6-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"
|
# WIP compat: qt6-wayland-smoke lives under wayland/ but historically
|
||||||
symlink "../../local/recipes/kde/kf6-kcoreaddons" "recipes/kde/kf6-kcoreaddons"
|
# was also linked under recipes/wip/wayland/
|
||||||
symlink "../../local/recipes/kde/kf6-kwidgetsaddons" "recipes/kde/kf6-kwidgetsaddons"
|
mkdir -p recipes/wip/wayland
|
||||||
symlink "../../local/recipes/kde/kf6-kconfig" "recipes/kde/kf6-kconfig"
|
symlink "../../../../local/recipes/wayland/qt6-wayland-smoke" "recipes/wip/wayland/qt6-wayland-smoke"
|
||||||
symlink "../../local/recipes/kde/kf6-ki18n" "recipes/kde/kf6-ki18n"
|
|
||||||
symlink "../../local/recipes/kde/kf6-kcodecs" "recipes/kde/kf6-kcodecs"
|
status "Custom recipe symlinks ready (${linked_count} linked, ${skipped_count} skipped)"
|
||||||
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 ""
|
echo ""
|
||||||
|
|
||||||
section "Ensuring recipe patch symlinks..."
|
section "Ensuring recipe patch symlinks..."
|
||||||
|
|||||||
Executable
+54
@@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# qemu-ram.sh — Boot Red Bear OS from RAM-disk (tmpfs)
|
||||||
|
#
|
||||||
|
# Copies the disk image into tmpfs before launching QEMU, eliminating
|
||||||
|
# all host disk I/O during OS runtime.
|
||||||
|
#
|
||||||
|
# Usage: invoked by `make qemu-ram` — not intended for direct use.
|
||||||
|
#
|
||||||
|
# Arguments:
|
||||||
|
# $1 QEMU binary (e.g. qemu-system-x86_64)
|
||||||
|
# $2 Disk image path (harddrive.img or live ISO)
|
||||||
|
# $3 QEMU flags (space-separated)
|
||||||
|
# $4 RAM directory (tmpfs mount point)
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
QEMU_BIN="${1:?Usage: qemu-ram.sh <qemu-bin> <disk> <flags> <ramdir>}"
|
||||||
|
DISK="${2:?disk image path required}"
|
||||||
|
QEMU_FLAGS="${3:?QEMU flags required}"
|
||||||
|
RAMDIR="${4:?RAM directory required}"
|
||||||
|
|
||||||
|
if [ ! -f "$DISK" ]; then
|
||||||
|
echo "ERROR: disk image not found: $DISK" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
echo "Red Bear: cleaning up RAM-disk..."
|
||||||
|
if mountpoint -q "$RAMDIR" 2>/dev/null; then
|
||||||
|
umount "$RAMDIR" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
rmdir "$RAMDIR" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
# Size the tmpfs: image size + 512 MiB overhead, minimum 1 GiB
|
||||||
|
img_mb=$(du -m "$DISK" | cut -f1)
|
||||||
|
tmpfs_mb=$((img_mb + 512))
|
||||||
|
[ "$tmpfs_mb" -lt 1024 ] && tmpfs_mb=1024
|
||||||
|
|
||||||
|
echo "Red Bear: preparing RAM-disk boot..."
|
||||||
|
mkdir -p "$RAMDIR"
|
||||||
|
|
||||||
|
if ! mountpoint -q "$RAMDIR" 2>/dev/null; then
|
||||||
|
mount -t tmpfs -o "size=${tmpfs_mb}m" tmpfs "$RAMDIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Red Bear: copying $DISK to RAM ($(du -h "$DISK" | cut -f1))..."
|
||||||
|
cp "$DISK" "$RAMDIR/disk.img"
|
||||||
|
|
||||||
|
ram_flags="${QEMU_FLAGS//$DISK/$RAMDIR/disk.img}"
|
||||||
|
|
||||||
|
echo "Red Bear: booting from RAM-disk..."
|
||||||
|
exec "$QEMU_BIN" $ram_flags
|
||||||
@@ -70,7 +70,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ usage() {
|
|||||||
Usage: test-msix-qemu.sh [config]
|
Usage: test-msix-qemu.sh [config]
|
||||||
|
|
||||||
Boot a Red Bear image in QEMU and verify a live MSI-X path via virtio-net.
|
Boot a Red Bear image in QEMU and verify a live MSI-X path via virtio-net.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ done
|
|||||||
|
|
||||||
config="${1:-redbear-mini}"
|
config="${1:-redbear-mini}"
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
arch="${ARCH:-$(uname -m)}"
|
arch="${ARCH:-$(uname -m)}"
|
||||||
image="build/$arch/$config/harddrive.img"
|
image="build/$arch/$config/harddrive.img"
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ usage() {
|
|||||||
cat <<'USAGE'
|
cat <<'USAGE'
|
||||||
Usage:
|
Usage:
|
||||||
./local/scripts/test-phase3-runtime-substrate.sh --guest
|
./local/scripts/test-phase3-runtime-substrate.sh --guest
|
||||||
./local/scripts/test-phase3-runtime-substrate.sh --qemu [redbear-desktop]
|
./local/scripts/test-phase3-runtime-substrate.sh --qemu [redbear-full]
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ case "${1:-}" in
|
|||||||
run_guest_checks
|
run_guest_checks
|
||||||
;;
|
;;
|
||||||
--qemu)
|
--qemu)
|
||||||
run_qemu_checks "${2:-redbear-desktop}"
|
run_qemu_checks "${2:-redbear-full}"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
usage
|
usage
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ usage() {
|
|||||||
Usage: test-ps2-qemu.sh [--check] [config] [extra qemu args...]
|
Usage: test-ps2-qemu.sh [--check] [config] [extra qemu args...]
|
||||||
|
|
||||||
Launch or validate the PS/2 + serio path on a Red Bear image in QEMU.
|
Launch or validate the PS/2 + serio path on a Red Bear image in QEMU.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ usage() {
|
|||||||
Usage: test-timer-qemu.sh [--check] [config] [extra qemu args...]
|
Usage: test-timer-qemu.sh [--check] [config] [extra qemu args...]
|
||||||
|
|
||||||
Launch or validate the startup timer path on a Red Bear image in QEMU.
|
Launch or validate the startup timer path on a Red Bear image in QEMU.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ usage() {
|
|||||||
Usage: test-usb-maturity-qemu.sh [config]
|
Usage: test-usb-maturity-qemu.sh [config]
|
||||||
|
|
||||||
Run the bounded USB maturity proof helpers in sequence.
|
Run the bounded USB maturity proof helpers in sequence.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
|
|
||||||
Checks run:
|
Checks run:
|
||||||
- xHCI interrupt mode
|
- xHCI interrupt mode
|
||||||
@@ -32,7 +32,7 @@ done
|
|||||||
config="${1:-redbear-mini}"
|
config="${1:-redbear-mini}"
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ">>> Running xHCI interrupt proof"
|
echo ">>> Running xHCI interrupt proof"
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ usage() {
|
|||||||
Usage: test-usb-qemu.sh [--check] [config]
|
Usage: test-usb-qemu.sh [--check] [config]
|
||||||
|
|
||||||
Boot or validate the full USB stack on a Red Bear image in QEMU.
|
Boot or validate the full USB stack on a Red Bear image in QEMU.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
|
|
||||||
Checks performed:
|
Checks performed:
|
||||||
1. xHCI controller initializes and reports interrupt mode
|
1. xHCI controller initializes and reports interrupt mode
|
||||||
@@ -80,7 +80,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ usage() {
|
|||||||
Usage: test-usb-storage-qemu.sh [config]
|
Usage: test-usb-storage-qemu.sh [config]
|
||||||
|
|
||||||
Boot a Red Bear image with a USB storage device attached and verify usbscsid autospawn.
|
Boot a Red Bear image with a USB storage device attached and verify usbscsid autospawn.
|
||||||
Defaults to redbear-desktop.
|
Defaults to redbear-full.
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ for arg in "$@"; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
config="${1:-redbear-desktop}"
|
config="${1:-redbear-full}"
|
||||||
arch="${ARCH:-$(uname -m)}"
|
arch="${ARCH:-$(uname -m)}"
|
||||||
image="build/$arch/$config/harddrive.img"
|
image="build/$arch/$config/harddrive.img"
|
||||||
extra="build/$arch/$config/extra.img"
|
extra="build/$arch/$config/extra.img"
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ Usage: test-vm-network-qemu.sh [config] [extra qemu args...]
|
|||||||
Launch Red Bear OS in QEMU with the VirtIO network baseline enabled.
|
Launch Red Bear OS in QEMU with the VirtIO network baseline enabled.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
config Optional config name (default: redbear-minimal)
|
config Optional config name (default: redbear-mini)
|
||||||
extra qemu args Additional arguments appended to QEMUFLAGS
|
extra qemu args Additional arguments appended to QEMUFLAGS
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
./local/scripts/test-vm-network-qemu.sh
|
./local/scripts/test-vm-network-qemu.sh
|
||||||
./local/scripts/test-vm-network-qemu.sh redbear-minimal -m 4G
|
./local/scripts/test-vm-network-qemu.sh redbear-mini -m 4G
|
||||||
QEMUFLAGS="-display sdl" ./local/scripts/test-vm-network-qemu.sh redbear-desktop
|
QEMUFLAGS="-display sdl" ./local/scripts/test-vm-network-qemu.sh redbear-full
|
||||||
|
|
||||||
In-guest validation commands:
|
In-guest validation commands:
|
||||||
redbear-info --verbose
|
redbear-info --verbose
|
||||||
@@ -58,14 +58,14 @@ for arg in "$@"; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
CONFIG="redbear-minimal"
|
CONFIG="redbear-mini"
|
||||||
if [[ $# -gt 0 ]] && [[ "$1" == redbear-* ]]; then
|
if [[ $# -gt 0 ]] && [[ "$1" == redbear-* ]]; then
|
||||||
CONFIG="$1"
|
CONFIG="$1"
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$CONFIG" in
|
case "$CONFIG" in
|
||||||
redbear-minimal|redbear-desktop|redbear-full|redbear-kde|redbear-live)
|
redbear-mini|redbear-full|redbear-grub)
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ERROR: unsupported config '$CONFIG'" >&2
|
echo "ERROR: unsupported config '$CONFIG'" >&2
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ usage() {
|
|||||||
Usage: test-xhci-device-lifecycle-qemu.sh [--check] [config]
|
Usage: test-xhci-device-lifecycle-qemu.sh [--check] [config]
|
||||||
|
|
||||||
Boot a Red Bear image and exercise bounded xHCI attach/detach behavior via
|
Boot a Red Bear image and exercise bounded xHCI attach/detach behavior via
|
||||||
QEMU monitor hotplug events. Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
QEMU monitor hotplug events. Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ usage() {
|
|||||||
Usage: test-xhci-irq-qemu.sh [--check] [config]
|
Usage: test-xhci-irq-qemu.sh [--check] [config]
|
||||||
|
|
||||||
Boot or validate xHCI interrupt-mode bring-up on a Red Bear image in QEMU.
|
Boot or validate xHCI interrupt-mode bring-up on a Red Bear image in QEMU.
|
||||||
Defaults to redbear-mini (mapped to the in-tree redbear-minimal image).
|
Defaults to redbear-mini (mapped to the in-tree redbear-mini image).
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ for arg in "$@"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [[ "$config" == "redbear-mini" ]]; then
|
if [[ "$config" == "redbear-mini" ]]; then
|
||||||
config="redbear-minimal"
|
config="redbear-mini"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
firmware="$(find_uefi_firmware)" || {
|
firmware="$(find_uefi_firmware)" || {
|
||||||
|
|||||||
@@ -36,18 +36,18 @@ require_pattern() {
|
|||||||
printf '=== Red Bear OS VM Network Baseline Validation ===\n'
|
printf '=== Red Bear OS VM Network Baseline Validation ===\n'
|
||||||
printf 'Root: %s\n\n' "$ROOT"
|
printf 'Root: %s\n\n' "$ROOT"
|
||||||
|
|
||||||
require_file "config/redbear-minimal.toml"
|
require_file "config/redbear-mini.toml"
|
||||||
require_file "config/redbear-netctl.toml"
|
require_file "config/redbear-netctl.toml"
|
||||||
require_file "recipes/core/base/source/init.d/00_pcid-spawner.service"
|
require_file "recipes/core/base/source/init.d/00_pcid-spawner.service"
|
||||||
require_file "recipes/core/base/source/init.d/10_smolnetd.service"
|
require_file "recipes/core/base/source/init.d/10_smolnetd.service"
|
||||||
require_file "recipes/core/base/source/init.d/10_dhcpd.service"
|
require_file "recipes/core/base/source/init.d/10_dhcpd.service"
|
||||||
require_file "recipes/core/base/recipe.toml"
|
require_file "recipes/core/base/recipe.toml"
|
||||||
|
|
||||||
require_pattern "config/redbear-minimal.toml" 'path = "/etc/netctl/active"' \
|
require_pattern "config/redbear-mini.toml" 'path = "/etc/netctl/active"' \
|
||||||
'redbear-minimal must install /etc/netctl/active'
|
'redbear-mini must install /etc/netctl/active'
|
||||||
require_pattern "config/redbear-minimal.toml" 'data = "wired-dhcp\\n"' \
|
require_pattern "config/redbear-mini.toml" 'data = "wired-dhcp\\n"' \
|
||||||
'redbear-minimal must enable wired-dhcp by default'
|
'redbear-mini must enable wired-dhcp by default'
|
||||||
pass 'redbear-minimal enables the wired-dhcp profile by default'
|
pass 'redbear-mini enables the wired-dhcp profile by default'
|
||||||
|
|
||||||
require_pattern "config/redbear-netctl.toml" 'path = "/usr/lib/init.d/12_netctl.service"' \
|
require_pattern "config/redbear-netctl.toml" 'path = "/usr/lib/init.d/12_netctl.service"' \
|
||||||
'redbear-netctl config must install the boot service'
|
'redbear-netctl config must install the boot service'
|
||||||
|
|||||||
@@ -163,15 +163,15 @@ fi
|
|||||||
log "==> Checking config/redbear-*.toml files..."
|
log "==> Checking config/redbear-*.toml files..."
|
||||||
CRITICAL_CONFIGS=(
|
CRITICAL_CONFIGS=(
|
||||||
"config/redbear-full.toml"
|
"config/redbear-full.toml"
|
||||||
"config/redbear-live-full.toml"
|
"config/redbear-mini.toml"
|
||||||
"config/redbear-minimal.toml"
|
"config/redbear-grub.toml"
|
||||||
"config/redbear-live-minimal.toml"
|
"config/redbear-grub-policy.toml"
|
||||||
"config/redbear-desktop.toml"
|
|
||||||
"config/redbear-device-services.toml"
|
"config/redbear-device-services.toml"
|
||||||
"config/redbear-legacy-base.toml"
|
"config/redbear-legacy-base.toml"
|
||||||
"config/redbear-legacy-desktop.toml"
|
"config/redbear-legacy-desktop.toml"
|
||||||
"config/redbear-netctl.toml"
|
"config/redbear-netctl.toml"
|
||||||
"config/redbear-greeter-services.toml"
|
"config/redbear-greeter-services.toml"
|
||||||
|
"config/redbear-boot-stages.toml"
|
||||||
)
|
)
|
||||||
|
|
||||||
MISSING_CONFIGS=0
|
MISSING_CONFIGS=0
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ else
|
|||||||
mv $@.partial $@
|
mv $@.partial $@
|
||||||
cp redbear.ipxe $(LIVE_IPXE)
|
cp redbear.ipxe $(LIVE_IPXE)
|
||||||
endif
|
endif
|
||||||
|
@echo "NOTE: $(LIVE_ISO) is a raw disk image with iPXE boot, not an ISO9660 image."
|
||||||
|
@echo " Use 'make live' for the full live image with bootloader embedded."
|
||||||
|
|
||||||
$(BUILD)/filesystem.img: $(FSTOOLS) $(REPO_TAG)
|
$(BUILD)/filesystem.img: $(FSTOOLS) $(REPO_TAG)
|
||||||
ifeq ($(FSTOOLS_IN_PODMAN),1)
|
ifeq ($(FSTOOLS_IN_PODMAN),1)
|
||||||
@@ -115,4 +117,5 @@ validate-init: $(BUILD)/harddrive.img
|
|||||||
|
|
||||||
validate: lint-config validate-init
|
validate: lint-config validate-init
|
||||||
@scripts/validate-file-ownership.sh
|
@scripts/validate-file-ownership.sh
|
||||||
|
@scripts/validate-collision-log.sh $(BUILD)
|
||||||
@echo "\033[1;36;49mBuild validation passed\033[0m"
|
@echo "\033[1;36;49mBuild validation passed\033[0m"
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user