SYS_EXIT, RUN command

Added ability to RUN a PGX file and the SYS_EXIT call.
This commit is contained in:
Peter Weingartner 2021-09-30 13:39:39 -04:00
parent ee4d8db4fa
commit a3dab23bac
27 changed files with 6471 additions and 6235 deletions

3
.gitignore vendored
View file

@ -50,3 +50,6 @@ modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
samples/HelloPGX/hello.pgx
samples/HelloPGX/hello.pgx
samples/HelloPGX/hello.lst

View file

@ -7,28 +7,32 @@ F00:0006
F00:0007 dc.b "PGX", $02 F00:0007 dc.b "PGX", $02
S01:00010000: 50 47 58 S01:00010000: 50 47 58
S01:00010003: 02 S01:00010003: 02
F00:0008 dc.l _start F00:0008 dc.l start
S01:00010004: 00 01 00 08 S01:00010004: 00 01 00 08
F00:0009 F00:0009
F00:0010 _start: move.l #_greet_end-_greet+1,d3 ; Length of the message F00:0010 start: move.l #$13,d0 ; sys_chan_write
S01:00010008: 76 0E S01:00010008: 70 13
F00:0011 move.l #_greet,d2 ; Pointer to the message F00:0011 clr.l d1 ; Channel #0
S01:0001000A: 24 3C 00 01 00 18 S01:0001000A: 72 00
F00:0012 clr.l d1 ; Write to channel #0 (main screen) F00:0012 move.l #greet,d2 ; Pointer to message
S01:00010010: 72 00 S01:0001000C: 24 3C 00 01 00 1C
F00:0013 move.l #$14,d0 ; sys_chan_write_b F00:0013 move.l #greet_end-greet+1,d3 ; Length of message
S01:00010012: 70 14 S01:00010012: 76 0E
F00:0014 trap #15 ; Call it F00:0014 trap #15
S01:00010014: 4E 4F S01:00010014: 4E 4F
F00:0015 F00:0015
F00:0016 _lock: bra _lock F00:0016 done: clr.l d0 ; sys_exit
S01:00010016: 60 FE S01:00010016: 70 00
F00:0017 F00:0017 clr.l d1 ; Return value = 0
F00:0018 _greet: dc.b "Hello, world!" S01:00010018: 72 00
S01:00010018: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21 F00:0018 trap #15
F00:0019 _greet_end: dc.b 0 S01:0001001A: 4E 4F
S01:00010025: 00 F00:0019
F00:0020 F00:0020 greet: dc.b "Hello, world!"
S01:0001001C: 48 65 6C 6C 6F 2C 20 77 6F 72 6C 64 21
F00:0021 greet_end: dc.b 0
S01:00010029: 00
F00:0022
Sections: Sections:
@ -40,14 +44,14 @@ F00 hello.s
Symbols: Symbols:
_lock EXPR(65558=0x10016) ABS done EXPR(65558=0x10016) UNUSED ABS
_greet EXPR(65560=0x10018) ABS greet_end EXPR(65577=0x10029) ABS
_greet_end EXPR(65573=0x10025) ABS greet EXPR(65564=0x1001c) ABS
_start EXPR(65544=0x10008) ABS start EXPR(65544=0x10008) ABS
_MOVEMBYTES EXPR(0=0x0) INTERNAL _MOVEMBYTES EXPR(0=0x0) INTERNAL
MOVEMSIZE EXPR(0=0x0) INTERNAL MOVEMSIZE EXPR(0=0x0) INTERNAL
_MOVEMREGS EXPR(0=0x0) INTERNAL _MOVEMREGS EXPR(0=0x0) INTERNAL
__LINE__ EXPR(20=0x14) INTERNAL __LINE__ EXPR(22=0x16) INTERNAL
__FO EXPR(0=0x0) INTERNAL __FO EXPR(0=0x0) INTERNAL
__RS EXPR(0=0x0) INTERNAL __RS EXPR(0=0x0) INTERNAL
REPTN EXPR(-1=0xffffffff) INTERNAL REPTN EXPR(-1=0xffffffff) INTERNAL

Binary file not shown.

View file

@ -5,15 +5,17 @@
org $010000 org $010000
dc.b "PGX", $02 dc.b "PGX", $02
dc.l _start dc.l start
_start: move.l #_greet_end-_greet+1,d3 ; Length of the message start: move.l #$13,d0 ; sys_chan_write
move.l #_greet,d2 ; Pointer to the message clr.l d1 ; Channel #0
clr.l d1 ; Write to channel #0 (main screen) move.l #greet,d2 ; Pointer to message
move.l #$14,d0 ; sys_chan_write_b move.l #greet_end-greet+1,d3 ; Length of message
trap #15 ; Call it trap #15
_lock: bra _lock done: clr.l d0 ; sys_exit
clr.l d1 ; Return value = 0
trap #15
_greet: dc.b "Hello, world!" greet: dc.b "Hello, world!"
_greet_end: dc.b 0 greet_end: dc.b 0

View file

@ -21,7 +21,8 @@ export MODEL=4
export AS = vasmm68k_mot export AS = vasmm68k_mot
export ASFLAGS = -quiet -Fvobj -nowarn=62 export ASFLAGS = -quiet -Fvobj -nowarn=62
export CC = vc export CC = vc
export CFLAGS = +../vbcc/config/m68k-foenix -I. -Iinclude -DCPU=$(CPU) -DMODEL=$(MODEL) export DEFINES = -DCPU=$(CPU) -DMODEL=$(MODEL) -DKBD_POLLED=1
export CFLAGS = +../vbcc/config/m68k-foenix -I. -Iinclude
export RM = cmd /C del /Q /F export RM = cmd /C del /Q /F
cpu = m68k cpu = m68k
@ -60,7 +61,7 @@ cli:
$(MAKE) --directory=cli $(MAKE) --directory=cli
foenixmcp.s68: $(c_obj) $(cpu) dev fatfs snd cli foenixmcp.s68: $(c_obj) $(cpu) dev fatfs snd cli
$(CC) $(CFLAGS) -o foenixmcp.s68 $(c_obj) $(cpu_c_obj) $(dev_c_obj) $(fat_c_obj) $(snd_c_obj) $(cli_c_obj) $(CC) $(CFLAGS) $(DEFINES) -o foenixmcp.s68 $(c_obj) $(cpu_c_obj) $(dev_c_obj) $(fat_c_obj) $(snd_c_obj) $(cli_c_obj)
%.o: %.c $(DEPS) %.o: %.c $(DEPS)
$(CC) -S -c -o $@ $< $(CFLAGS) $(CC) -S -c -o $@ $< $(CFLAGS)

View file

@ -7,7 +7,7 @@ cobjects = $(subst .c,.o,$(csources))
all: $(cobjects) all: $(cobjects)
%.o: %.c %.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS) $(DEFINES)
.PHONY: clean .PHONY: clean

View file

@ -27,27 +27,10 @@ typedef struct s_cli_command {
} t_cli_command, *p_cli_command; } t_cli_command, *p_cli_command;
/* /*
* Commands * Variables
*/ */
extern const t_cli_command g_cli_commands[]; short g_current_channel = 0;
//
// List all the commands
//
int cmd_help(short channel, int argc, char * argv[]) {
p_cli_command command;
for (command = g_cli_commands; (command != 0) && (command->name != 0); command++) {
sys_chan_write(channel, command->help, strlen(command->help));
sys_chan_write(channel, "\n", 2);
}
return 0;
}
//
// CLI variables
//
const t_cli_command g_cli_commands[] = { const t_cli_command g_cli_commands[] = {
{ "?", "? -- print this helpful message", cmd_help }, { "?", "? -- print this helpful message", cmd_help },
@ -61,10 +44,24 @@ const t_cli_command g_cli_commands[] = {
{ "POKE8", "POKE8 <address> <value> -- write the byte value to the address in memory", mem_cmd_poke8}, { "POKE8", "POKE8 <address> <value> -- write the byte value to the address in memory", mem_cmd_poke8},
{ "POKE16", "POKE16 <address> <value> -- write the 16-bit word value to the address in memory", mem_cmd_poke16}, { "POKE16", "POKE16 <address> <value> -- write the 16-bit word value to the address in memory", mem_cmd_poke16},
{ "POKE32", "POKE32 <address> <value> -- write the 32-bit long word value to the address in memory", mem_cmd_poke32}, { "POKE32", "POKE32 <address> <value> -- write the 32-bit long word value to the address in memory", mem_cmd_poke32},
{ "RUN", "RUN <path> -- execute a binary file", cmd_run },
{ "TYPE", "TYPE <path> -- print the contents of a text file", cmd_type }, { "TYPE", "TYPE <path> -- print the contents of a text file", cmd_type },
{ 0, 0 } { 0, 0 }
}; };
//
// List all the commands
//
int cmd_help(short channel, int argc, char * argv[]) {
p_cli_command command;
for (command = g_cli_commands; (command != 0) && (command->name != 0); command++) {
sys_chan_write(channel, command->help, strlen(command->help));
sys_chan_write(channel, "\n", 2);
}
return 0;
}
// //
// Attempt to execute a command // Attempt to execute a command
// //
@ -126,6 +123,12 @@ char * strtok_r(char * source, const char * delimiter, char ** saveptr) {
return x; return x;
} }
short cli_rerepl() {
while (1) {
cli_repl(g_current_channel);
}
}
// //
// Enter the CLI's read-eval-print loop // Enter the CLI's read-eval-print loop
// //
@ -137,8 +140,7 @@ short cli_repl(short channel) {
int argc = 0; int argc = 0;
char * argv[MAX_ARGC]; char * argv[MAX_ARGC];
const char * welcome = "\n\nFoenix/MCP Command Line Utility... online.\nType \"HELP\" or \"?\" for help.\n\n"; g_current_channel = channel;
sys_chan_write(channel, welcome, strlen(welcome));
while (1) { while (1) {
sys_chan_write(channel, "\n> ", 3); // Print our prompt sys_chan_write(channel, "\n> ", 3); // Print our prompt

View file

@ -39,4 +39,9 @@ extern short cli_repl(short channel);
*/ */
extern long cli_eval_number(const char * arg); extern long cli_eval_number(const char * arg);
/*
* Print a help message
*/
extern int cmd_help(short channel, int argc, char * argv[]);
#endif #endif

View file

@ -5,11 +5,24 @@
#include "log.h" #include "log.h"
#include "simpleio.h" #include "simpleio.h"
#include "cli.h" #include "cli.h"
#include "proc.h"
#include "cli/dos_cmds.h" #include "cli/dos_cmds.h"
#include "dev/block.h" #include "dev/block.h"
#include "dev/fsys.h" #include "dev/fsys.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
short cmd_run(short screen, int argc, char * argv[]) {
TRACE("cmd_run");
if (argc > 1) {
short result = proc_run(argv[1]);
if (result < 0) {
log_num(LOG_ERROR, "Unable to run: ", result);
return result;
}
}
}
short cmd_dir(short screen, int argc, char * argv[]) { short cmd_dir(short screen, int argc, char * argv[]) {
t_file_info my_file; t_file_info my_file;
char * path = ""; char * path = "";

View file

@ -5,6 +5,11 @@
#ifndef __DOS_CMDS_H #ifndef __DOS_CMDS_H
#define __DOS_CMDS_H #define __DOS_CMDS_H
/*
* Execute a binary file
*/
extern short cmd_run(short screen, int argc, char * argv[]);
/* /*
* List the directory at the given path * List the directory at the given path
*/ */

View file

@ -7,7 +7,7 @@ cobjects = $(subst .c,.o,$(csources))
all: $(cobjects) all: $(cobjects)
%.o: %.c %.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS) $(DEFINES)
.PHONY: clean .PHONY: clean

View file

@ -278,6 +278,8 @@ short chan_write_b(short channel, uint8_t b) {
p_dev_chan cdev; p_dev_chan cdev;
short res; short res;
TRACE("chan_write_b");
res = chan_get_records(channel, &chan, &cdev); res = chan_get_records(channel, &chan, &cdev);
if (res == 0) { if (res == 0) {
return cdev->write_b(chan, b); return cdev->write_b(chan, b);

View file

@ -35,7 +35,11 @@ short con_write_b(p_channel chan, uint8_t b) {
short con_read_b(p_channel chan) { short con_read_b(p_channel chan) {
char c; char c;
do { do {
#ifdef KBD_POLLED
c = kbdmo_getc_poll();
#else
c = kbdmo_getc(); c = kbdmo_getc();
#endif
} while (c == 0); } while (c == 0);
// Echo the character to the screen // Echo the character to the screen

View file

@ -221,7 +221,9 @@ short kbdmo_init() {
int_register(INT_KBD_A2560K, kbdmo_handle_irq); int_register(INT_KBD_A2560K, kbdmo_handle_irq);
/* Enable the interrupt for the keyboard */ /* Enable the interrupt for the keyboard */
#ifndef KBD_POLLED
int_enable(INT_KBD_A2560K); int_enable(INT_KBD_A2560K);
#endif
return 0; return 0;
} }

View file

@ -7,7 +7,7 @@ cobjects = $(subst .c,.o,$(csources))
all: $(cobjects) all: $(cobjects)
%.o: %.c %.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS) $(DEFINES)
.PHONY: clean .PHONY: clean

View file

@ -96,7 +96,7 @@ void initialize() {
text_init(); // Initialize the text channels text_init(); // Initialize the text channels
DEBUG("Foenix/MCP starting up..."); DEBUG("Foenix/MCP starting up...");
log_setlevel(LOG_VERBOSE); log_setlevel(LOG_ERROR);
/* Initialize the interrupt system */ /* Initialize the interrupt system */
int_init(); int_init();
@ -174,50 +174,6 @@ void initialize() {
int_enable_all(); int_enable_all();
} }
// void try_mo_scancodes(short screen) {
// // volatile unsigned short * kbd_mo_data = ((volatile unsigned short *)0x00C00040);
// // volatile unsigned short * kbd_mo_stat = ((volatile unsigned short *)0x00C00042);
//
// print(screen, "mo> ");
//
// do {
// // unsigned short status = *kbd_mo_stat;
// // if ((status & KBD_MO_STAT_EMPTY) != KBD_MO_STAT_EMPTY) {
// // unsigned short data = *kbd_mo_data;
// // print(screen, "[");
// // print_hex_16(screen, status);
// // print(screen, "]: {");
// //
// // print_hex_16(screen, data);
// // print(screen, "}\n ");
// // // }
// // }
//
// unsigned short scancode = kbdmo_get_scancode_poll();
// if (scancode != 0) {
// print(screen, "[");
// print_hex_16(screen, scancode);
// print(screen, "]\n");
// }
//
// } while (1);
// }
// void try_mo_chars(short screen) {
// char buffer[2];
// buffer[1] = 0;
//
// print(screen, "mo> ");
//
// while (1) {
// unsigned char c = kbdmo_getc_poll();
// if (c) {
// // text_put_raw(screen, c);
// return;
// }
// }
// }
void uart_send(short uart, char * message) { void uart_send(short uart, char * message) {
int i, j; int i, j;
@ -380,14 +336,6 @@ int main(int argc, char * argv[]) {
print(CDEV_CONSOLE, "Text Channel A\n"); print(CDEV_CONSOLE, "Text Channel A\n");
print(CDEV_EVID, "Text Channel B\n"); print(CDEV_EVID, "Text Channel B\n");
print(CDEV_CONSOLE, "MASK_GRP1: ");
print_hex_16(CDEV_CONSOLE, *MASK_GRP1);
print(CDEV_CONSOLE, "\n");
print(CDEV_CONSOLE, "MASK_PEND1: ");
print_hex_16(CDEV_CONSOLE, *PENDING_GRP1);
print(CDEV_CONSOLE, "\n");
// uart_test_send(0); // uart_test_send(0);
/* Register a handler for the SOF interrupt and enable it */ /* Register a handler for the SOF interrupt and enable it */
@ -413,6 +361,9 @@ int main(int argc, char * argv[]) {
// } // }
// } // }
const char * welcome = "\n\nFoenix/MCP Command Line Utility... online.\nType \"HELP\" or \"?\" for help.\n\n";
sys_chan_write(0, welcome, strlen(welcome));
cli_repl(0); cli_repl(0);
DEBUG("Stopping."); DEBUG("Stopping.");

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
#ifndef __ERRORS_H #ifndef __ERRORS_H
#define __ERRORS_H #define __ERRORS_H
#define MAX_ERROR_NUMBER 15 // Largest (absolute value) of the error number #define MAX_ERROR_NUMBER 16 // Largest (absolute value) of the error number
#define ERR_GENERAL -1 // A general error condition #define ERR_GENERAL -1 // A general error condition
#define DEV_ERR_BADDEV -2 // Device number is bad (too big or no device assigned) #define DEV_ERR_BADDEV -2 // Device number is bad (too big or no device assigned)
@ -22,5 +22,5 @@
#define ERR_BAD_EXTENSION -13 // The path to load did not have an extension that matched registered loaders #define ERR_BAD_EXTENSION -13 // The path to load did not have an extension that matched registered loaders
#define ERR_OUT_OF_MEMORY -14 // Unable to allocate more memory #define ERR_OUT_OF_MEMORY -14 // Unable to allocate more memory
#define ERR_BAD_BINARY -15 // Bad binary file format... i.e. binary format does not match expectations #define ERR_BAD_BINARY -15 // Bad binary file format... i.e. binary format does not match expectations
#define ERR_NOT_EXECUTABLE -16 // Binary file format does not have a starting address
#endif #endif

View file

@ -53,7 +53,7 @@
// //
// #elif SYSTEM == SYS_FOENIX_A2560K // #elif SYSTEM == SYS_FOENIX_A2560K
#define PS2_STATUS ((unsigned char *)0x00C02064) #define PS2_STATUS ((unsigned char *)0x00C02064)
#define PS2_CMD_BUF ((unsigned char *)0x00C02060) #define PS2_CMD_BUF ((unsigned char *)0x00C02064)
#define PS2_OUT_BUF ((unsigned char *)0x00C02060) #define PS2_OUT_BUF ((unsigned char *)0x00C02060)
#define PS2_INPT_BUF ((unsigned char *)0x00C02060) #define PS2_INPT_BUF ((unsigned char *)0x00C02060)
#define PS2_DATA_BUF ((unsigned char *)0x00C02060) #define PS2_DATA_BUF ((unsigned char *)0x00C02060)

View file

@ -89,6 +89,18 @@ extern int32_t syscall(int32_t function, ...);
*** Core system calls *** Core system calls
***/ ***/
/*
* Quit the current user process
*
* NOTE: at the moment, this relaunches the CLI. In the future, this
* may cause execution to return to the program that started
* the user process.
*
* Inputs:
* result = the code to return to the kernel
*/
extern void sys_exit(int result);
/* /*
* Enable all interrupts * Enable all interrupts
* *

View file

@ -85,7 +85,7 @@ void log3(short level, char * message1, char * message2, char * message3) {
void log_num(short level, char * message, int n) { void log_num(short level, char * message, int n) {
if (level <= log_level) { if (level <= log_level) {
print(log_channel, message); print(log_channel, message);
print_hex_16(log_channel, n); print_hex_32(log_channel, n);
print_c(log_channel, '\n'); print_c(log_channel, '\n');
} }
} }

View file

@ -12,7 +12,7 @@ all: $(aobjects) $(cobjects)
$(AS) $(ASFLAGS) -o $@ $< $(AS) $(ASFLAGS) -o $@ $<
%.o: %.c %.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS) $(DEFINES)
.PHONY: clean .PHONY: clean

View file

@ -21,6 +21,7 @@ int32_t syscall_dispatch(int32_t function, int32_t param0, int32_t param1, int32
/* Core System Calls */ /* Core System Calls */
switch (function) { switch (function) {
case KFN_EXIT: case KFN_EXIT:
proc_exit((int)param0);
break; break;
case KFN_WARMBOOT: case KFN_WARMBOOT:

View file

@ -1,8 +1,12 @@
xref ___main xref ___main
xref _cli_rerepl
xdef _syscall xdef _syscall
xdef ___exit xdef ___exit
xdef _int_enable_all xdef _int_enable_all
xdef _int_disable_all xdef _int_disable_all
xdef _call_user
xdef _restart_cli
section "vectors",code section "vectors",code
@ -240,3 +244,22 @@ h_trap_15:
add.l #28,sp ; Remove parameters from the stack add.l #28,sp ; Remove parameters from the stack
rte ; Return to the caller rte ; Return to the caller
;
; Jump into a user mode code
;
; Inputs:
; a0 = pointer to code to execute
; a1 = location to set user stack pointer
;
_call_user:
move.l (4,a7),a0
move.l (8,a7),a1
andi #$dfff,sr ; Drop into user mode
movea.l a1,a7 ; Set the stack
jmp (a0)
_restart_cli:
lea ___STACK,sp
jsr _cli_rerepl
bra _restart_cli

File diff suppressed because it is too large Load diff

91
src/proc.c Normal file
View file

@ -0,0 +1,91 @@
/*
* Routines to support processes
*
* NOTE: at the moment, FoenixMCP is single tasking only, so there is only
* one "process" besides the kernel.
*
*/
#include "errors.h"
#include "log.h"
#include "dev/fsys.h"
static const long k_default_stack = 0x0000ffff; /* For now... we're just going to put the user stack under 0x00010000 */
static int g_proc_result;
/*
* Assembly routine: reset the supervisor stack pointer and restart the CLI
*/
extern void restart_cli();
extern void call_user(long start, long stack);
/*
* Start a user mode process
*
* Inputs:
* start = the address to start execution
* stack = the location to start the user mode stack
*/
void proc_exec(long start, long stack) {
TRACE("proc_exec");
log_num(LOG_INFO, "proc_exec start: ", start);
log_num(LOG_INFO, "proc_exec stack: ", stack);
g_proc_result = 0;
call_user(start, stack);
}
/*
* Quit the current user process
*
* NOTE: at the moment, this relaunches the CLI. In the future, this
* may cause execution to return to the program that started
* the user process.
*
* Inputs:
*/
void proc_exit(int result) {
g_proc_result = result;
restart_cli();
}
/*
* Return the result code of the previously running user process
*/
int proc_get_result() {
return g_proc_result;
}
/*
* Find an executable binary matching the path, load it, and execute it
*
* Inputs:
* path = the path to try to load
*
* Returns:
* returns an error code on failure, will not return on success
*/
short proc_run(const char * path) {
TRACE("proc_run");
/* TODO: allow for commands without extensions */
/* TODO: allow for a search PATH */
/* TODO: allocate stack more dynamically */
long start = 0;
short result = fsys_load(path, 0, &start);
if (result == 0) {
if (start != 0) {
proc_exec(start, k_default_stack);
} else {
log_num(LOG_ERROR, "Couldn't execute file: ", result);
return ERR_NOT_EXECUTABLE;
}
} else {
log_num(LOG_ERROR, "Couldn't load file: ", result);
return result;
}
}

48
src/proc.h Normal file
View file

@ -0,0 +1,48 @@
/*
* Routines to support processes
*
* NOTE: at the moment, FoenixMCP is single tasking only, so there is only
* one "process" besides the kernel.
*
*/
#ifndef __PROC_H
#define __PROC_H
/*
* Start a user mode process
*
* Inputs:
* start = the address to start execution
* stack = the location to start the user mode stack
*/
extern void proc_exec(long start, long stack);
/*
* Quit the current user process
*
* NOTE: at the moment, this relaunches the CLI. In the future, this
* may cause execution to return to the program that started
* the user process.
*
* Inputs:
*/
extern void proc_exit(int result);
/*
* Return the result code of the previously running user process
*/
extern int proc_get_result();
/*
* Find an executable binary matching the path, load it, and execute it
*
* Inputs:
* path = the path to try to load
*
* Returns:
* returns an error code on failure, will not return on success
*/
extern short proc_run(const char * path);
#endif