33use 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
1741impl 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