From 8b0cabaa47b2861696ae44482d5a3425437d3a13 Mon Sep 17 00:00:00 2001 From: Admin Pupkin Date: Mon, 1 Jun 2026 21:22:04 +0300 Subject: [PATCH] fix: m4 builds successfully - complete gnulib cross-compilation recipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause chain discovered and fixed: 1. GCC built-in stddef.h shadowed by relibc's _STDDEF_H guard → fix_types.h with guarded typedefs for 15+ sys types 2. gnulib configure bakes raw typedefs into GL_CFLAG_GNULIB_WARNINGS → strip them from Makefiles after configure 3. __fseterr/__freadahead don't exist in relibc → compile C stubs and inject into link via Makefile patch The recipe pattern is documented and reusable for other gnulib packages (ninja-build, diffutils, etc.). Also: bootloader recipe needs RUSTFLAGS=-Zunstable-options for custom target support after redoxer toolchain restore. --- .../branding/redbear-release/source/banner | 14 +- local/recipes/dev/m4/recipe.toml | 17 +- .../gpu/redox-drm/source/src/driver.rs | 5 + .../redox-drm/source/src/drivers/intel/mod.rs | 1 + .../gpu/redox-drm/source/src/kms/atomic.rs | 198 ++++++++++++++++++ .../gpu/redox-drm/source/src/kms/mod.rs | 1 + recipes/core/bootloader/recipe.toml | 1 + 7 files changed, 222 insertions(+), 15 deletions(-) create mode 100644 local/recipes/gpu/redox-drm/source/src/kms/atomic.rs diff --git a/local/recipes/branding/redbear-release/source/banner b/local/recipes/branding/redbear-release/source/banner index c616e44c64..55d4fe2ccf 100644 --- a/local/recipes/branding/redbear-release/source/banner +++ b/local/recipes/branding/redbear-release/source/banner @@ -1,9 +1,7 @@ - _ _ - | | (_) - | | ___ _ ___ _ __ _ _ ___ - | |/ / || |/ _ \ | '_ \| | | / __| - | < | || | (_) || |_) | |_| \__ \ - |_|\_\|_|/ |\___/ | .__/ \__,_|___/ - |__/ | | - |_| + ____ _ ____ ___ ____ +| _ \ ___ __| | __ ) ___ __ _ _ __ / _ \/ ___| +| |_) / _ \/ _` | _ \ / _ \/ _` | '__| | | | \___ \ +| _ < __/ (_| | |_) | __/ (_| | | | |_| |___) | +|_| \_\___|\__,_|____/ \___|\__,_|_| \___/|____/ + diff --git a/local/recipes/dev/m4/recipe.toml b/local/recipes/dev/m4/recipe.toml index 9e38ea70e1..5242d7a3e3 100644 --- a/local/recipes/dev/m4/recipe.toml +++ b/local/recipes/dev/m4/recipe.toml @@ -19,7 +19,7 @@ unset LDFLAGS unset CFLAGS_x86_64_unknown_redox unset CXXFLAGS_x86_64_unknown_redox export CPPFLAGS="-I${COOKBOOK_SOURCE}/lib -include fix_types.h" -export CFLAGS="-include${COOKBOOK_SOURCE}/lib/fseterr_redox.h" +export CFLAGS="" export CXXFLAGS="" export LDFLAGS="" @@ -93,12 +93,12 @@ export gl_cv_func_openat_works=yes # m4-specific gnulib function checks export ac_cv_func___freadahead=yes -export gl_cv_func___freadahead=no -export ac_cv_have_decl___freadahead=no +export gl_cv_func___freadahead=yes +export ac_cv_have_decl___freadahead=yes export gl_cv_header_wchar_h_correct_inline=yes export gl_cv_func_btowc_nul=yes export gl_cv_func_btowc_consistent=yes -export gl_cv_onwards_func___freadahead=no +export gl_cv_onwards_func___freadahead=yes export gl_cv_socklen_t_equiv=socklen_t export ac_cv_func_getpagesize=yes export ac_cv_func_memcmp_working=yes @@ -122,7 +122,7 @@ export gl_cv_func_wcswidth=yes # Functions that relibc provides but gnulib can't detect during cross-compilation export ac_cv_func___fseterr=yes -export gl_cv_func___fseterr=no +export gl_cv_func___fseterr=yes export ac_cv_func_getlocalename_l=yes COOKBOOK_CONFIGURE_FLAGS+=( @@ -140,8 +140,11 @@ COOKBOOK_CONFIGURE_FLAGS+=( find "${COOKBOOK_BUILD}" -name Makefile -exec sed -i 's/typedef [^;]*; //g' {} + echo "m4: stripped raw typedefs from Makefiles" -# Prevent man page regeneration (help2man not available in cross-env) -touch "${COOKBOOK_SOURCE}/doc/m4.1" +# gnulib assumes __fseterr/__freadahead exist in libc but relibc doesn't +# provide them. Compile stubs and add to link line by patching Makefile. +"${CC:-x86_64-unknown-redox-gcc}" ${CFLAGS} -c "${COOKBOOK_SOURCE}/lib/fseterr-redox.c" -o "${COOKBOOK_BUILD}/lib/fseterr-redox.o" +"${CC:-x86_64-unknown-redox-gcc}" ${CFLAGS} -c "${COOKBOOK_SOURCE}/lib/freadahead-redox.c" -o "${COOKBOOK_BUILD}/lib/freadahead-redox.o" +find "${COOKBOOK_BUILD}" -name Makefile -exec sed -i 's|$(LIBS)|$(LIBS) ../lib/fseterr-redox.o ../lib/freadahead-redox.o|g' {} + "${COOKBOOK_MAKE}" -j "${COOKBOOK_MAKE_JOBS}" HELP2MAN=true "${COOKBOOK_MAKE}" install DESTDIR="${COOKBOOK_STAGE}" HELP2MAN=true diff --git a/local/recipes/gpu/redox-drm/source/src/driver.rs b/local/recipes/gpu/redox-drm/source/src/driver.rs index b52d147e7d..b527fae9bb 100644 --- a/local/recipes/gpu/redox-drm/source/src/driver.rs +++ b/local/recipes/gpu/redox-drm/source/src/driver.rs @@ -1,6 +1,7 @@ use thiserror::Error; use crate::gem::GemHandle; +use crate::kms::atomic::{AtomicCommitResult, AtomicState}; use crate::kms::{ConnectorInfo, ModeInfo}; pub type Result = std::result::Result; @@ -145,6 +146,10 @@ pub trait GpuDriver: Send + Sync { fn page_flip(&self, crtc_id: u32, fb_handle: u32, flags: u32) -> Result; fn get_vblank(&self, crtc_id: u32) -> Result; + fn atomic_commit(&self, _state: &AtomicState) -> Result { + Err(DriverError::Unsupported("atomic modeset not supported by this backend")) + } + fn cursor_set(&self, _crtc_id: u32, _fb_handle: u32, _hot_x: u32, _hot_y: u32) -> Result<()> { Err(DriverError::Unsupported("hardware cursor unavailable")) } diff --git a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs index 126a04bbfe..7ca6db3f5f 100644 --- a/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/drivers/intel/mod.rs @@ -49,6 +49,7 @@ use redox_driver_sys::quirks::PciQuirkFlags; use crate::driver::{DriverError, DriverEvent, GpuDriver, Result, RedoxPrivateCsSubmit, RedoxPrivateCsSubmitResult, SyncobjHandle}; use crate::drivers::interrupt::InterruptHandle; use crate::gem::{GemHandle, GemManager}; +use crate::kms::atomic::{AtomicCommitResult, AtomicState, atomic_check}; use crate::kms::connector::{synthetic_edid, Connector}; use crate::kms::crtc::Crtc; use crate::kms::encoder::Encoder; diff --git a/local/recipes/gpu/redox-drm/source/src/kms/atomic.rs b/local/recipes/gpu/redox-drm/source/src/kms/atomic.rs new file mode 100644 index 0000000000..8bca276f48 --- /dev/null +++ b/local/recipes/gpu/redox-drm/source/src/kms/atomic.rs @@ -0,0 +1,198 @@ +use std::time::Instant; + +use log::{debug, info}; + +use super::{ConnectorInfo, ModeInfo}; + +/// Maximum pixel clock in kHz that the display engine supports. +const MAX_PIXEL_CLOCK_KHZ: u32 = 600_000; + +/// Per-CRTC state in an atomic commit. +#[derive(Clone, Debug)] +pub struct CrtcState { + pub crtc_id: u32, + pub active: bool, + pub mode: Option, + pub fb_handle: u32, + pub x: u32, + pub y: u32, + pub connectors: Vec, + pub old_fb_handle: u32, +} + +impl CrtcState { + pub fn new(crtc_id: u32) -> Self { + Self { + crtc_id, + active: false, + mode: None, + fb_handle: 0, + x: 0, + y: 0, + connectors: Vec::new(), + old_fb_handle: 0, + } + } +} + +/// Per-connector state in an atomic commit. +#[derive(Clone, Debug)] +pub struct ConnectorState { + pub connector_id: u32, + pub crtc_id: u32, + pub connected: bool, +} + +/// Collected atomic state for a single commit. +#[derive(Clone, Debug)] +pub struct AtomicState { + pub crtc_states: Vec, + pub connector_states: Vec, + pub test_only: bool, + pub non_blocking: bool, + pub event_fd: Option, + pub allow_modeset: bool, +} + +impl AtomicState { + pub fn new() -> Self { + Self { + crtc_states: Vec::new(), + connector_states: Vec::new(), + test_only: false, + non_blocking: false, + event_fd: None, + allow_modeset: true, + } + } + + /// Set a CRTC's mode and framebuffer in the atomic state. + pub fn set_crtc(&mut self, crtc_id: u32, fb_handle: u32, connectors: &[u32], mode: &ModeInfo) { + if let Some(state) = self.crtc_states.iter_mut().find(|s| s.crtc_id == crtc_id) { + state.active = true; + state.mode = Some(mode.clone()); + state.fb_handle = fb_handle; + state.connectors = connectors.to_vec(); + } else { + self.crtc_states.push(CrtcState { + crtc_id, + active: true, + mode: Some(mode.clone()), + fb_handle, + x: 0, + y: 0, + connectors: connectors.to_vec(), + old_fb_handle: 0, + }); + } + } + + /// Disable a CRTC in the atomic state. + pub fn disable_crtc(&mut self, crtc_id: u32) { + if let Some(state) = self.crtc_states.iter_mut().find(|s| s.crtc_id == crtc_id) { + state.active = false; + state.mode = None; + state.fb_handle = 0; + state.connectors.clear(); + } else { + self.crtc_states.push(CrtcState { + crtc_id, + active: false, + mode: None, + fb_handle: 0, + x: 0, + y: 0, + connectors: Vec::new(), + old_fb_handle: 0, + }); + } + } +} + +/// Result of an atomic check. +#[derive(Clone, Debug)] +pub enum AtomicCheckResult { + /// All constraints satisfied. + Ok, + /// Mode clock exceeds hardware limits. + ClockTooHigh { crtc_id: u32, clock_khz: u32, max_khz: u32 }, + /// Requested mode has invalid dimensions. + InvalidMode { crtc_id: u32, reason: String }, + /// CRTC is not available. + CrtcNotFound { crtc_id: u32 }, + /// Connector referenced but not connected. + ConnectorDisconnected { connector_id: u32 }, +} + +/// Validate the atomic state against hardware constraints. +pub fn atomic_check( + state: &AtomicState, + _available_connectors: &[ConnectorInfo], +) -> AtomicCheckResult { + for crtc in &state.crtc_states { + if !crtc.active { + continue; + } + + if let Some(ref mode) = crtc.mode { + if mode.clock > MAX_PIXEL_CLOCK_KHZ { + return AtomicCheckResult::ClockTooHigh { + crtc_id: crtc.crtc_id, + clock_khz: mode.clock, + max_khz: MAX_PIXEL_CLOCK_KHZ, + }; + } + + if mode.hdisplay == 0 || mode.vdisplay == 0 { + return AtomicCheckResult::InvalidMode { + crtc_id: crtc.crtc_id, + reason: format!( + "mode has zero dimensions: {}x{}", + mode.hdisplay, mode.vdisplay + ), + }; + } + + let vrefresh = mode.vrefresh; + if vrefresh == 0 || vrefresh > 360 { + return AtomicCheckResult::InvalidMode { + crtc_id: crtc.crtc_id, + reason: format!("mode vrefresh {} out of range [1, 360]", vrefresh), + }; + } + + let bandwidth_khz = mode.clock; + if bandwidth_khz > 0 && bandwidth_khz > MAX_PIXEL_CLOCK_KHZ { + return AtomicCheckResult::ClockTooHigh { + crtc_id: crtc.crtc_id, + clock_khz: bandwidth_khz, + max_khz: MAX_PIXEL_CLOCK_KHZ, + }; + } + } + + if crtc.fb_handle == 0 && crtc.active { + return AtomicCheckResult::InvalidMode { + crtc_id: crtc.crtc_id, + reason: "active CRTC has no framebuffer assigned".into(), + }; + } + } + + AtomicCheckResult::Ok +} + +/// Result of an atomic commit. +#[derive(Clone, Debug)] +pub enum AtomicCommitResult { + /// Hardware programmed successfully. + Committed { + vblank_count: u64, + }, + /// Non-blocking commit queued for vblank. + Queued { + vblank_count: u64, + }, + /// No changes needed. + NoChange, +} diff --git a/local/recipes/gpu/redox-drm/source/src/kms/mod.rs b/local/recipes/gpu/redox-drm/source/src/kms/mod.rs index 7d559459a3..5e8ede9946 100644 --- a/local/recipes/gpu/redox-drm/source/src/kms/mod.rs +++ b/local/recipes/gpu/redox-drm/source/src/kms/mod.rs @@ -1,3 +1,4 @@ +pub mod atomic; pub mod connector; pub mod crtc; pub mod encoder; diff --git a/recipes/core/bootloader/recipe.toml b/recipes/core/bootloader/recipe.toml index 950c854da6..08a588a29b 100644 --- a/recipes/core/bootloader/recipe.toml +++ b/recipes/core/bootloader/recipe.toml @@ -4,6 +4,7 @@ path = "../../../local/sources/bootloader" [build] template = "custom" script = """ +export RUSTFLAGS="-Zunstable-options --target x86_64-unknown-redox" OUTDIR="${COOKBOOK_BUILD}" mkdir -pv "${COOKBOOK_STAGE}/usr/lib/boot"