Skip to content

Commit 16102cb

Browse files
committed
Use latest API crate.
1 parent 74089ae commit 16102cb

File tree

4 files changed

+270
-11
lines changed

4 files changed

+270
-11
lines changed

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
[package]
22
name = "neotron-os"
33
version = "0.3.3"
4-
authors = ["Jonathan 'theJPster' Pallant <[email protected]>", "The Neotron Developers"]
4+
authors = [
5+
"Jonathan 'theJPster' Pallant <[email protected]>",
6+
"The Neotron Developers"
7+
]
58
edition = "2018"
69
description = "The Neotron Operating System"
710
license = "GPL-3.0-or-later"
@@ -46,3 +49,4 @@ serde = { version = "1.0", default-features = false }
4649
menu = "0.3"
4750
chrono = { version = "0.4", default-features = false }
4851
embedded-sdmmc = { version = "0.5", default-features = false }
52+
neotron-api = { path = "../neotron-api" }

src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,25 @@ impl Api {
131131
/// Represents the serial port we can use as a text input/output device.
132132
struct SerialConsole(u8);
133133

134+
impl SerialConsole {
135+
fn write_bstr(&mut self, data: &[u8]) -> core::fmt::Result {
136+
let api = API.get();
137+
let is_panic = IS_PANIC.load(Ordering::SeqCst);
138+
let res = (api.serial_write)(
139+
// Which port
140+
self.0,
141+
// Data
142+
bios::ApiByteSlice::new(data),
143+
// No timeout
144+
bios::Option::None,
145+
);
146+
if !is_panic {
147+
res.unwrap();
148+
}
149+
Ok(())
150+
}
151+
}
152+
134153
impl core::fmt::Write for SerialConsole {
135154
fn write_str(&mut self, data: &str) -> core::fmt::Result {
136155
let api = API.get();

src/program.rs

Lines changed: 225 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,29 @@
33
use crate::{print, println};
44

55
#[allow(unused)]
6-
static CALLBACK_TABLE: Api = Api { print: print_fn };
6+
static CALLBACK_TABLE: neotron_api::Api = neotron_api::Api {
7+
open: api_open,
8+
close: api_close,
9+
write: api_write,
10+
read: api_read,
11+
seek_set: api_seek_set,
12+
seek_cur: api_seek_cur,
13+
seek_end: api_seek_end,
14+
rename: api_rename,
15+
ioctl: api_ioctl,
16+
opendir: api_opendir,
17+
closedir: api_closedir,
18+
readdir: api_readdir,
19+
stat: api_stat,
20+
fstat: api_fstat,
21+
deletefile: api_deletefile,
22+
deletedir: api_deletedir,
23+
chdir: api_chdir,
24+
dchdir: api_dchdir,
25+
pwd: api_pwd,
26+
malloc: api_malloc,
27+
free: api_free,
28+
};
729

830
/// Ways in which loading a program can fail.
931
#[derive(Debug)]
@@ -12,6 +34,8 @@ pub enum Error {
1234
ProgramTooLarge,
1335
/// A filesystem error occurred
1436
Filesystem(embedded_sdmmc::Error<neotron_common_bios::Error>),
37+
/// Start Address didn't look right
38+
BadAddress(u32),
1539
}
1640

1741
impl From<embedded_sdmmc::Error<neotron_common_bios::Error>> for Error {
@@ -20,13 +44,6 @@ impl From<embedded_sdmmc::Error<neotron_common_bios::Error>> for Error {
2044
}
2145
}
2246

23-
#[allow(unused)]
24-
#[repr(C)]
25-
/// The API we give to applications.
26-
pub struct Api {
27-
pub print: extern "C" fn(data: *const u8, len: usize),
28-
}
29-
3047
/// Represents the Transient Program Area.
3148
///
3249
/// This is a piece of memory that can be used for loading and executing programs.
@@ -139,10 +156,31 @@ impl TransientProgramArea {
139156
/// of view of this API. You wanted to run a program, and the program was
140157
/// run.
141158
pub fn execute(&mut self) -> Result<i32, Error> {
159+
// Read start-ptr as a 32-bit value
142160
let application_ram = self.as_slice_u32();
143-
let start_ptr = application_ram[0] as *const ();
161+
let start_addr = application_ram[0];
162+
// But now we want RAM as u8 values, as start_ptr will be an odd number
163+
// because it's a Thumb2 address and that's a u16 aligned value, plus 1
164+
// to indicate Thumb2 mode.
165+
let application_ram = self.as_slice_u8();
166+
print!("Start address 0x{:08x}:", start_addr);
167+
// Does this start pointer look OK?
168+
if (start_addr & 1) != 1 {
169+
println!("not thumb2 func");
170+
return Err(Error::BadAddress(start_addr));
171+
}
172+
if !application_ram
173+
.as_ptr_range()
174+
.contains(&(start_addr as *const u8))
175+
{
176+
println!("out of bounds");
177+
return Err(Error::BadAddress(start_addr));
178+
}
179+
println!("OK!");
180+
drop(application_ram);
144181
let result = unsafe {
145-
let code: extern "C" fn(*const Api) -> i32 = ::core::mem::transmute(start_ptr);
182+
let code: extern "C" fn(*const neotron_api::Api) -> i32 =
183+
::core::mem::transmute(start_addr);
146184
code(&CALLBACK_TABLE)
147185
};
148186
Ok(result)
@@ -160,6 +198,183 @@ extern "C" fn print_fn(data: *const u8, len: usize) {
160198
}
161199
}
162200

201+
/// Open a file, given a path as UTF-8 string.
202+
///
203+
/// If the file does not exist, or is already open, it returns an error.
204+
///
205+
/// Path may be relative to current directory, or it may be an absolute
206+
/// path.
207+
extern "C" fn api_open(
208+
_path: neotron_api::FfiString,
209+
_flags: neotron_api::file::Flags,
210+
) -> neotron_api::Result<neotron_api::file::Handle> {
211+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
212+
}
213+
214+
/// Close a previously opened file.
215+
extern "C" fn api_close(_fd: neotron_api::file::Handle) -> neotron_api::Result<()> {
216+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
217+
}
218+
219+
/// Write to an open file handle, blocking until everything is written.
220+
///
221+
/// Some files do not support writing and will produce an error.
222+
extern "C" fn api_write(
223+
fd: neotron_api::file::Handle,
224+
buffer: neotron_api::FfiByteSlice,
225+
) -> neotron_api::Result<()> {
226+
if fd == neotron_api::file::Handle::new_stdout() {
227+
if let Some(ref mut console) = unsafe { &mut crate::VGA_CONSOLE } {
228+
console.write_bstr(buffer.as_slice());
229+
}
230+
if let Some(ref mut console) = unsafe { &mut crate::SERIAL_CONSOLE } {
231+
if let Err(_e) = console.write_bstr(buffer.as_slice()) {
232+
return neotron_api::Result::Err(neotron_api::Error::DeviceSpecific);
233+
}
234+
}
235+
neotron_api::Result::Ok(())
236+
} else {
237+
neotron_api::Result::Err(neotron_api::Error::BadHandle)
238+
}
239+
}
240+
241+
/// Read from an open file, returning how much was actually read.
242+
///
243+
/// If you hit the end of the file, you might get less data than you asked for.
244+
extern "C" fn api_read(
245+
_fd: neotron_api::file::Handle,
246+
_buffer: neotron_api::FfiBuffer,
247+
) -> neotron_api::Result<usize> {
248+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
249+
}
250+
251+
/// Move the file offset (for the given file handle) to the given position.
252+
///
253+
/// Some files do not support seeking and will produce an error.
254+
extern "C" fn api_seek_set(
255+
_fd: neotron_api::file::Handle,
256+
_position: u64,
257+
) -> neotron_api::Result<()> {
258+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
259+
}
260+
261+
/// Move the file offset (for the given file handle) relative to the current position
262+
///
263+
/// Some files do not support seeking and will produce an error.
264+
extern "C" fn api_seek_cur(
265+
_fd: neotron_api::file::Handle,
266+
_offset: i64,
267+
) -> neotron_api::Result<u64> {
268+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
269+
}
270+
271+
/// Move the file offset (for the given file handle) to the end of the file
272+
///
273+
/// Some files do not support seeking and will produce an error.
274+
extern "C" fn api_seek_end(_fd: neotron_api::file::Handle) -> neotron_api::Result<u64> {
275+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
276+
}
277+
278+
/// Rename a file
279+
extern "C" fn api_rename(
280+
_old_path: neotron_api::FfiString,
281+
_new_path: neotron_api::FfiString,
282+
) -> neotron_api::Result<()> {
283+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
284+
}
285+
286+
/// Perform a special I/O control operation.
287+
extern "C" fn api_ioctl(
288+
_fd: neotron_api::file::Handle,
289+
_command: u64,
290+
_value: u64,
291+
) -> neotron_api::Result<u64> {
292+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
293+
}
294+
295+
/// Open a directory, given a path as a UTF-8 string.
296+
extern "C" fn api_opendir(
297+
_path: neotron_api::FfiString,
298+
) -> neotron_api::Result<neotron_api::dir::Handle> {
299+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
300+
}
301+
302+
/// Close a previously opened directory.
303+
extern "C" fn api_closedir(_dir: neotron_api::dir::Handle) -> neotron_api::Result<()> {
304+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
305+
}
306+
307+
/// Read from an open directory
308+
extern "C" fn api_readdir(
309+
_dir: neotron_api::dir::Handle,
310+
) -> neotron_api::Result<neotron_api::dir::Entry> {
311+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
312+
}
313+
314+
/// Get information about a file
315+
extern "C" fn api_stat(
316+
_path: neotron_api::FfiString,
317+
) -> neotron_api::Result<neotron_api::file::Stat> {
318+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
319+
}
320+
321+
/// Get information about an open file
322+
extern "C" fn api_fstat(
323+
_fd: neotron_api::file::Handle,
324+
) -> neotron_api::Result<neotron_api::file::Stat> {
325+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
326+
}
327+
328+
/// Delete a file.
329+
///
330+
/// If the file is currently open this will give an error.
331+
extern "C" fn api_deletefile(_path: neotron_api::FfiString) -> neotron_api::Result<()> {
332+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
333+
}
334+
335+
/// Delete a directory
336+
///
337+
/// If the directory has anything in it, this will give an error.
338+
extern "C" fn api_deletedir(_path: neotron_api::FfiString) -> neotron_api::Result<()> {
339+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
340+
}
341+
342+
/// Change the current directory
343+
///
344+
/// Relative file paths are taken to be relative to the current directory.
345+
///
346+
/// Unlike on MS-DOS, there is only one current directory for the whole
347+
/// system, not one per drive.
348+
extern "C" fn api_chdir(_path: neotron_api::FfiString) -> neotron_api::Result<()> {
349+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
350+
}
351+
352+
/// Change the current directory to the open directory
353+
///
354+
/// Relative file paths are taken to be relative to the current directory.
355+
///
356+
/// Unlike on MS-DOS, there is only one current directory for the whole
357+
/// system, not one per drive.
358+
extern "C" fn api_dchdir(_dir: neotron_api::dir::Handle) -> neotron_api::Result<()> {
359+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
360+
}
361+
362+
/// Obtain the current working directory.
363+
extern "C" fn api_pwd(_path: neotron_api::FfiBuffer) -> neotron_api::Result<usize> {
364+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
365+
}
366+
367+
/// Allocate some memory
368+
extern "C" fn api_malloc(
369+
_size: usize,
370+
_alignment: usize,
371+
) -> neotron_api::Result<*mut core::ffi::c_void> {
372+
neotron_api::Result::Err(neotron_api::Error::Unimplemented)
373+
}
374+
375+
/// Free some previously allocated memory
376+
extern "C" fn api_free(_ptr: *mut core::ffi::c_void, _size: usize, _alignment: usize) {}
377+
163378
// ===========================================================================
164379
// End of file
165380
// ===========================================================================

0 commit comments

Comments
 (0)