Skip to content

Commit

Permalink
Merge pull request #83 from Neotron-Compute/release/v0.7.0
Browse files Browse the repository at this point in the history
Release/v0.7.0
  • Loading branch information
thejpster committed Oct 21, 2023
2 parents 1ed1f70 + 97614ac commit 90c5e32
Show file tree
Hide file tree
Showing 21 changed files with 554 additions and 206 deletions.
29 changes: 19 additions & 10 deletions CHANGELOG.md
@@ -1,10 +1,19 @@
# Change Log

## Unreleased changes
## Unreleased changes ([Source](https://github.com/neotron-compute/neotron-os/tree/develop) | [Changes](https://github.com/neotron-compute/neotron-os/compare/v0.7.0...develop))

* None

## v0.6.0 (2023-10-08, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.6.0))
## v0.7.0 - 2023-10-21 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.7.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.7.0))

* Add `i2c` command.
* Support printing `\t`, with 8 character tab-stops
* Add `type` command to print files
* Add `exec` command to execute scripts containing commands
* Update `embedded-sdmmc` crate
* Split `lshw` into `lsblk`, `lsbus`, `lsi2c`, `lsmem` and `lsuart`

## v0.6.0 - 2023-10-08 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.6.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.6.0))

* Can set/set video mode
* Stores video mode as part of config
Expand All @@ -13,7 +22,7 @@
* Added mixer command
* Switch to [`neotron-common-bios`] 0.11.1

## v0.5.0 (2023-07-21, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.5.0))
## v0.5.0 - 2023-07-21 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.5.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.5.0))

* Switch to [`neotron-common-bios`] 0.11
* Added "Shutdown" command
Expand All @@ -22,31 +31,31 @@
* Use new compare-and-swap BIOS API to implement mutexes, instead of `static mut`
* OS now requires 256K Flash space

## v0.4.0 (2023-06-25, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.4.0))
## v0.4.0 - 2023-06-25 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.4.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.4.0))

* The `load` command now takes ELF binaries, not raw binaries.
* Neotron OS can now be used as a dependency within an application, if desired.

## v0.3.3 (2023-05-22, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.3))
## v0.3.3 - 2023-05-22 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.3.3) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.3))

* Add `dir` command
* Change `load` command to load from disk
* Repository includes `Cargo.lock` file
* Update to `postcard` 1.0
* Fix `readblk` help text, and print 32 bytes per line

## v0.3.2 (2023-05-05, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.2))
## v0.3.2 - 2023-05-05 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.3.2) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.2))

* Add `date` command.
* Add `lsblk` and `blkread` commands.
* Renamed `bioshw` to `lshw`

## v0.3.1 (2023-03-09, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.1))
## v0.3.1 - 2023-03-09 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.3.1) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.1))

* Add `hexdump`, `load` and `run` commands.
* Set colour attributes correctly (White on Black only currently)

## v0.3.0 (2023-02-12, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.0))
## v0.3.0 - 2023-02-12 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.3.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.3.0))

* Updated to [`neotron-common-bios`] v0.8.0
* Use [`pc-keyboard`] for decoding HID events
Expand All @@ -59,10 +68,10 @@
[`neotron-common-bios`]: https://crates.io/crates/neotron-common-bios
[`pc-keyboard`]: https://crates.io/crates/pc-keyboard

## v0.2.0 (2023-01-07, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.2.0))
## v0.2.0 - 2023-01-07 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.2.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.2.0))

Adds HID support and basic shell, with 'mem' and 'fill' commands.

## v0.1.0 (2022-03-18, [Github Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.1.0))
## v0.1.0 - 2022-03-18 ([Source](https://github.com/neotron-compute/neotron-os/tree/v0.1.0) | [Release](https://github.com/neotron-compute/neotron-os/releases/tag/v0.1.0))

First version.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "neotron-os"
version = "0.6.0"
version = "0.7.0"
authors = [
"Jonathan 'theJPster' Pallant <github@thejpster.org.uk>",
"The Neotron Developers"
Expand Down Expand Up @@ -49,7 +49,7 @@ postcard = "1.0"
serde = { version = "1.0", default-features = false }
menu = "0.3"
chrono = { version = "0.4", default-features = false }
embedded-sdmmc = { version = "0.5", default-features = false }
embedded-sdmmc = { version = "0.6", default-features = false }
neotron-api = "0.1"
neotron-loader = "0.1"
vte = "0.12"
Expand Down
2 changes: 2 additions & 0 deletions build.rs
Expand Up @@ -31,3 +31,5 @@ fn main() {
println!("cargo:rustc-link-lib=dylib=msvcrt");
}
}

// End of file
2 changes: 2 additions & 0 deletions src/bin/flash0002.rs
Expand Up @@ -14,3 +14,5 @@
#[link_section = ".entry_point"]
#[used]
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

// End of file
2 changes: 2 additions & 0 deletions src/bin/flash0802.rs
Expand Up @@ -14,3 +14,5 @@
#[link_section = ".entry_point"]
#[used]
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

// End of file
2 changes: 2 additions & 0 deletions src/bin/flash1002.rs
Expand Up @@ -14,3 +14,5 @@
#[link_section = ".entry_point"]
#[used]
pub static ENTRY_POINT_ADDR: extern "C" fn(&neotron_common_bios::Api) -> ! = neotron_os::os_main;

// End of file
63 changes: 6 additions & 57 deletions src/commands/block.rs
@@ -1,16 +1,8 @@
//! Block Device related commands for Neotron OS

use super::{parse_u64, parse_u8};
use crate::{bios, osprint, osprintln, Ctx, API};

pub static LSBLK_ITEM: menu::Item<Ctx> = menu::Item {
item_type: menu::ItemType::Callback {
function: lsblk,
parameters: &[],
},
command: "lsblk",
help: Some("List all the Block Devices"),
};

pub static READ_ITEM: menu::Item<Ctx> = menu::Item {
item_type: menu::ItemType::Callback {
function: read_block,
Expand All @@ -29,66 +21,21 @@ pub static READ_ITEM: menu::Item<Ctx> = menu::Item {
help: Some("Display one disk block, as hex"),
};

/// Called when the "lsblk" command is executed.
fn lsblk(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
let api = API.get();
let mut found = false;

osprintln!("Block Devices:");
for dev_idx in 0..=255u8 {
if let bios::FfiOption::Some(device_info) = (api.block_dev_get_info)(dev_idx) {
let (bsize, bunits, dsize, dunits) =
match device_info.num_blocks * u64::from(device_info.block_size) {
x if x < (1024 * 1024 * 1024) => {
// Under 1 GiB, give it in 10s of MiB
(10 * x / (1024 * 1024), "MiB", x / 100_000, "MB")
}
x => {
// Anything else in GiB
(10 * x / (1024 * 1024 * 1024), "GiB", x / 100_000_000, "GB")
}
};
osprintln!("Device {}:", dev_idx);
osprintln!(" Name: {}", device_info.name);
osprintln!(" Type: {:?}", device_info.device_type);
osprintln!(" Block size: {}", device_info.block_size);
osprintln!(" Num Blocks: {}", device_info.num_blocks);
osprintln!(
" Card Size: {}.{} {} ({}.{} {})",
bsize / 10,
bsize % 10,
bunits,
dsize / 10,
dsize % 10,
dunits
);
osprintln!(" Ejectable: {}", device_info.ejectable);
osprintln!(" Removable: {}", device_info.removable);
osprintln!(" Media Present: {}", device_info.media_present);
osprintln!(" Read Only: {}", device_info.read_only);
found = true;
}
}
if !found {
osprintln!(" None");
}
}

/// Called when the "read_block" command is executed.
fn read_block(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], _ctx: &mut Ctx) {
let api = API.get();
let Ok(dev_idx) = args[0].parse::<u8>() else {
let Ok(device_idx) = parse_u8(args[0]) else {
osprintln!("Couldn't parse {:?}", args[0]);
return;
};
let Ok(block_idx) = args[1].parse::<u64>() else {
let Ok(block_idx) = parse_u64(args[1]) else {
osprintln!("Couldn't parse {:?}", args[1]);
return;
};
osprintln!("Reading block {}:", block_idx);
let mut buffer = [0u8; 512];
match (api.block_read)(
dev_idx,
device_idx,
bios::block_dev::BlockIdx(block_idx),
1,
bios::FfiBuffer::new(&mut buffer),
Expand All @@ -110,3 +57,5 @@ fn read_block(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], _
}
}
}

// End of file
2 changes: 2 additions & 0 deletions src/commands/config.rs
Expand Up @@ -106,3 +106,5 @@ fn command(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx:
}
}
}

// End of file
105 changes: 100 additions & 5 deletions src/commands/fs.rs
@@ -1,7 +1,5 @@
//! File Systems related commands for Neotron OS

use embedded_sdmmc::VolumeIdx;

use crate::{bios, osprint, osprintln, Ctx};

pub static DIR_ITEM: menu::Item<Ctx> = menu::Item {
Expand All @@ -25,6 +23,30 @@ pub static LOAD_ITEM: menu::Item<Ctx> = menu::Item {
help: Some("Load a file into the application area"),
};

pub static EXEC_ITEM: menu::Item<Ctx> = menu::Item {
item_type: menu::ItemType::Callback {
function: exec,
parameters: &[menu::Parameter::Mandatory {
parameter_name: "file",
help: Some("The shell script to run"),
}],
},
command: "exec",
help: Some("Execute a shell script"),
};

pub static TYPE_ITEM: menu::Item<Ctx> = menu::Item {
item_type: menu::ItemType::Callback {
function: typefn,
parameters: &[menu::Parameter::Mandatory {
parameter_name: "file",
help: Some("The file to type"),
}],
},
command: "type",
help: Some("Type a file to the console"),
};

/// Called when the "dir" command is executed.
fn dir(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
fn work() -> Result<(), embedded_sdmmc::Error<bios::Error>> {
Expand All @@ -33,11 +55,11 @@ fn dir(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &
let time = crate::fs::BiosTime();
let mut mgr = embedded_sdmmc::VolumeManager::new(bios_block, time);
// Open the first partition
let volume = mgr.get_volume(VolumeIdx(0))?;
let root_dir = mgr.open_root_dir(&volume)?;
let volume = mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
let root_dir = mgr.open_root_dir(volume)?;
let mut total_bytes = 0u64;
let mut num_files = 0;
mgr.iterate_dir(&volume, &root_dir, |dir_entry| {
mgr.iterate_dir(root_dir, |dir_entry| {
let padding = 8 - dir_entry.name.base_name().len();
for b in dir_entry.name.base_name() {
let ch = *b as char;
Expand Down Expand Up @@ -99,3 +121,76 @@ fn load(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &m
}
}
}

/// Called when the "exec" command is executed.
fn exec(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &mut Ctx) {
fn work(ctx: &mut Ctx, filename: &str) -> Result<(), embedded_sdmmc::Error<bios::Error>> {
let bios_block = crate::fs::BiosBlock();
let time = crate::fs::BiosTime();
let mut mgr = embedded_sdmmc::VolumeManager::new(bios_block, time);
// Open the first partition
let volume = mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
let root_dir = mgr.open_root_dir(volume)?;
let file = mgr.open_file_in_dir(root_dir, filename, embedded_sdmmc::Mode::ReadOnly)?;
let buffer = ctx.tpa.as_slice_u8();
let count = mgr.read(file, buffer)?;
if count != mgr.file_length(file)? as usize {
osprintln!("File too large! Max {} bytes allowed.", buffer.len());
return Ok(());
}
let Ok(s) = core::str::from_utf8(&buffer[0..count]) else {
osprintln!("File is not valid UTF-8");
return Ok(());
};
// tell the main loop to run from these bytes next
ctx.exec_tpa = Some(s.len());
Ok(())
}

// index can't panic - we always have enough args
let r = work(ctx, args[0]);
match r {
Ok(_) => {}
Err(e) => {
osprintln!("Error: {:?}", e);
}
}
}

/// Called when the "type" command is executed.
fn typefn(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, args: &[&str], ctx: &mut Ctx) {
fn work(ctx: &mut Ctx, filename: &str) -> Result<(), embedded_sdmmc::Error<bios::Error>> {
let bios_block = crate::fs::BiosBlock();
let time = crate::fs::BiosTime();
let mut mgr = embedded_sdmmc::VolumeManager::new(bios_block, time);
// Open the first partition
let volume = mgr.open_volume(embedded_sdmmc::VolumeIdx(0))?;
let root_dir = mgr.open_root_dir(volume)?;
let file = mgr.open_file_in_dir(root_dir, filename, embedded_sdmmc::Mode::ReadOnly)?;
let buffer = ctx.tpa.as_slice_u8();
let count = mgr.read(file, buffer)?;
if count != mgr.file_length(file)? as usize {
osprintln!("File too large! Max {} bytes allowed.", buffer.len());
return Ok(());
}
let Ok(s) = core::str::from_utf8(&buffer[0..count]) else {
osprintln!("File is not valid UTF-8");
return Ok(());
};
osprintln!("{}", s);
Ok(())
}

// index can't panic - we always have enough args
let r = work(ctx, args[0]);
// reset SGR
osprint!("\u{001b}[0m");
match r {
Ok(_) => {}
Err(e) => {
osprintln!("Error: {:?}", e);
}
}
}

// End of file

0 comments on commit 90c5e32

Please sign in to comment.