|
4 | 4 | //! |
5 | 5 | //! ## License |
6 | 6 | //! |
7 | | -//! Copyright (C) 2019 Jonathan 'theJPster' Pallant <[email protected]> |
| 7 | +//! Copyright (C) The Neotron Developers, 2019-2020 |
8 | 8 | //! |
9 | 9 | //! This program is free software: you can redistribute it and/or modify |
10 | 10 | //! it under the terms of the GNU General Public License as published by |
|
24 | 24 |
|
25 | 25 | /// BIOS API semantic version for the API defined in this crate, as <0x00> |
26 | 26 | /// <major> <minor> <patch>. |
27 | | -pub const API_VERSION: u32 = 0x0000_0100; |
| 27 | +pub const API_VERSION: u32 = 0x00_00_02_00; |
28 | 28 |
|
29 | 29 | /// The type of the function which starts up the Operating System. The BIOS |
30 | 30 | /// finds and calls this function. |
@@ -103,6 +103,19 @@ pub struct ApiByteSlice<'a> { |
103 | 103 | _phantom: core::marker::PhantomData<&'a [u8]>, |
104 | 104 | } |
105 | 105 |
|
| 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 | + |
106 | 119 | /// Represents an instant in time between 2000-01-01T00:00:00Z and |
107 | 120 | /// 2136-02-07T06:28:16Z. |
108 | 121 | #[repr(C)] |
@@ -184,6 +197,16 @@ pub struct Api { |
184 | 197 | /// two consecutive bytes - one for the glyph and one for the attribute. |
185 | 198 | pub video_memory_info_get: |
186 | 199 | 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<()>, |
187 | 210 | } |
188 | 211 |
|
189 | 212 | /// Serial Port / UART related types. |
@@ -340,6 +363,49 @@ impl<'a> From<&'a [u8]> for ApiByteSlice<'a> { |
340 | 363 | } |
341 | 364 | } |
342 | 365 |
|
| 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 | + |
343 | 409 | impl<'a> ApiString<'a> { |
344 | 410 | /// Create a new string slice we can send over the FFI. |
345 | 411 | pub fn new(s: &'a str) -> ApiString<'a> { |
|
0 commit comments