Skip to content

Commit 94abb57

Browse files
committed
Add config API.
The OS can use this to store arbitrary configuration (which has been serialised to a byte array) and get it back again.
1 parent 25329e8 commit 94abb57

File tree

1 file changed

+68
-2
lines changed

1 file changed

+68
-2
lines changed

src/lib.rs

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//!
55
//! ## License
66
//!
7-
//! Copyright (C) 2019 Jonathan 'theJPster' Pallant <[email protected]>
7+
//! Copyright (C) The Neotron Developers, 2019-2020
88
//!
99
//! This program is free software: you can redistribute it and/or modify
1010
//! it under the terms of the GNU General Public License as published by
@@ -24,7 +24,7 @@
2424

2525
/// BIOS API semantic version for the API defined in this crate, as <0x00>
2626
/// <major> <minor> <patch>.
27-
pub const API_VERSION: u32 = 0x0000_0100;
27+
pub const API_VERSION: u32 = 0x00_00_02_00;
2828

2929
/// The type of the function which starts up the Operating System. The BIOS
3030
/// finds and calls this function.
@@ -103,6 +103,19 @@ pub struct ApiByteSlice<'a> {
103103
_phantom: core::marker::PhantomData<&'a [u8]>,
104104
}
105105

106+
/// A Rust u8 mutable slice, but compatible with FFI. Assume the lifetime is
107+
/// only valid until the callee returns to the caller.
108+
#[repr(C)]
109+
#[derive(Clone)]
110+
pub struct ApiBuffer<'a> {
111+
/// A pointer to where the data can be put
112+
pub data: *mut u8,
113+
/// The maximum number of bytes we can store in this buffer
114+
pub data_len: usize,
115+
/// A phantom object to hold the lifetime
116+
_phantom: core::marker::PhantomData<&'a [u8]>,
117+
}
118+
106119
/// Represents an instant in time between 2000-01-01T00:00:00Z and
107120
/// 2136-02-07T06:28:16Z.
108121
#[repr(C)]
@@ -184,6 +197,16 @@ pub struct Api {
184197
/// two consecutive bytes - one for the glyph and one for the attribute.
185198
pub video_memory_info_get:
186199
extern "C" fn(address: &mut *mut u8, width_cols: &mut u8, height_rows: &mut u8),
200+
/// Get the configuration data block.
201+
///
202+
/// Configuration data is, to the BIOS, just a block of bytes of a given
203+
/// length. How it stores them is up to the BIOS - it could be EEPROM, or
204+
/// battery-backed SRAM.
205+
pub configuration_get: extern "C" fn(buffer: ApiBuffer) -> crate::Result<usize>,
206+
/// Set the configuration data block.
207+
///
208+
/// See `configuration_get`.
209+
pub configuration_set: extern "C" fn(buffer: ApiByteSlice) -> crate::Result<()>,
187210
}
188211

189212
/// Serial Port / UART related types.
@@ -340,6 +363,49 @@ impl<'a> From<&'a [u8]> for ApiByteSlice<'a> {
340363
}
341364
}
342365

366+
impl core::fmt::Debug for ApiBuffer<'_> {
367+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
368+
let slice = self.as_slice();
369+
write!(f, "[ ")?;
370+
if let Some((last, rest)) = slice.split_last() {
371+
for i in rest.iter() {
372+
write!(f, "0x{:02x}, ", i)?;
373+
}
374+
write!(f, "0x{:02x} ", last)?;
375+
}
376+
write!(f, "]")
377+
}
378+
}
379+
380+
impl<'a> ApiBuffer<'a> {
381+
/// Create a new buffer we can send over the FFI. NB: By doing this Rust
382+
/// can't track lifetimes any more.
383+
pub fn new(s: &'a mut [u8]) -> ApiBuffer<'a> {
384+
ApiBuffer {
385+
data: s.as_mut_ptr(),
386+
data_len: s.len(),
387+
_phantom: core::marker::PhantomData,
388+
}
389+
}
390+
391+
/// Turn this buffer into a Rust byte slice.
392+
pub fn as_slice(&self) -> &[u8] {
393+
unsafe { core::slice::from_raw_parts(self.data, self.data_len) }
394+
}
395+
396+
/// Turn this buffer into a Rust mutable byte slice.
397+
pub fn as_mut_slice(&mut self) -> &mut [u8] {
398+
unsafe { core::slice::from_raw_parts_mut(self.data, self.data_len) }
399+
}
400+
}
401+
402+
impl<'a> From<&'a mut [u8]> for ApiBuffer<'a> {
403+
/// Convert from a Rust byte slice into an FFI compatible byte slice
404+
fn from(input: &'a mut [u8]) -> ApiBuffer<'a> {
405+
ApiBuffer::new(input)
406+
}
407+
}
408+
343409
impl<'a> ApiString<'a> {
344410
/// Create a new string slice we can send over the FFI.
345411
pub fn new(s: &'a str) -> ApiString<'a> {

0 commit comments

Comments
 (0)