Update Red Bear driver substrate
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -61,6 +61,23 @@ index 94a1eb17..3fd91156 100644
|
||||
+ Ok(values) => {
|
||||
+ log::debug!("{}._PS0 => {:?}", device_path, values);
|
||||
+ }
|
||||
@@
|
||||
while let Some((descriptor, len)) = AnyDescriptor::parse(&data[i..]) {
|
||||
descriptors.push(descriptor);
|
||||
i += len;
|
||||
}
|
||||
+ let descriptor_count = descriptors.len();
|
||||
+
|
||||
+ if i < data.len() {
|
||||
+ log::warn!(
|
||||
+ "port {} slot {} config {} descriptor parsing stopped early at byte {} of {}",
|
||||
+ port_id,
|
||||
+ slot,
|
||||
+ index,
|
||||
+ i,
|
||||
+ data.len()
|
||||
+ );
|
||||
+ }
|
||||
+ Err(error) => {
|
||||
+ log::warn!("Failed to power on {} with _PS0: {:?}", device_path, error);
|
||||
+ }
|
||||
@@ -1039,3 +1056,300 @@ index 670a5526..24ce3d68 100644
|
||||
}
|
||||
UnitKind::Target {} => {
|
||||
if config.log_debug {
|
||||
diff --git a/drivers/storage/usbscsid/src/main.rs b/drivers/storage/usbscsid/src/main.rs
|
||||
--- a/drivers/storage/usbscsid/src/main.rs
|
||||
+++ b/drivers/storage/usbscsid/src/main.rs
|
||||
@@
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
}
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
- let mut args = env::args().skip(1);
|
||||
+ if let Err(err) = run(daemon) {
|
||||
+ eprintln!("usbscsid: startup failed: {err}");
|
||||
+ std::process::exit(1);
|
||||
+ }
|
||||
+
|
||||
+ std::process::exit(0);
|
||||
+}
|
||||
+
|
||||
+fn run(daemon: daemon::Daemon) -> Result<(), String> {
|
||||
+ let mut args = env::args().skip(1);
|
||||
|
||||
const USAGE: &'static str = "usbscsid <scheme> <port> <protocol>";
|
||||
|
||||
- let scheme = args.next().expect(USAGE);
|
||||
- let port = args
|
||||
- .next()
|
||||
- .expect(USAGE)
|
||||
- .parse::<PortId>()
|
||||
- .expect("Expected port ID");
|
||||
- let protocol = args
|
||||
- .next()
|
||||
- .expect(USAGE)
|
||||
- .parse::<u8>()
|
||||
- .expect("protocol has to be a number 0-255");
|
||||
+ let scheme = args.next().ok_or_else(|| USAGE.to_string())?;
|
||||
+ let port_arg = args.next().ok_or_else(|| USAGE.to_string())?;
|
||||
+ let protocol_arg = args.next().ok_or_else(|| USAGE.to_string())?;
|
||||
+ let port = port_arg
|
||||
+ .parse::<PortId>()
|
||||
+ .map_err(|err| format!("invalid port id `{port_arg}`: {err}"))?;
|
||||
+ let protocol = protocol_arg
|
||||
+ .parse::<u8>()
|
||||
+ .map_err(|err| format!("invalid protocol `{protocol_arg}`: {err}"))?;
|
||||
@@
|
||||
- let handle =
|
||||
- XhciClientHandle::new(scheme.to_owned(), port).expect("Failed to open XhciClientHandle");
|
||||
+ let handle = XhciClientHandle::new(scheme.to_owned(), port)
|
||||
+ .map_err(|err| format!("failed to open XHCI client handle: {err}"))?;
|
||||
|
||||
let desc = handle
|
||||
.get_standard_descs()
|
||||
- .expect("Failed to get standard descriptors");
|
||||
+ .map_err(|err| format!("failed to get standard descriptors: {err}"))?;
|
||||
@@
|
||||
- .expect("Failed to find suitable configuration");
|
||||
+ .ok_or_else(|| "failed to find suitable BOT configuration".to_string())?;
|
||||
@@
|
||||
- .expect("Failed to configure endpoints");
|
||||
+ .map_err(|err| format!("failed to configure endpoints: {err}"))?;
|
||||
|
||||
- let mut protocol = protocol::setup(&handle, protocol, &desc, &conf_desc, &if_desc)
|
||||
- .expect("Failed to setup protocol");
|
||||
+ let mut protocol = protocol::setup(&handle, protocol, &desc, &conf_desc, &if_desc)
|
||||
+ .map_err(|err| format!("failed to setup protocol: {err}"))?;
|
||||
@@
|
||||
- let mut scsi = Scsi::new(&mut *protocol).expect("usbscsid: failed to setup SCSI");
|
||||
+ let mut scsi =
|
||||
+ Scsi::new(&mut *protocol).map_err(|err| format!("failed to setup SCSI: {err}"))?;
|
||||
println!("SCSI initialized");
|
||||
- let mut buffer = [0u8; 512];
|
||||
- scsi.read(&mut *protocol, 0, &mut buffer).unwrap();
|
||||
- println!("DISK CONTENT: {}", base64::encode(&buffer[..]));
|
||||
|
||||
- let event_queue = event::EventQueue::new().unwrap();
|
||||
+ let event_queue =
|
||||
+ event::EventQueue::new().map_err(|err| format!("failed to create event queue: {err}"))?;
|
||||
@@
|
||||
- .unwrap();
|
||||
+ .map_err(|err| format!("failed to subscribe scheme event handle: {err}"))?;
|
||||
|
||||
for event in event_queue {
|
||||
- match event.unwrap().user_data {
|
||||
- Event::Scheme => driver_block::FuturesExecutor
|
||||
- .block_on(scheme.tick())
|
||||
- .unwrap(),
|
||||
+ let event = match event {
|
||||
+ Ok(event) => event,
|
||||
+ Err(err) => {
|
||||
+ eprintln!("usbscsid: event queue error: {err}");
|
||||
+ continue;
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ match event.user_data {
|
||||
+ Event::Scheme => {
|
||||
+ if let Err(err) = driver_block::FuturesExecutor.block_on(scheme.tick()) {
|
||||
+ eprintln!("usbscsid: scheme tick failed: {err}");
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
- std::process::exit(0);
|
||||
+ Ok(())
|
||||
}
|
||||
diff --git a/drivers/storage/usbscsid/src/protocol/mod.rs b/drivers/storage/usbscsid/src/protocol/mod.rs
|
||||
--- a/drivers/storage/usbscsid/src/protocol/mod.rs
|
||||
+++ b/drivers/storage/usbscsid/src/protocol/mod.rs
|
||||
@@
|
||||
#[error("attempted recovery failed")]
|
||||
RecoveryFailed,
|
||||
|
||||
+ #[error("unsupported USB mass-storage protocol 0x{0:02X}")]
|
||||
+ UnsupportedProtocol(u8),
|
||||
+
|
||||
#[error("protocol error")]
|
||||
ProtocolError(&'static str),
|
||||
}
|
||||
@@
|
||||
pub fn setup<'a>(
|
||||
handle: &'a XhciClientHandle,
|
||||
protocol: u8,
|
||||
- dev_desc: &DevDesc,
|
||||
+ _dev_desc: &DevDesc,
|
||||
conf_desc: &ConfDesc,
|
||||
if_desc: &IfDesc,
|
||||
-) -> Option<Box<dyn Protocol + 'a>> {
|
||||
+) -> Result<Box<dyn Protocol + 'a>, ProtocolError> {
|
||||
match protocol {
|
||||
- 0x50 => Some(Box::new(
|
||||
- BulkOnlyTransport::init(handle, conf_desc, if_desc).unwrap(),
|
||||
- )),
|
||||
- _ => None,
|
||||
+ 0x50 => BulkOnlyTransport::init(handle, conf_desc, if_desc)
|
||||
+ .map(|transport| Box::new(transport) as Box<dyn Protocol + 'a>),
|
||||
+ _ => Err(ProtocolError::UnsupportedProtocol(protocol)),
|
||||
}
|
||||
}
|
||||
diff --git a/drivers/storage/usbscsid/src/scsi/mod.rs b/drivers/storage/usbscsid/src/scsi/mod.rs
|
||||
--- a/drivers/storage/usbscsid/src/scsi/mod.rs
|
||||
+++ b/drivers/storage/usbscsid/src/scsi/mod.rs
|
||||
@@
|
||||
#[error("overflow")]
|
||||
Overflow(&'static str),
|
||||
+
|
||||
+ #[error("SCSI command failed: {0}")]
|
||||
+ CommandFailed(&'static str),
|
||||
}
|
||||
@@
|
||||
if let SendCommandStatus {
|
||||
kind: SendCommandStatusKind::Failed,
|
||||
..
|
||||
} = protocol.send_command(
|
||||
&self.command_buffer[..10],
|
||||
DeviceReqData::In(&mut self.data_buffer[..initial_alloc_len as usize]),
|
||||
)? {
|
||||
self.get_ff_sense(protocol, 252)?;
|
||||
- panic!("{:?}", self.res_ff_sense_data());
|
||||
+ eprintln!(
|
||||
+ "usbscsid: MODE SENSE(10) failed; sense data: {:?}",
|
||||
+ self.res_ff_sense_data()
|
||||
+ );
|
||||
+ return Err(ScsiError::CommandFailed("MODE SENSE(10)"));
|
||||
}
|
||||
diff --git a/drivers/usb/xhcid/src/xhci/event.rs b/drivers/usb/xhcid/src/xhci/event.rs
|
||||
--- a/drivers/usb/xhcid/src/xhci/event.rs
|
||||
+++ b/drivers/usb/xhcid/src/xhci/event.rs
|
||||
@@
|
||||
#[test]
|
||||
fn grow_preserves_existing_ring_state() {
|
||||
- let mut ring = EventRing::new::<super::super::CONTEXT_64>(true).unwrap();
|
||||
+ let mut ring = EventRing::new::<{ super::super::CONTEXT_64 }>(true).unwrap();
|
||||
@@
|
||||
- ring.grow::<super::super::CONTEXT_64>(true, old_len + 64)
|
||||
+ ring.grow::<{ super::super::CONTEXT_64 }>(true, old_len + 64)
|
||||
.unwrap();
|
||||
diff --git a/drivers/usb/xhcid/src/xhci/mod.rs b/drivers/usb/xhcid/src/xhci/mod.rs
|
||||
--- a/drivers/usb/xhcid/src/xhci/mod.rs
|
||||
+++ b/drivers/usb/xhcid/src/xhci/mod.rs
|
||||
@@
|
||||
let dev_desc = self.get_desc(port_id, slot).await?;
|
||||
debug!("Got the full device descriptor!");
|
||||
+ info!(
|
||||
+ "port {} slot {} device {:04X}:{:04X} class {}.{} proto {} has {} configuration(s)",
|
||||
+ port_id,
|
||||
+ slot,
|
||||
+ dev_desc.vendor,
|
||||
+ dev_desc.product,
|
||||
+ dev_desc.class,
|
||||
+ dev_desc.sub_class,
|
||||
+ dev_desc.protocol,
|
||||
+ dev_desc.config_descs.len()
|
||||
+ );
|
||||
self.port_states.get_mut(&port_id).unwrap().dev_desc = Some(dev_desc);
|
||||
@@
|
||||
debug!("Updated the default control pipe");
|
||||
+ info!("port {} slot {} starting subdriver matching", port_id, slot);
|
||||
|
||||
match self.spawn_drivers(port_id) {
|
||||
Ok(()) => (),
|
||||
@@
|
||||
trace!("Got config and device descriptors on port {}", port);
|
||||
let drivers_usercfg: &DriversConfig = &DRIVERS_CONFIG;
|
||||
+
|
||||
+ if config_desc.interface_descs.is_empty() {
|
||||
+ warn!(
|
||||
+ "No interface descriptors found for port {} in configuration {}; no subdrivers can be matched",
|
||||
+ port,
|
||||
+ config_desc.configuration_value
|
||||
+ );
|
||||
+ }
|
||||
|
||||
for ifdesc in config_desc.interface_descs.iter() {
|
||||
diff --git a/drivers/usb/xhcid/src/xhci/scheme.rs b/drivers/usb/xhcid/src/xhci/scheme.rs
|
||||
--- a/drivers/usb/xhcid/src/xhci/scheme.rs
|
||||
+++ b/drivers/usb/xhcid/src/xhci/scheme.rs
|
||||
@@
|
||||
pub enum AnyDescriptor {
|
||||
// These are the ones that I have found, but there are more.
|
||||
Device(usb::DeviceDescriptor),
|
||||
Config(usb::ConfigDescriptor),
|
||||
Interface(usb::InterfaceDescriptor),
|
||||
Endpoint(usb::EndpointDescriptor),
|
||||
Hid(usb::HidDescriptor),
|
||||
SuperSpeedCompanion(usb::SuperSpeedCompanionDescriptor),
|
||||
SuperSpeedPlusCompanion(usb::SuperSpeedPlusIsochCmpDescriptor),
|
||||
+ Unknown { kind: u8 },
|
||||
}
|
||||
|
||||
impl AnyDescriptor {
|
||||
@@
|
||||
- _ => {
|
||||
- //panic!("Descriptor unknown {}: bytes {:#0x?}", kind, bytes);
|
||||
- return None;
|
||||
- }
|
||||
+ _ => Self::Unknown { kind },
|
||||
},
|
||||
len.into(),
|
||||
))
|
||||
@@
|
||||
- let mut interface_descs = SmallVec::new();
|
||||
+ let mut interface_descs = SmallVec::<[IfDesc; 1]>::new();
|
||||
let mut iter = descriptors.into_iter().peekable();
|
||||
@@
|
||||
Some(AnyDescriptor::Hid(h)) if idesc.class == 3 => {
|
||||
hid_descs.push(h.into());
|
||||
continue;
|
||||
}
|
||||
+ Some(AnyDescriptor::Unknown { kind }) => {
|
||||
+ log::warn!(
|
||||
+ "port {} slot {} iface {} skipping unknown descriptor kind {} while collecting endpoints",
|
||||
+ port_id,
|
||||
+ slot,
|
||||
+ idesc.number,
|
||||
+ kind
|
||||
+ );
|
||||
+ continue;
|
||||
+ }
|
||||
Some(unexpected) => {
|
||||
log::warn!("expected endpoint, got {:X?}", unexpected);
|
||||
break;
|
||||
@@
|
||||
} else {
|
||||
log::warn!("expected interface, got {:?}", item);
|
||||
// TODO
|
||||
//break;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ log::info!(
|
||||
+ "port {} slot {} config {} parsed {} descriptor entries into {} interface(s)",
|
||||
+ port_id,
|
||||
+ slot,
|
||||
+ index,
|
||||
+ descriptor_count,
|
||||
+ interface_descs.len()
|
||||
+ );
|
||||
+
|
||||
+ for if_desc in interface_descs.iter() {
|
||||
+ let number: u8 = if_desc.number;
|
||||
+ let alternate_setting: u8 = if_desc.alternate_setting;
|
||||
+ let class: u8 = if_desc.class;
|
||||
+ let sub_class: u8 = if_desc.sub_class;
|
||||
+ let protocol: u8 = if_desc.protocol;
|
||||
+ let endpoint_count: usize = if_desc.endpoints.len();
|
||||
+ log::info!(
|
||||
+ "port {} slot {} config {} iface {} alt {} class {}.{} proto {} endpoints {}",
|
||||
+ port_id,
|
||||
+ slot,
|
||||
+ index,
|
||||
+ number,
|
||||
+ alternate_setting,
|
||||
+ class,
|
||||
+ sub_class,
|
||||
+ protocol,
|
||||
+ endpoint_count
|
||||
+ );
|
||||
+ }
|
||||
|
||||
@@ -1,13 +1,34 @@
|
||||
use core::ptr::NonNull;
|
||||
use std::sync::atomic::{AtomicI32, Ordering};
|
||||
|
||||
use redox_syscall::flag::{MAP_SHARED, O_CLOEXEC, O_RDWR, PROT_READ, PROT_WRITE};
|
||||
use redox_syscall::flag::{MAP_PRIVATE, O_CLOEXEC, PROT_READ, PROT_WRITE};
|
||||
use redox_syscall::PAGE_SIZE;
|
||||
use syscall as redox_syscall;
|
||||
|
||||
use crate::{DriverError, Result};
|
||||
|
||||
/// SAFETY: Cached FD for `/scheme/memory/physical`. -1 means uninitialized.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum DmaMemoryType {
|
||||
Writeback,
|
||||
Uncacheable,
|
||||
}
|
||||
|
||||
impl DmaMemoryType {
|
||||
const fn suffix(self) -> &'static str {
|
||||
match self {
|
||||
Self::Writeback => "wb",
|
||||
Self::Uncacheable => "uc",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DMA_MEMORY_TYPE: DmaMemoryType = if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
|
||||
DmaMemoryType::Writeback
|
||||
} else {
|
||||
DmaMemoryType::Uncacheable
|
||||
};
|
||||
|
||||
/// SAFETY: Cached FD for `/scheme/memory/scheme-root`. -1 means uninitialized.
|
||||
/// This FD is process-lifetime cached for performance. If scheme:memory
|
||||
/// restarts (which should never happen — it's a kernel scheme), all
|
||||
/// in-flight DMA operations are already undefined behavior.
|
||||
@@ -19,7 +40,7 @@ fn get_dma_memory_fd() -> Result<i32> {
|
||||
return Ok(current);
|
||||
}
|
||||
|
||||
let fd = libredox::call::open("/scheme/memory/physical", (O_CLOEXEC | O_RDWR) as i32, 0)
|
||||
let fd = libredox::call::open("/scheme/memory/scheme-root", O_CLOEXEC as i32, 0)
|
||||
.map_err(|e| DriverError::Io(std::io::Error::from_raw_os_error(e.errno())))?;
|
||||
|
||||
let raw = fd as i32;
|
||||
@@ -68,7 +89,11 @@ fn virt_to_phys_cached(virt: usize) -> Result<usize> {
|
||||
|
||||
enum DmaStorage {
|
||||
/// Allocated via scheme:memory — freed via munmap
|
||||
SchemeMapped { ptr: NonNull<u8>, size: usize },
|
||||
SchemeMapped {
|
||||
ptr: NonNull<u8>,
|
||||
size: usize,
|
||||
region_fd: i32,
|
||||
},
|
||||
/// Allocated via heap — freed via dealloc
|
||||
Heap {
|
||||
ptr: NonNull<u8>,
|
||||
@@ -126,9 +151,8 @@ impl DmaBuffer {
|
||||
/// Allocate physically contiguous memory via scheme:memory/physical.
|
||||
fn allocate_via_scheme(mem_fd: i32, size: usize, _align: usize) -> Result<Self> {
|
||||
// Open a physical memory region of the requested size
|
||||
let path = format!("zeroed@{}", size);
|
||||
let region_fd =
|
||||
libredox::call::openat(mem_fd as usize, &path, (O_CLOEXEC | O_RDWR) as i32, 0)
|
||||
let path = format!("zeroed@{}?phys_contiguous", DMA_MEMORY_TYPE.suffix());
|
||||
let region_fd = libredox::call::openat(mem_fd as usize, &path, O_CLOEXEC as i32, 0)
|
||||
.map_err(|e| DriverError::Io(std::io::Error::from_raw_os_error(e.errno())))?;
|
||||
|
||||
// Map it into our address space
|
||||
@@ -137,7 +161,7 @@ impl DmaBuffer {
|
||||
fd: region_fd as usize,
|
||||
offset: 0,
|
||||
length: size,
|
||||
flags: MAP_SHARED.bits() as u32,
|
||||
flags: MAP_PRIVATE.bits() as u32,
|
||||
prot: (PROT_READ | PROT_WRITE).bits() as u32,
|
||||
addr: core::ptr::null_mut(),
|
||||
})
|
||||
@@ -154,6 +178,17 @@ impl DmaBuffer {
|
||||
let _ = libredox::call::close(region_fd as usize);
|
||||
|
||||
let phys_addr = virt_to_phys_cached(ptr as usize)?;
|
||||
for page in 1..size.div_ceil(PAGE_SIZE) {
|
||||
let translated = virt_to_phys_cached(ptr as usize + page * PAGE_SIZE)?;
|
||||
if translated != phys_addr + page * PAGE_SIZE {
|
||||
return Err(DriverError::Other(format!(
|
||||
"DMA mapping is not physically contiguous across page {}: expected {:#x}, got {:#x}",
|
||||
page,
|
||||
phys_addr + page * PAGE_SIZE,
|
||||
translated
|
||||
)));
|
||||
}
|
||||
}
|
||||
let ptr = NonNull::new(ptr as *mut u8)
|
||||
.ok_or_else(|| DriverError::Other("DMA mmap returned null".into()))?;
|
||||
|
||||
@@ -165,7 +200,11 @@ impl DmaBuffer {
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
storage: DmaStorage::SchemeMapped { ptr, size },
|
||||
storage: DmaStorage::SchemeMapped {
|
||||
ptr,
|
||||
size,
|
||||
region_fd: region_fd as i32,
|
||||
},
|
||||
phys_addr,
|
||||
size,
|
||||
})
|
||||
@@ -205,8 +244,13 @@ impl DmaBuffer {
|
||||
impl Drop for DmaBuffer {
|
||||
fn drop(&mut self) {
|
||||
match &self.storage {
|
||||
DmaStorage::SchemeMapped { ptr, size } => {
|
||||
DmaStorage::SchemeMapped {
|
||||
ptr,
|
||||
size,
|
||||
region_fd,
|
||||
} => {
|
||||
let _ = unsafe { libredox::call::munmap(ptr.as_ptr() as *mut (), *size) };
|
||||
let _ = libredox::call::close(*region_fd as usize);
|
||||
}
|
||||
DmaStorage::Heap { ptr, layout } => {
|
||||
unsafe { std::alloc::dealloc(ptr.as_ptr(), *layout) };
|
||||
|
||||
@@ -149,6 +149,12 @@ impl MsixTable {
|
||||
let (irq, fd) = allocate_irq_vector(cpu_id)?;
|
||||
self.program_x86_message(index, cpu_id, irq)?;
|
||||
self.unmask_vector(index);
|
||||
log::info!(
|
||||
"redox-driver-sys: allocated MSI-X vector {} -> irq {} on cpu {}",
|
||||
index,
|
||||
irq,
|
||||
cpu_id
|
||||
);
|
||||
Ok(MsixVector { fd, index, irq })
|
||||
}
|
||||
|
||||
@@ -288,7 +294,15 @@ fn allocate_irq_vector(cpu_id: u8) -> Result<(u32, File)> {
|
||||
.create_new(true)
|
||||
.open(&path)
|
||||
{
|
||||
Ok(fd) => return Ok((irq, fd)),
|
||||
Ok(fd) => {
|
||||
log::debug!(
|
||||
"redox-driver-sys: reserved irq vector {} from {} for cpu {}",
|
||||
irq,
|
||||
path,
|
||||
cpu_id
|
||||
);
|
||||
return Ok((irq, fd));
|
||||
}
|
||||
Err(err) if err.kind() == ErrorKind::AlreadyExists => continue,
|
||||
Err(err) if err.kind() == ErrorKind::NotFound => continue,
|
||||
Err(err) => {
|
||||
|
||||
+10
-7
@@ -64,16 +64,19 @@ Driver access pattern:
|
||||
- Register as scheme: daemon name becomes `/scheme/<name>`
|
||||
- PCI devices discovered via `pcid` daemon → spawns drivers
|
||||
|
||||
## POSIX GAPS IN RELIBC (blocking Wayland)
|
||||
## HISTORICAL POSIX GAPS IN RELIBC (Wayland-facing)
|
||||
|
||||
| Missing API | Location to implement |
|
||||
|-------------|----------------------|
|
||||
| signalfd/signalfd4 | `relibc/source/src/header/signal/` |
|
||||
| timerfd_create/settime/gettime | `relibc/source/src/header/sys_timerfd/` (NEW) |
|
||||
| eventfd | `relibc/source/src/header/sys_eventfd/` (NEW) |
|
||||
| F_DUPFD_CLOEXEC | `relibc/source/src/header/fcntl/` |
|
||||
| MSG_CMSG_CLOEXEC, MSG_NOSIGNAL | `relibc/source/src/header/sys_socket/` |
|
||||
| open_memstream | `relibc/source/src/header/stdio/` |
|
||||
| signalfd/signalfd4 | `relibc/source/src/header/signal/` — now source-visible in the current Red Bear tree |
|
||||
| timerfd_create/settime/gettime | `relibc/source/src/header/sys_timerfd/` — now source-visible in the current Red Bear tree |
|
||||
| eventfd | `relibc/source/src/header/sys_eventfd/` — now source-visible in the current Red Bear tree |
|
||||
| F_DUPFD_CLOEXEC | `relibc/source/src/header/fcntl/` — now source-visible in the current Red Bear tree |
|
||||
| MSG_CMSG_CLOEXEC, MSG_NOSIGNAL | `relibc/source/src/header/sys_socket/` — now source-visible in the current Red Bear tree |
|
||||
| open_memstream | `relibc/source/src/header/stdio/` — now source-visible in the current Red Bear tree |
|
||||
|
||||
The current relibc work is therefore no longer just “add the missing Wayland APIs.” The higher-value
|
||||
remaining work is completeness depth, downstream cleanup, and runtime validation.
|
||||
|
||||
## ANTI-PATTERNS
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ BINS=(
|
||||
# depending on the target architecture
|
||||
case "${TARGET}" in
|
||||
i586-unknown-redox | i686-unknown-redox | x86_64-unknown-redox)
|
||||
BINS+=(ac97d bgad sb16d vboxd)
|
||||
BINS+=(ac97d sb16d vboxd)
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user