Red Bear OS — microkernel OS in Rust, based on Redox
Derivative of Redox OS (https://www.redox-os.org) adding: - AMD GPU driver (amdgpu) via LinuxKPI compat layer - ext4 filesystem support (ext4d scheme daemon) - ACPI fixes for AMD bare metal (x2APIC, DMAR, IVRS, MCFG) - Custom branding (hostname, os-release, boot identity) Build system is full upstream Redox with RBOS overlay in local/. Patches for kernel, base, and relibc are symlinked from local/patches/ and protected from make clean/distclean. Custom recipes live in local/recipes/ with symlinks into the recipes/ search path. Build: make all CONFIG_NAME=redbear-full Sync: ./local/scripts/sync-upstream.sh
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
[package]
|
||||
name = "ext4-blockdev"
|
||||
description = "BlockDevice trait implementations for rsext4 on Redox OS"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
rsext4.workspace = true
|
||||
redox_syscall = { workspace = true, optional = true }
|
||||
libredox = { workspace = true, optional = true }
|
||||
log.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["redox"]
|
||||
redox = ["dep:redox_syscall", "dep:libredox"]
|
||||
@@ -0,0 +1,100 @@
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::path::Path;
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use rsext4::bmalloc::AbsoluteBN;
|
||||
use rsext4::disknode::Ext4Timestamp;
|
||||
use rsext4::{BlockDevice, Ext4Error, Ext4Result};
|
||||
|
||||
pub struct FileDisk {
|
||||
file: File,
|
||||
total_blocks: u64,
|
||||
block_size: u32,
|
||||
}
|
||||
|
||||
impl FileDisk {
|
||||
pub fn open<P: AsRef<Path>>(path: P, block_size: u32) -> std::io::Result<Self> {
|
||||
let file = OpenOptions::new().read(true).write(true).open(path)?;
|
||||
let len = file.metadata()?.len();
|
||||
Ok(Self {
|
||||
file,
|
||||
total_blocks: len / block_size as u64,
|
||||
block_size,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create<P: AsRef<Path>>(path: P, size: u64, block_size: u32) -> std::io::Result<Self> {
|
||||
let file = OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)?;
|
||||
file.set_len(size)?;
|
||||
Ok(Self {
|
||||
file,
|
||||
total_blocks: size / block_size as u64,
|
||||
block_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for FileDisk {
|
||||
fn read(&mut self, buffer: &mut [u8], block_id: AbsoluteBN, count: u32) -> Ext4Result<()> {
|
||||
let offset = block_id.raw() * self.block_size as u64;
|
||||
self.file
|
||||
.seek(SeekFrom::Start(offset))
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
let total = count as usize * self.block_size as usize;
|
||||
if buffer.len() < total {
|
||||
return Err(Ext4Error::invalid_input());
|
||||
}
|
||||
self.file
|
||||
.read_exact(&mut buffer[..total])
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, buffer: &[u8], block_id: AbsoluteBN, count: u32) -> Ext4Result<()> {
|
||||
let offset = block_id.raw() * self.block_size as u64;
|
||||
self.file
|
||||
.seek(SeekFrom::Start(offset))
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
let total = count as usize * self.block_size as usize;
|
||||
if buffer.len() < total {
|
||||
return Err(Ext4Error::invalid_input());
|
||||
}
|
||||
self.file
|
||||
.write_all(&buffer[..total])
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(&mut self) -> Ext4Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&mut self) -> Ext4Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn total_blocks(&self) -> u64 {
|
||||
self.total_blocks
|
||||
}
|
||||
|
||||
fn block_size(&self) -> u32 {
|
||||
self.block_size
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Ext4Result<()> {
|
||||
self.file.sync_data().map_err(|_| Ext4Error::io())
|
||||
}
|
||||
|
||||
fn current_time(&self) -> Ext4Result<Ext4Timestamp> {
|
||||
let dur = std::time::SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
Ok(Ext4Timestamp::new(dur.as_secs() as i64, dur.subsec_nanos()))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
pub mod file_disk;
|
||||
|
||||
#[cfg(feature = "redox")]
|
||||
pub mod redox_disk;
|
||||
|
||||
pub use file_disk::FileDisk;
|
||||
|
||||
#[cfg(feature = "redox")]
|
||||
pub use redox_disk::RedoxDisk;
|
||||
|
||||
pub use rsext4::bmalloc::AbsoluteBN;
|
||||
pub use rsext4::disknode::Ext4Timestamp;
|
||||
pub use rsext4::{BlockDevice, Ext4Error, Ext4Result};
|
||||
@@ -0,0 +1,93 @@
|
||||
use rsext4::bmalloc::AbsoluteBN;
|
||||
use rsext4::disknode::Ext4Timestamp;
|
||||
use rsext4::{BlockDevice, Ext4Error, Ext4Result};
|
||||
|
||||
pub struct RedoxDisk {
|
||||
fd: usize,
|
||||
total_blocks: u64,
|
||||
block_size: u32,
|
||||
}
|
||||
|
||||
impl RedoxDisk {
|
||||
pub fn open(disk_path: &str, block_size: u32) -> syscall::error::Result<Self> {
|
||||
let fd = libredox::call::open(disk_path, libredox::flag::O_RDWR, 0)?;
|
||||
let mut stat = syscall::data::Stat::default();
|
||||
syscall::call::fstat(fd, &mut stat)?;
|
||||
let total_blocks = stat.st_size / block_size as u64;
|
||||
Ok(Self {
|
||||
fd,
|
||||
total_blocks,
|
||||
block_size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockDevice for RedoxDisk {
|
||||
fn read(&mut self, buffer: &mut [u8], block_id: AbsoluteBN, count: u32) -> Ext4Result<()> {
|
||||
let offset = block_id.raw() * self.block_size as u64;
|
||||
let total = count as usize * self.block_size as usize;
|
||||
if buffer.len() < total {
|
||||
return Err(Ext4Error::invalid_input());
|
||||
}
|
||||
syscall::call::lseek(self.fd, offset as isize, syscall::flag::SEEK_SET)
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
let mut read_total = 0;
|
||||
while read_total < total {
|
||||
let n = syscall::call::read(self.fd, &mut buffer[read_total..total])
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
if n == 0 {
|
||||
return Err(Ext4Error::io());
|
||||
}
|
||||
read_total += n;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write(&mut self, buffer: &[u8], block_id: AbsoluteBN, count: u32) -> Ext4Result<()> {
|
||||
let offset = block_id.raw() * self.block_size as u64;
|
||||
let total = count as usize * self.block_size as usize;
|
||||
if buffer.len() < total {
|
||||
return Err(Ext4Error::invalid_input());
|
||||
}
|
||||
syscall::call::lseek(self.fd, offset as isize, syscall::flag::SEEK_SET)
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
let mut written_total = 0;
|
||||
while written_total < total {
|
||||
let n = syscall::call::write(self.fd, &buffer[written_total..total])
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
if n == 0 {
|
||||
return Err(Ext4Error::io());
|
||||
}
|
||||
written_total += n;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(&mut self) -> Ext4Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn close(&mut self) -> Ext4Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn total_blocks(&self) -> u64 {
|
||||
self.total_blocks
|
||||
}
|
||||
|
||||
fn block_size(&self) -> u32 {
|
||||
self.block_size
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Ext4Result<()> {
|
||||
syscall::call::fsync(self.fd).map_err(|_| Ext4Error::io())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_time(&self) -> Ext4Result<Ext4Timestamp> {
|
||||
let mut ts = syscall::data::TimeSpec::default();
|
||||
syscall::call::clock_gettime(syscall::flag::CLOCK_REALTIME, &mut ts)
|
||||
.map_err(|_| Ext4Error::io())?;
|
||||
Ok(Ext4Timestamp::new(ts.tv_sec, ts.tv_nsec as u32))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user