fix: m4 builds successfully - complete gnulib cross-compilation recipe
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.
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
|
||||
_ _
|
||||
| | (_)
|
||||
| | ___ _ ___ _ __ _ _ ___
|
||||
| |/ / || |/ _ \ | '_ \| | | / __|
|
||||
| < | || | (_) || |_) | |_| \__ \
|
||||
|_|\_\|_|/ |\___/ | .__/ \__,_|___/
|
||||
|__/ | |
|
||||
|_|
|
||||
____ _ ____ ___ ____
|
||||
| _ \ ___ __| | __ ) ___ __ _ _ __ / _ \/ ___|
|
||||
| |_) / _ \/ _` | _ \ / _ \/ _` | '__| | | | \___ \
|
||||
| _ < __/ (_| | |_) | __/ (_| | | | |_| |___) |
|
||||
|_| \_\___|\__,_|____/ \___|\__,_|_| \___/|____/
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<T> = std::result::Result<T, DriverError>;
|
||||
@@ -145,6 +146,10 @@ pub trait GpuDriver: Send + Sync {
|
||||
fn page_flip(&self, crtc_id: u32, fb_handle: u32, flags: u32) -> Result<u64>;
|
||||
fn get_vblank(&self, crtc_id: u32) -> Result<u64>;
|
||||
|
||||
fn atomic_commit(&self, _state: &AtomicState) -> Result<AtomicCommitResult> {
|
||||
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"))
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<ModeInfo>,
|
||||
pub fb_handle: u32,
|
||||
pub x: u32,
|
||||
pub y: u32,
|
||||
pub connectors: Vec<u32>,
|
||||
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<CrtcState>,
|
||||
pub connector_states: Vec<ConnectorState>,
|
||||
pub test_only: bool,
|
||||
pub non_blocking: bool,
|
||||
pub event_fd: Option<i32>,
|
||||
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,
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod atomic;
|
||||
pub mod connector;
|
||||
pub mod crtc;
|
||||
pub mod encoder;
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user