Skip to content

Commit 2b074c7

Browse files
Add support for reading/writing OS config.
1 parent 07c8e47 commit 2b074c7

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@
1212
# Our uncompressed disk image
1313
disk.img
1414

15+
# This where you should store your OS config
16+
nvram.dat

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Build and run this BIOS (and use it to boot Neotron OS) with...
2828
```console
2929
~ $ git checkout https://github.com/neotron-compute/Neotron-Desktop-BIOS.git
3030
~ $ cd Neotron-Desktop-BIOS
31-
~/Neotron-Desktop-BIOS $ RUST_LOG=debug cargo run -- --serial=/dev/ttyS0 --peripheral=sdmmc,./disk.img --os=./libneotron_os.so
31+
~/Neotron-Desktop-BIOS $ RUST_LOG=debug cargo run -- --config=./nvram.dat --os=./libneotron_os.so
3232
```
3333

3434
Press `Esc` with the GUI window selected to quit the BIOS.

src/main.rs

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
// ===========================================================================
2929

3030
use std::io::prelude::*;
31-
use std::sync::atomic::{AtomicU32, AtomicU8, Ordering};
31+
use std::path::PathBuf;
32+
use std::sync::{
33+
atomic::{AtomicU32, AtomicU8, Ordering},
34+
mpsc, Mutex,
35+
};
3236

3337
use clap::Parser;
3438
use common::video::RGBColour;
@@ -47,7 +51,7 @@ struct MyApp {
4751
mode: common::video::Mode,
4852
font8x16: Vec<TextureId>,
4953
font8x8: Vec<TextureId>,
50-
sender: std::sync::mpsc::Sender<AppEvent>,
54+
sender: mpsc::Sender<AppEvent>,
5155
}
5256

5357
#[derive(Debug, PartialEq, Eq)]
@@ -68,10 +72,13 @@ struct Framebuffer<const N: usize> {
6872
struct Args {
6973
/// Path to the OS library
7074
#[arg(long)]
71-
os: std::path::PathBuf,
75+
os: PathBuf,
7276
/// Path to a file to use as a disk image
7377
#[arg(long)]
74-
disk: Option<std::path::PathBuf>,
78+
disk: Option<PathBuf>,
79+
/// Path to NVRAM file
80+
#[arg(long)]
81+
nvram: Option<PathBuf>,
7582
}
7683

7784
/// All our emulated hardware
@@ -99,7 +106,7 @@ static FRAMEBUFFER: Framebuffer<{ 640 * 480 }> = Framebuffer::new();
99106
const SCALE_FACTOR: f32 = 2.0;
100107

101108
/// When we booted up
102-
static HARDWARE: std::sync::Mutex<Option<Hardware>> = std::sync::Mutex::new(None);
109+
static HARDWARE: Mutex<Option<Hardware>> = Mutex::new(None);
103110

104111
/// The functions we export to the OS
105112
static BIOS_API: common::Api = common::Api {
@@ -673,8 +680,11 @@ static PALETTE: [AtomicU32; 256] = [
673680

674681
static VIDEO_MODE: AtomicU8 = AtomicU8::new(0);
675682

676-
static EV_QUEUE: std::sync::Mutex<Option<std::sync::mpsc::Receiver<AppEvent>>> =
677-
std::sync::Mutex::new(None);
683+
/// HID events come from here
684+
static EV_QUEUE: Mutex<Option<mpsc::Receiver<AppEvent>>> = Mutex::new(None);
685+
686+
/// Where the OS config is read from or written to.
687+
static CONFIG_FILE_PATH: Mutex<Option<PathBuf>> = Mutex::new(None);
678688

679689
// ===========================================================================
680690
// Macros
@@ -722,15 +732,14 @@ fn main() {
722732
}
723733

724734
// Process args
725-
let mut lib = None;
726-
for arg in std::env::args() {
727-
if let Some(os_path) = arg.strip_prefix("--os=") {
728-
info!("Loading OS from {:?}", os_path);
729-
lib = unsafe { Some(libloading::Library::new(os_path).expect("library to load")) };
730-
println!("Loaded!");
731-
}
735+
info!("Loading OS from: {}", args.os.display());
736+
let lib = unsafe { libloading::Library::new(args.os).expect("library to load") };
737+
println!("Loaded!");
738+
739+
if let Some(config_path) = args.nvram {
740+
info!("Loading OS config from: {}", config_path.display());
741+
*CONFIG_FILE_PATH.lock().unwrap() = Some(config_path);
732742
}
733-
let lib = lib.expect("Fetching --os=filename from args");
734743

735744
// Make a window
736745
let mut engine = Engine::builder()
@@ -740,7 +749,7 @@ fn main() {
740749
.target_frame_rate(60)
741750
.build()
742751
.unwrap();
743-
let (sender, receiver) = std::sync::mpsc::channel();
752+
let (sender, receiver) = mpsc::channel();
744753
let mut app = MyApp {
745754
mode: unsafe { common::video::Mode::from_u8(0) },
746755
font8x16: Vec::new(),
@@ -883,17 +892,43 @@ extern "C" fn time_clock_set(time: common::Time) {
883892
/// Configuration data is, to the BIOS, just a block of bytes of a given
884893
/// length. How it stores them is up to the BIOS - it could be EEPROM, or
885894
/// battery-backed SRAM.
886-
extern "C" fn configuration_get(_buffer: common::FfiBuffer) -> common::ApiResult<usize> {
887-
debug!("configuration_get()");
888-
Err(common::Error::Unimplemented).into()
895+
extern "C" fn configuration_get(mut os_buffer: common::FfiBuffer) -> common::ApiResult<usize> {
896+
let file_path = CONFIG_FILE_PATH.lock().unwrap().clone();
897+
let Some(os_buffer) = os_buffer.as_mut_slice() else {
898+
return common::ApiResult::Err(common::Error::DeviceError(0));
899+
};
900+
match file_path.as_ref() {
901+
Some(path) => match std::fs::read(path) {
902+
Ok(read_data) => {
903+
for (src, dest) in read_data.iter().zip(os_buffer.iter_mut()) {
904+
*dest = *src;
905+
}
906+
common::ApiResult::Ok(read_data.len())
907+
}
908+
Err(_e) => {
909+
println!("Failed to get config from {:?}", path);
910+
common::ApiResult::Err(common::Error::DeviceError(0))
911+
}
912+
},
913+
None => common::ApiResult::Err(common::Error::Unimplemented),
914+
}
889915
}
890916

891917
/// Set the configuration data block.
892918
///
893919
/// See `configuration_get`.
894-
extern "C" fn configuration_set(_buffer: common::FfiByteSlice) -> common::ApiResult<()> {
895-
debug!("configuration_set()");
896-
Err(common::Error::Unimplemented).into()
920+
extern "C" fn configuration_set(buffer: common::FfiByteSlice) -> common::ApiResult<()> {
921+
let file_path = CONFIG_FILE_PATH.lock().unwrap().clone();
922+
match file_path.as_ref() {
923+
Some(path) => match std::fs::write(path, buffer.as_slice()) {
924+
Ok(_) => common::ApiResult::Ok(()),
925+
Err(_e) => {
926+
println!("Failed to write config to {:?}", path);
927+
common::ApiResult::Err(common::Error::DeviceError(0))
928+
}
929+
},
930+
None => common::ApiResult::Err(common::Error::Unimplemented),
931+
}
897932
}
898933

899934
/// Does this Neotron BIOS support this video mode?

0 commit comments

Comments
 (0)