drviers: chrdev: random: new

Add a new chardev which implements /dev/random.
This commit is contained in:
Matthew Leach
2026-02-25 20:30:07 +00:00
committed by Ashwin Naren
parent d85293f5a7
commit 95dbf4f4f2
5 changed files with 95 additions and 2 deletions

View File

@@ -0,0 +1,3 @@
pub mod null;
pub mod random;
pub mod zero;

View File

@@ -0,0 +1,90 @@
use crate::{
drivers::{
CharDriver, DriverManager, OpenableDevice, ReservedMajors, fs::dev::devfs,
init::PlatformBus,
},
fs::{
fops::FileOps,
open_file::{FileCtx, OpenFile},
},
kernel::rand::sys_getrandom,
kernel_driver,
};
use alloc::{boxed::Box, string::ToString, sync::Arc};
use async_trait::async_trait;
use core::{future::Future, pin::Pin};
use libkernel::{
driver::CharDevDescriptor,
error::Result,
fs::{OpenFlags, attr::FilePermissions},
memory::address::UA,
};
struct RandomFileOps;
#[async_trait]
impl FileOps for RandomFileOps {
async fn read(&mut self, _ctx: &mut FileCtx, buf: UA, count: usize) -> Result<usize> {
self.readat(buf, count, 0).await
}
async fn writeat(&mut self, _buf: UA, count: usize, _offset: u64) -> Result<usize> {
// Just consume the write.
Ok(count)
}
async fn readat(&mut self, buf: UA, count: usize, _offset: u64) -> Result<usize> {
sys_getrandom(buf.cast(), count as _, 0).await
}
fn poll_read_ready(&self) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> {
Box::pin(async { Ok(()) })
}
}
struct RandomDev;
impl OpenableDevice for RandomDev {
fn open(&self, flags: OpenFlags) -> Result<Arc<OpenFile>> {
Ok(Arc::new(OpenFile::new(Box::new(RandomFileOps), flags)))
}
}
struct RandomCharDev {
random_dev: Arc<dyn OpenableDevice>,
}
impl RandomCharDev {
fn new() -> Result<Self> {
devfs().mknod(
"random".to_string(),
CharDevDescriptor {
major: ReservedMajors::Random as _,
minor: 0,
},
FilePermissions::from_bits_retain(0o666),
)?;
Ok(Self {
random_dev: Arc::new(RandomDev),
})
}
}
impl CharDriver for RandomCharDev {
fn get_device(&self, minor: u64) -> Option<Arc<dyn OpenableDevice>> {
if minor == 0 {
Some(self.random_dev.clone())
} else {
None
}
}
}
/// Driver initialisation entry point invoked during kernel boot.
pub fn random_chardev_init(_bus: &mut PlatformBus, dm: &mut DriverManager) -> Result<()> {
let cdev = RandomCharDev::new()?;
dm.register_char_driver(ReservedMajors::Random as _, Arc::new(cdev))
}
kernel_driver!(random_chardev_init);

View File

@@ -20,20 +20,20 @@ use crate::{
sync::SpinLock,
};
pub mod chrdev;
pub mod fdt_prober;
pub mod fs;
pub mod init;
pub mod interrupts;
pub mod null;
pub mod probe;
pub mod timer;
pub mod uart;
pub mod zero;
#[repr(u64)]
pub enum ReservedMajors {
Null = 1,
Zero = 2,
Random = 3,
Console = 5,
Uart = 10,
End = 11,