diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig index 189c10ced6d4f7..84ee68733e7574 100644 --- a/samples/rust/Kconfig +++ b/samples/rust/Kconfig @@ -70,6 +70,16 @@ config SAMPLE_RUST_MISCDEV If unsure, say N. +config SAMPLE_RUST_BUFFER + tristate "File buffer" + help + This option builds the Rust file buffer sample. + + To compile this as a module, choose M here: + the module will be called rust_buffer. + + If unsure, say N. + config SAMPLE_RUST_STACK_PROBING tristate "Stack probing" help diff --git a/samples/rust/Makefile b/samples/rust/Makefile index 420bcefeb08255..a5da377b96d728 100644 --- a/samples/rust/Makefile +++ b/samples/rust/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_SAMPLE_RUST_MODULE_PARAMETERS) += rust_module_parameters.o obj-$(CONFIG_SAMPLE_RUST_SYNC) += rust_sync.o obj-$(CONFIG_SAMPLE_RUST_CHRDEV) += rust_chrdev.o obj-$(CONFIG_SAMPLE_RUST_MISCDEV) += rust_miscdev.o +obj-$(CONFIG_SAMPLE_RUST_BUFFER) += rust_buffer.o obj-$(CONFIG_SAMPLE_RUST_STACK_PROBING) += rust_stack_probing.o obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE) += rust_semaphore.o obj-$(CONFIG_SAMPLE_RUST_SEMAPHORE_C) += rust_semaphore_c.o diff --git a/samples/rust/rust_buffer.rs b/samples/rust/rust_buffer.rs new file mode 100644 index 00000000000000..827fc92d67e7fe --- /dev/null +++ b/samples/rust/rust_buffer.rs @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 + +//! Rust memory-backed file. +//! +//! Allocate a buffer of shared kernel memory and expose this buffer to user-space using a misc +//! file device interface. + +use kernel::{ + file::{self, File}, + io_buffer::{IoBufferReader, IoBufferWriter}, + prelude::*, +}; + +module_misc_device! { + type: RustBuffer, + name: "rust_buffer", + author: "Andrea Righi ", + description: "Memory-backed file implemented in Rust", + license: "GPL v2", +} + +// Size of the shared memory buffer (4K by default) +const BUFSIZE : usize = 4096usize; + +// Shared memory buffer +static mut BUFFER: [u8; BUFSIZE] = [0u8; BUFSIZE]; + +struct RustBuffer { +} + +#[vtable] +impl file::Operations for RustBuffer { + type Data = Box; + + fn open(_context: &Self::OpenData, _file: &File) -> Result { + Ok(Box::try_new(Self { })?) + } + + fn read(_this: &Self, _: &File, buf: &mut impl IoBufferWriter, offset: u64) -> Result { + let mut total_len = 0; + let off : usize = offset.try_into().unwrap(); + + while !buf.is_empty() { + let start : usize = off + total_len; + let len = buf.len().min(BUFSIZE - start); + if len <= 0 { + break; + } + unsafe { + buf.write_slice(&BUFFER[start .. start + len])?; + } + total_len += len; + } + Ok(total_len) + } + + fn write(_this: &Self, _: &File, buf: &mut impl IoBufferReader, offset: u64) -> Result { + let mut total_len = 0; + let off : usize = offset.try_into().unwrap(); + + while !buf.is_empty() { + let start : usize = off + total_len; + let len = buf.len().min(BUFSIZE - start); + if len <= 0 { + break; + } + unsafe { + buf.read_slice(&mut BUFFER[start .. start + len])?; + } + total_len += len; + } + Ok(total_len) + } +}