News:
* Multi-process management * Many syscall implementations * Sheared object creation * Fix process creation * Fix process return Implemented syscall list: * wait * waitpid * _exit * getpid * getppid * getpgid * setpgid Bugs found (but not fixed): * TTY cursor drawing crash. * Loader relocatable sections management (unable to load the file) * Loader relocatable sections management (symbols not relocalized, crash)
This commit is contained in:
parent
2f34cf4d48
commit
97fb770fe1
|
@ -23,6 +23,14 @@ struct tty_s
|
|||
char **output;
|
||||
} buffers;
|
||||
|
||||
// Window size informations used by the write primitive
|
||||
struct {
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
} winsize;
|
||||
|
||||
// Cursor informations
|
||||
struct {
|
||||
int16_t x;
|
||||
|
|
|
@ -64,7 +64,8 @@ struct casio_smem_fragment_s
|
|||
uint16_t data_block_id; // ID of blocks containing data for this fragment
|
||||
uint16_t data_offset; // offset of fragment data in the given block
|
||||
|
||||
// WARNING : the size is (real_size-1), so *do not forget* to add 1 to
|
||||
// WARNING :
|
||||
// The size is (real_size-1), so *do not forget* to add 1 to
|
||||
// have the real size of data!
|
||||
uint16_t data_size; // size of this fragment data
|
||||
|
||||
|
@ -75,6 +76,7 @@ struct casio_smem_fragment_s
|
|||
typedef struct casio_smem_block_s smemfs_sector_t;
|
||||
typedef struct casio_smem_header_s smemfs_inode_t;
|
||||
typedef struct casio_smem_fragment_s smemfs_fragdata_t;
|
||||
typedef struct casio_smem_header_s smemfs_header_t;
|
||||
|
||||
|
||||
// Define internal superblock
|
||||
|
|
|
@ -22,22 +22,17 @@ struct process
|
|||
// Used when interrupt or exception occur
|
||||
//---
|
||||
struct {
|
||||
uint32_t kernel;
|
||||
uint32_t user;
|
||||
void *kernel;
|
||||
void *user;
|
||||
} stack;
|
||||
|
||||
|
||||
//---
|
||||
// Context management
|
||||
//---
|
||||
common_context_t context;
|
||||
|
||||
|
||||
//---
|
||||
// Private data
|
||||
//---
|
||||
char name[PROCESS_NAME_LENGHT];
|
||||
|
||||
|
||||
//---
|
||||
// Shared (child / parent) data informations
|
||||
//---
|
||||
|
@ -51,11 +46,12 @@ struct process
|
|||
struct dentry *working_dir;
|
||||
FILE tty;
|
||||
|
||||
|
||||
//---
|
||||
// Signals management.
|
||||
//---
|
||||
//sighandler_t signal[NSIG];
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// Virtual / Physical memory management.
|
||||
|
@ -67,20 +63,20 @@ struct process
|
|||
//---
|
||||
struct {
|
||||
struct {
|
||||
uint32_t user;
|
||||
uint32_t kernel;
|
||||
void *user;
|
||||
void *kernel;
|
||||
struct {
|
||||
uint32_t user;
|
||||
uint32_t kernel;
|
||||
size_t user;
|
||||
size_t kernel;
|
||||
} size;
|
||||
} stack;
|
||||
struct {
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
void *start;
|
||||
size_t size;
|
||||
} program;
|
||||
struct {
|
||||
uint32_t start;
|
||||
uint32_t size;
|
||||
void *start;
|
||||
size_t size;
|
||||
} exit;
|
||||
} memory;
|
||||
|
||||
|
@ -89,35 +85,43 @@ struct process
|
|||
// Other process management.
|
||||
//---
|
||||
struct process *parent;
|
||||
struct process *sibling;
|
||||
struct process *child;
|
||||
|
||||
|
||||
//---
|
||||
// Private data
|
||||
//---
|
||||
// Process ID
|
||||
pid_t pid;
|
||||
pid_t pgid;
|
||||
|
||||
// Indicate process status
|
||||
enum {
|
||||
PROC_INIT,
|
||||
PROC_RUNNING,
|
||||
PROC_SLEEP,
|
||||
PROC_STOP,
|
||||
PROC_ZOMBIE,
|
||||
PROC_DEAD
|
||||
} status;
|
||||
|
||||
// Used to by the _exit() syscall
|
||||
uint32_t __stat_loc;
|
||||
|
||||
// Used by the allocator
|
||||
struct process *next;
|
||||
};
|
||||
|
||||
|
||||
// Internal struct used by the
|
||||
// static process stack
|
||||
struct process_stack
|
||||
{
|
||||
// Indicate process slot status
|
||||
enum {
|
||||
PROC_USED,
|
||||
PROC_UNUSED
|
||||
} status;
|
||||
|
||||
// Internal process data
|
||||
struct process process;
|
||||
};
|
||||
|
||||
|
||||
// Functions.
|
||||
extern struct process *process_create(const char *name);
|
||||
extern struct process *process_get(pid_t pid);
|
||||
extern pid_t process_get_pid(struct process *process);
|
||||
extern struct process *process_create(void);
|
||||
extern int process_switch(pid_t pid);
|
||||
|
||||
|
||||
// Internal function.
|
||||
extern pid_t process_alloc(struct process **process);
|
||||
// Internals
|
||||
extern struct process *process_alloc(void);
|
||||
extern struct process *process_get(pid_t pid);
|
||||
extern int process_free(struct process *process);
|
||||
|
||||
#endif /*__KERNEL_PROCESS_H__*/
|
||||
|
|
|
@ -5,15 +5,12 @@
|
|||
#include <stddef.h>
|
||||
#include <kernel/util/types.h>
|
||||
|
||||
//---
|
||||
//
|
||||
// Vhex part !!
|
||||
//
|
||||
//---
|
||||
// Process
|
||||
extern pid_t sys_fork(void);
|
||||
extern pid_t sys_getpid(void);
|
||||
extern pid_t sys_getppid(void);
|
||||
extern pid_t sys_getpgid(void);
|
||||
extern pid_t sys_wait(int *wstatus);
|
||||
extern int sys_setpgid(pid_t pid, pid_t pgid);
|
||||
extern pid_t sys_waitpid(pid_t pid, int *wstatus, int options);
|
||||
extern pid_t sys_fexecve(const char *pathname);
|
||||
extern void sys_exit(int status);
|
||||
|
|
|
@ -26,12 +26,9 @@ typedef enum mpu_e
|
|||
MPU_UNKNOWN,
|
||||
} mpu_t;
|
||||
|
||||
typedef int pid_t;
|
||||
typedef int32_t pid_t;
|
||||
typedef int16_t mode_t;
|
||||
typedef uint16_t dev_t;
|
||||
typedef uint16_t umode_t;
|
||||
|
||||
// Force inline function.
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
|
||||
#endif /*__TYPES_H__*/
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef __KERNEL_UNISTD_32_H__
|
||||
# define __KERNEL_UNISTD_32_H__
|
||||
|
||||
// Define the number of syscall
|
||||
#define __NR_MAX 14
|
||||
|
||||
// Kernel Test
|
||||
#define __NR_test_syscall 0
|
||||
|
||||
|
@ -8,27 +11,17 @@
|
|||
#define __NR_exit 1
|
||||
#define __NR_fexecve 2
|
||||
#define __NR_waitpid 3
|
||||
#define __NR_wait 4
|
||||
#define __NR_getpid 5
|
||||
#define __NR_getppid 6
|
||||
#define __NR_getpgid 7
|
||||
#define __NR_setpgid 8
|
||||
|
||||
// VFS
|
||||
#define __NR_read 4
|
||||
#define __NR_write 5
|
||||
#define __NR_open 6
|
||||
#define __NR_close 7
|
||||
#define __NR_lseek 8
|
||||
|
||||
//--
|
||||
// Custom !
|
||||
//--
|
||||
|
||||
// Display
|
||||
#define __NR_kvram_display 9
|
||||
#define __NR_kvram_clear 10
|
||||
#define __NR_kvram_print 11
|
||||
#define __NR_kvram_ascii 12
|
||||
#define __NR_kvram_reverse 13
|
||||
#define __NR_kvram_scroll 14
|
||||
#define __NR_kvram_clr_str_area 15
|
||||
|
||||
//TODO: keyboard
|
||||
#define __NR_read 9
|
||||
#define __NR_write 10
|
||||
#define __NR_open 11
|
||||
#define __NR_close 12
|
||||
#define __NR_lseek 13
|
||||
|
||||
#endif /*__KERNEL_UNISTD_32_H__*/
|
||||
|
|
|
@ -17,6 +17,16 @@
|
|||
#define WNOHANG 0
|
||||
#define WUNTRACED 1
|
||||
#define WCONTINUED 2
|
||||
|
||||
//TODO: move me
|
||||
#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig))
|
||||
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
|
||||
#define WEXITSTATUS(status) __WEXITSTATUS(status)
|
||||
|
||||
extern pid_t getpid(void);
|
||||
extern pid_t getpgid(void);
|
||||
extern pid_t getppid(void);
|
||||
extern int setpgid(pid_t pid, pid_t pgid);
|
||||
extern pid_t waitpid(pid_t pid, int *wstatus, int options);
|
||||
extern pid_t fexecve(const char *pathname);
|
||||
|
||||
|
|
|
@ -76,18 +76,18 @@ static void rom_explore(volatile void *rom, int32_t size)
|
|||
while (size >= 0)
|
||||
{
|
||||
unused = *(volatile uint8_t*)rom;
|
||||
rom = (void*)((uint32_t)rom + 1024);
|
||||
size = size - 1024;
|
||||
rom = rom + 1024;
|
||||
}
|
||||
}
|
||||
|
||||
/* section_execute() - Used to execute contructors and destructors */
|
||||
static void section_execute(void *bsection, void *esection)
|
||||
{
|
||||
while ((uintptr_t)bsection < (uintptr_t)esection)
|
||||
while (bsection < esection)
|
||||
{
|
||||
((void (*)(void))*((uint32_t*)bsection))();
|
||||
bsection = (void*)((uint32_t)bsection + 4);
|
||||
((void (*)(void))*((void**)bsection))();
|
||||
bsection = bsection + sizeof(void (*)(void));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,9 +107,7 @@ int start(void)
|
|||
// Check MPU hardware.
|
||||
current_mpu = mpu_get();
|
||||
if (current_mpu != MPU_SH7305)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Execute constructor.
|
||||
section_execute(&bctors, &ectors);
|
||||
|
@ -169,8 +167,8 @@ int start(void)
|
|||
vfs_mkdir("/dev", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
vfs_mkdir("/home", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
vfs_mkdir("/mnt", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
vfs_mkdir("/mnt/smemfs", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL);
|
||||
vfs_mkdir("/mnt/casio", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
vfs_mount(NULL, "/mnt/casio", "smemfs", /*MS_RDONLY*/0, NULL);
|
||||
|
||||
// Add devices
|
||||
earlyterm_write("Add devices...\n");
|
||||
|
@ -182,24 +180,10 @@ int start(void)
|
|||
// Start first process !
|
||||
//---
|
||||
|
||||
// Create first process: Vhex.
|
||||
//earlyterm_write("Create first process...\n");
|
||||
//struct process *vhex_process = process_create("Vhex");
|
||||
/*if (vhex_process == NULL)
|
||||
{
|
||||
earlyterm_clear();
|
||||
earlyterm_write("Vhex fatal error !\n");
|
||||
earlyterm_write("First process error !\n");
|
||||
earlyterm_write("Press [MENU] key...\n");
|
||||
while (1) { __asm__ volatile ("sleep"); }
|
||||
}*/
|
||||
|
||||
// Load programe.
|
||||
//vhex_process->context.spc = (uint32_t)loader("/mnt/smemfs/VHEX/shell.elf", vhex_process);
|
||||
//if (vhex_process->context.spc == 0x00000000)
|
||||
earlyterm_write("Create first process...\n");
|
||||
struct process *vhex_process = process_create("Vhex");
|
||||
if (vhex_process == NULL || loader(vhex_process, "/mnt/smemfs/VHEX/shell.elf") != 0)
|
||||
struct process *vhex_process = process_create();
|
||||
if (vhex_process == NULL || loader(vhex_process, "/mnt/casio/VHEX/shell.elf") != 0)
|
||||
{
|
||||
// Display message.
|
||||
earlyterm_clear();
|
||||
|
@ -208,8 +192,8 @@ int start(void)
|
|||
if (vhex_process->context.spc == 0xffffffff)
|
||||
earlyterm_write("process_create() error\n");
|
||||
else
|
||||
earlyterm_write("File \"VHEX/shell.elf\" not found !");
|
||||
earlyterm_write("Press [MENU key]...");
|
||||
earlyterm_write("File \"VHEX/shell.elf\" not found !\n");
|
||||
earlyterm_write("Press [MENU key]...\n");
|
||||
|
||||
// Restore Casio context.
|
||||
fx9860_context_restore(&casio_context);
|
||||
|
|
|
@ -26,6 +26,12 @@ void *tty_open(dev_t major, dev_t minor)
|
|||
return (NULL);
|
||||
}
|
||||
|
||||
// Generate "visible" informations for the write primitive
|
||||
tty->winsize.ws_xpixel = screen_get(SCREEN_WIDTH);
|
||||
tty->winsize.ws_ypixel = screen_get(SCREEN_HEIGHT);
|
||||
tty->winsize.ws_col = tty->winsize.ws_xpixel / (tty->disp.font->font.width + 1);
|
||||
tty->winsize.ws_row = tty->winsize.ws_ypixel / (tty->disp.font->font.height + 1);
|
||||
|
||||
// Generate formated output buffer indicator
|
||||
tty->cursor.max.x = screen_get(SCREEN_WIDTH) / (tty->disp.font->font.width + 1);
|
||||
tty->cursor.max.y = screen_get(SCREEN_HEIGHT) / (tty->disp.font->font.height + 1);
|
||||
|
|
|
@ -90,6 +90,7 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
|
|||
return (keyboard.buffer.clen);
|
||||
}
|
||||
|
||||
//TODO: move me
|
||||
static int check_signal(struct keyboard_obj_s *keyboard, key_t key)
|
||||
{
|
||||
//TODO
|
||||
|
@ -98,111 +99,103 @@ static int check_signal(struct keyboard_obj_s *keyboard, key_t key)
|
|||
return (0);
|
||||
}
|
||||
|
||||
// TODO: move me
|
||||
// TODO: update me
|
||||
static int check_special(struct keyboard_obj_s *keyboard, key_t key)
|
||||
{
|
||||
extern fx9860_context_t casio_context;
|
||||
extern fx9860_context_t vhex_context;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
// Check MAJ.
|
||||
case KEY_ALPHA:
|
||||
{
|
||||
keyboard->mode = keyboard->mode ^ 0x02;
|
||||
return (1);
|
||||
}
|
||||
if (key == KEY_ALPHA) {
|
||||
keyboard->mode = keyboard->mode ^ 0x02;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check Alpha / num mode.
|
||||
case KEY_SHIFT:
|
||||
{
|
||||
keyboard->mode = keyboard->mode ^ 0x01;
|
||||
return (1);
|
||||
}
|
||||
// Check Alpha / num mode.
|
||||
if (key == KEY_SHIFT) {
|
||||
keyboard->mode = keyboard->mode ^ 0x01;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check DEL key.
|
||||
case KEY_DEL:
|
||||
{
|
||||
// Check potential error.
|
||||
if (keyboard->buffer.cursor <= 0)
|
||||
return (1);
|
||||
|
||||
// Move seconde part.
|
||||
memcpy(
|
||||
&keyboard->buffer.addr[keyboard->buffer.cursor - 1],
|
||||
&keyboard->buffer.addr[keyboard->buffer.cursor],
|
||||
keyboard->buffer.clen - keyboard->buffer.cursor
|
||||
);
|
||||
|
||||
// Add null char and update clen.
|
||||
keyboard->buffer.clen = keyboard->buffer.clen - 1;
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
|
||||
if (key == KEY_DEL)
|
||||
{
|
||||
// Check potential error.
|
||||
if (keyboard->buffer.cursor <= 0)
|
||||
return (1);
|
||||
}
|
||||
// Move seconde part.
|
||||
memcpy(
|
||||
&keyboard->buffer.addr[keyboard->buffer.cursor - 1],
|
||||
&keyboard->buffer.addr[keyboard->buffer.cursor],
|
||||
keyboard->buffer.clen - keyboard->buffer.cursor
|
||||
);
|
||||
|
||||
// Check MENU key.
|
||||
// TODO: fix me !
|
||||
case KEY_MENU:
|
||||
{
|
||||
// Save current Vhex context and restore Casio's context.
|
||||
atomic_start();
|
||||
fx9860_context_save(&vhex_context);
|
||||
fx9860_context_restore(&casio_context);
|
||||
atomic_stop();
|
||||
// Add null char and update clen.
|
||||
keyboard->buffer.clen = keyboard->buffer.clen - 1;
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Inject MENU key and call GetKey().
|
||||
// TODO !!!
|
||||
//int row = 0;
|
||||
//int column = 0;
|
||||
//uint16_t keymatrix = 0x0308;
|
||||
//casio_Bkey_PutKeymatrix(&keymatrix);
|
||||
//casio_GetKeyWait(&row, &column, 0, 0, 0, &key);
|
||||
casio_GetKey(&key);
|
||||
// Check MENU key.
|
||||
// TODO: fix me !
|
||||
if (key == KEY_MENU)
|
||||
{
|
||||
// Save current Vhex context and restore Casio's context.
|
||||
atomic_start();
|
||||
fx9860_context_save(&vhex_context);
|
||||
fx9860_context_restore(&casio_context);
|
||||
atomic_stop();
|
||||
|
||||
// Inject MENU key and call GetKey().
|
||||
// TODO !!!
|
||||
//casio_GetKeyWait(&row, &column, 0, 0, 0, &key);
|
||||
casio_GetKey(&key);
|
||||
|
||||
// Save current Casio's context and restore Vhex's context.
|
||||
atomic_start();
|
||||
fx9860_context_save(&casio_context);
|
||||
fx9860_context_restore(&vhex_context);
|
||||
atomic_stop();
|
||||
return (1);
|
||||
}
|
||||
// Save current Casio's context and restore Vhex's context.
|
||||
atomic_start();
|
||||
fx9860_context_save(&casio_context);
|
||||
fx9860_context_restore(&vhex_context);
|
||||
atomic_stop();
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check EXE key.
|
||||
case KEY_EXE:
|
||||
{
|
||||
// Add new line character.
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\n';
|
||||
keyboard->buffer.clen = keyboard->buffer.clen + 1;
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
|
||||
// Check EXE key.
|
||||
if (key == KEY_EXE)
|
||||
{
|
||||
// Add new line character.
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\n';
|
||||
keyboard->buffer.clen = keyboard->buffer.clen + 1;
|
||||
keyboard->buffer.addr[keyboard->buffer.clen] = '\0';
|
||||
|
||||
// indicate that the EXE has been pressed.
|
||||
keyboard->mode = keyboard->mode | 0x04;
|
||||
// indicate that the EXE has been pressed.
|
||||
keyboard->mode = keyboard->mode | 0x04;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check LEFT key.
|
||||
if (key == KEY_LEFT)
|
||||
{
|
||||
// Check potential error.
|
||||
if (keyboard->buffer.cursor <= 0)
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check LEFT key.
|
||||
case KEY_LEFT:
|
||||
{
|
||||
// Check potential error.
|
||||
if (keyboard->buffer.cursor <= 0)
|
||||
return (1);
|
||||
// Move cursor.
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Move cursor.
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor - 1;
|
||||
// Check RIGHT key.
|
||||
if (key == KEY_RIGHT)
|
||||
{
|
||||
// Check limit
|
||||
if (keyboard->buffer.cursor >= keyboard->buffer.clen)
|
||||
return (1);
|
||||
}
|
||||
|
||||
// Check RIGHT key.
|
||||
case KEY_RIGHT:
|
||||
{
|
||||
if (keyboard->buffer.cursor >= keyboard->buffer.clen)
|
||||
return (1);
|
||||
|
||||
// Move cursor.
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor + 1;
|
||||
return (1);
|
||||
}
|
||||
default: break;
|
||||
// Move cursor.
|
||||
keyboard->buffer.cursor = keyboard->buffer.cursor + 1;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
@ -323,12 +316,13 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
|
|||
y = y * (keyboard->tty->disp.font->font.height + 1);
|
||||
|
||||
// Display cursor.
|
||||
dreverse(
|
||||
/* dreverse(
|
||||
&keyboard->tty->disp, x, y,
|
||||
(keyboard->tty->disp.font->font.width + 1),
|
||||
(keyboard->tty->disp.font->font.height + 1)
|
||||
);
|
||||
(*screen_update)(keyboard->tty->disp.vram);
|
||||
*/
|
||||
|
||||
// Restore TTY cursor position
|
||||
keyboard->tty->cursor.x = sttyx;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
static void tty_vertical_update(struct tty_s *tty)
|
||||
{
|
||||
// Get next line.
|
||||
if (tty->cursor.y + 1 <= tty->cursor.max.y)
|
||||
if (tty->cursor.y + 1 < tty->cursor.max.y)
|
||||
tty->cursor.y = tty->cursor.y + 1;
|
||||
else
|
||||
tty->cursor.y = 0;
|
||||
|
@ -117,7 +117,7 @@ static void tty_display(struct tty_s *tty)
|
|||
// @note: circular buffer.
|
||||
line = 0;
|
||||
start = tty->cursor.y;
|
||||
while (++line < tty->cursor.max.y)
|
||||
while (++line < tty->winsize.ws_row)
|
||||
{
|
||||
// Update check line.
|
||||
saved_start = start;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <kernel/fs/smemfs.h>
|
||||
#include <kernel/fs/file.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
|
@ -13,51 +14,64 @@ static void *casio_smem_get_data_base_address(smemfs_fragdata_t *fragment)
|
|||
while (block->magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC &&
|
||||
block->info.id != fragment->data_block_id)
|
||||
{
|
||||
block = block + 1;
|
||||
block = &block[1];
|
||||
}
|
||||
if (block->info.id != fragment->data_block_id)
|
||||
return (NULL);
|
||||
return ((void *)(uint32_t)(block->offset + fragment->data_offset));
|
||||
return ((void *)(block->offset + fragment->data_offset));
|
||||
}
|
||||
|
||||
/* casio_smem_read() - Read the file data (based on internal cursor) */
|
||||
ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos)
|
||||
{
|
||||
smemfs_fragdata_t *fragment;
|
||||
smemfs_header_t *header;
|
||||
off_t fragment_data_offset;
|
||||
void *data_base_addr;
|
||||
ssize_t current_size;
|
||||
size_t current_size;
|
||||
size_t real_size;
|
||||
|
||||
// Get Check obvious error.
|
||||
if (inode == NULL || buf == NULL)
|
||||
return (-1);
|
||||
|
||||
// Check file type
|
||||
header = inode;
|
||||
if (header->info != CASIO_SMEM_HEADER_INFO_EXIST ||
|
||||
header->type != CASIO_SMEM_HEADER_TYPE_FILE) {
|
||||
earlyterm_write("smemfs: header error !\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Get the current data fragment.
|
||||
current_size = 0;
|
||||
fragment = (void *)((uint32_t)inode + sizeof(struct casio_smem_header_s));
|
||||
fragment = inode + sizeof(struct casio_smem_header_s);
|
||||
while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC &&
|
||||
pos > (off_t)(current_size + fragment->data_size + 1))
|
||||
fragment->info == CASIO_SMEM_FRAGMENT_INFO_EXIST &&
|
||||
(off_t)(current_size + fragment->data_size + 1) < pos)
|
||||
{
|
||||
current_size = current_size + fragment->data_size + 1;
|
||||
fragment = fragment + 1;
|
||||
fragment = &fragment[1];
|
||||
}
|
||||
|
||||
// Check fragment error
|
||||
if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC)
|
||||
if (fragment->magic != CASIO_SMEM_FRAGMENT_MAGIC ||
|
||||
fragment->info != CASIO_SMEM_FRAGMENT_INFO_EXIST)
|
||||
{
|
||||
atomic_stop();
|
||||
earlyterm_write("smemfs: fragment error !\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Read file data
|
||||
current_size = 0;
|
||||
fragment_data_offset = pos - current_size;
|
||||
while (current_size < (ssize_t)count &&
|
||||
fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
|
||||
while (current_size < count &&
|
||||
fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC &&
|
||||
fragment->info == CASIO_SMEM_FRAGMENT_INFO_EXIST)
|
||||
{
|
||||
// Calculate the real size to read.
|
||||
real_size = fragment->data_size + 1 - fragment_data_offset;
|
||||
|
@ -72,16 +86,16 @@ ssize_t smemfs_read(void *inode, void *buf, size_t count, off_t pos)
|
|||
// Handle fragment data offset.
|
||||
if (fragment_data_offset != 0)
|
||||
{
|
||||
data_base_addr = (void *)(((uint32_t)data_base_addr) + fragment_data_offset);
|
||||
data_base_addr = data_base_addr + fragment_data_offset;
|
||||
fragment_data_offset = 0;
|
||||
}
|
||||
|
||||
// Fill the buffer
|
||||
memcpy((void*)(buf + current_size), (void*)(0xa0000000 + data_base_addr), real_size);
|
||||
memcpy(buf + current_size, (void*)(0xa0000000 + data_base_addr), real_size);
|
||||
|
||||
// Update informations.
|
||||
current_size = current_size + real_size;
|
||||
fragment = fragment + 1;
|
||||
fragment = &fragment[1];
|
||||
}
|
||||
|
||||
// Stop atomic operation
|
||||
|
|
|
@ -3,37 +3,34 @@
|
|||
/* smemfs_walk() - Find inode based on directory ID and flags */
|
||||
/* @note: This function is internal of smemFS, do not call it ! */
|
||||
smemfs_inode_t *smemfs_walk(smemfs_inode_t *current,
|
||||
smemfs_inode_t *entry, uint16_t folder_id, int flags)
|
||||
smemfs_inode_t *file, uint16_t folder_id, int flags)
|
||||
{
|
||||
smemfs_fragdata_t *fragdata;
|
||||
|
||||
// Check current inode validity.
|
||||
if (entry == NULL)
|
||||
if (file == NULL)
|
||||
return (NULL);
|
||||
|
||||
// Walk entry
|
||||
while (entry->info == CASIO_SMEM_HEADER_INFO_EXIST ||
|
||||
entry->info == CASIO_SMEM_HEADER_INFO_DELETE)
|
||||
// Walk file
|
||||
while (file->info == CASIO_SMEM_HEADER_INFO_EXIST ||
|
||||
file->info == CASIO_SMEM_HEADER_INFO_DELETE)
|
||||
{
|
||||
// New inode validity check.
|
||||
if (entry != current &&
|
||||
entry->info == CASIO_SMEM_HEADER_INFO_EXIST &&
|
||||
(((flags & WALK_FLAG_ID_CHECK_PARENT) != 0 && entry->parent.id == folder_id) ||
|
||||
((flags & WALK_FLAG_ID_CHECK_PARENT) == 0 && entry->id == folder_id)))
|
||||
if (file != current &&
|
||||
file->info == CASIO_SMEM_HEADER_INFO_EXIST &&
|
||||
(((flags & WALK_FLAG_ID_CHECK_PARENT) != 0 && file->parent.id == folder_id) ||
|
||||
((flags & WALK_FLAG_ID_CHECK_PARENT) == 0 && file->id == folder_id)))
|
||||
{
|
||||
return (entry);
|
||||
return (file);
|
||||
}
|
||||
|
||||
// Fast fragmentation skip
|
||||
fragdata = (void *)((uint32_t)(entry) + sizeof(struct casio_smem_header_s));
|
||||
fragdata = (void *)&file[1];
|
||||
if (fragdata->magic == CASIO_SMEM_FRAGMENT_MAGIC)
|
||||
{
|
||||
fragdata = (void *)((uint32_t)fragdata +
|
||||
(sizeof(struct casio_smem_fragment_s) * fragdata->frag_total));
|
||||
}
|
||||
fragdata = &fragdata[fragdata->frag_total];
|
||||
|
||||
// Update current inode
|
||||
entry = (void*)fragdata;
|
||||
file = (void*)fragdata;
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
// Check VFS validity
|
||||
if (vfs_root_node == NULL)
|
||||
{
|
||||
earlyterm_write("VFS root error !");
|
||||
earlyterm_write("VFS root error !\n");
|
||||
DBG_WAIT;
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -105,10 +105,10 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
next = vfs_dentry_find_next_sibling(next);
|
||||
if (next == NULL)
|
||||
{
|
||||
earlyterm_write("vfs_resolve(): sibling error !");
|
||||
earlyterm_write("* old next: %s$", tmp->name);
|
||||
earlyterm_write("* file: %s$", file->name);
|
||||
earlyterm_write("* name: %s$", name);
|
||||
earlyterm_write("vfs_resolve(): sibling error !\n");
|
||||
earlyterm_write("* old next: %s$\n", tmp->name);
|
||||
earlyterm_write("* file: %s$\n", file->name);
|
||||
earlyterm_write("* name: %s$\n", name);
|
||||
DBG_WAIT;
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
|
|||
if ((file->mode & __S_IFDIR) == 0)
|
||||
{
|
||||
// Debug !
|
||||
earlyterm_write("vfs_resolve(): dir error !");
|
||||
earlyterm_write("vfs_resolve(): dir error !\n");
|
||||
DBG_WAIT;
|
||||
return (NULL);
|
||||
}
|
||||
|
|
|
@ -11,13 +11,14 @@ int loader(struct process *process, const char *path)
|
|||
{
|
||||
Elf32_Ehdr header;
|
||||
FILE file;
|
||||
int err;
|
||||
|
||||
// Check error and try to open the file.
|
||||
if (process == NULL || vfs_open(&file, path, O_RDONLY) != 0)
|
||||
{
|
||||
earlyterm_write("loader: Fault error !");
|
||||
earlyterm_write("* path: %s$", path);
|
||||
earlyterm_write("* process: %p", process);
|
||||
earlyterm_write("loader: Fault error !\n");
|
||||
earlyterm_write("* path: %s$\n", path);
|
||||
earlyterm_write("* process: %p\n", process);
|
||||
DBG_WAIT;
|
||||
return (-1);
|
||||
}
|
||||
|
@ -25,25 +26,43 @@ int loader(struct process *process, const char *path)
|
|||
//@NOTE: Only ELF supported !!!
|
||||
// Get / Check ELF header
|
||||
// FIXME: return the file type (elf, g1a, bin, ...)
|
||||
if (loader_get_header(&file, &header) != 0)
|
||||
err = loader_get_header(&file, &header);
|
||||
if (err != 0)
|
||||
{
|
||||
earlyterm_write("loader: ELF file header error !");
|
||||
earlyterm_write("loader: ELF file header error ! (%d)\n", err);
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
return (-2);
|
||||
}
|
||||
|
||||
// Get / Check program validity
|
||||
if (loader_load_image(process, &file, &header) != 0)
|
||||
err = loader_load_image(process, &file, &header);
|
||||
if (err != 0)
|
||||
{
|
||||
earlyterm_write("loader: ELF file image error !");
|
||||
earlyterm_write("loader: ELF file image error ! (%d)\n", err);
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
return (-3);
|
||||
}
|
||||
|
||||
// Relocalise sections / symbols
|
||||
if (loader_reloc_sym(process, &file, &header) != 0)
|
||||
err = loader_reloc_sym(process, &file, &header);
|
||||
if (err != 0)
|
||||
{
|
||||
earlyterm_write("loader: ELF relo error !");
|
||||
earlyterm_write("loader: ELF relo error ! (%d)\n", err);
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
return (-4);
|
||||
}
|
||||
|
|
|
@ -19,18 +19,20 @@ int loader_get_header(FILE *file, Elf32_Ehdr *header)
|
|||
if (header->e_ident[EI_CLASS] != ELFCLASS32)
|
||||
return (-3);
|
||||
|
||||
//TODO: Check OSABI (?)
|
||||
// Check data encoding
|
||||
if (header->e_ident[EI_DATA] != ELFDATA2MSB)
|
||||
return (-4);
|
||||
|
||||
// Check ELF type.
|
||||
if (header->e_type != ET_DYN)
|
||||
return (-4);
|
||||
return (-5);
|
||||
|
||||
// Check ELF specifique instruction
|
||||
if (header->e_machine != EM_SH)
|
||||
return (-5);
|
||||
return (-6);
|
||||
|
||||
// Check ELF version
|
||||
if (header->e_version != EV_CURRENT)
|
||||
return (-6);
|
||||
return (-7);
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
|
||||
{
|
||||
Elf32_Phdr program;
|
||||
uint32_t paddress;
|
||||
void *paddress;
|
||||
uint16_t i;
|
||||
|
||||
// Walk one time to get program size and
|
||||
|
@ -31,7 +31,7 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
|
|||
|
||||
// Allocate programe space into
|
||||
// physical memory.
|
||||
process->memory.program.start = (uint32_t)pm_alloc(process->memory.program.size);
|
||||
process->memory.program.start = (void *)pm_alloc(process->memory.program.size);
|
||||
if (process->memory.program.start == 0x00000000)
|
||||
return (-3);
|
||||
|
||||
|
@ -49,11 +49,11 @@ int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
|
|||
|
||||
// p_filesz can be smaller than p_memsz so, we need to wipe the area
|
||||
// before the dump.
|
||||
memset((void *)paddress, 0, program.p_memsz);
|
||||
memset(paddress, 0, program.p_memsz);
|
||||
|
||||
// Dump the program.
|
||||
vfs_lseek(file, program.p_offset, SEEK_SET);
|
||||
vfs_read(file, (void *)paddress, program.p_filesz);
|
||||
vfs_read(file, paddress, program.p_filesz);
|
||||
}
|
||||
|
||||
// Generate program entry address
|
||||
|
|
|
@ -9,10 +9,14 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
|
|||
char *shstrtab;
|
||||
|
||||
// Get sections string header tables
|
||||
vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(shdr)), SEEK_SET);
|
||||
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
|
||||
earlyterm_write(
|
||||
"off_t = %#x\noff_t = %#x\n",
|
||||
header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)),
|
||||
vfs_lseek(file, header->e_shoff + (header->e_shstrndx * sizeof(Elf32_Shdr)), SEEK_SET)
|
||||
);;
|
||||
if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr))
|
||||
{
|
||||
earlyterm_write("loader_relo_sym: section header table error\n");
|
||||
earlyterm_write("relo_sym: section header table error\n");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -20,7 +24,7 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
|
|||
shstrtab = (char*)pm_alloc(shdr.sh_size);
|
||||
if (shstrtab == NULL)
|
||||
{
|
||||
earlyterm_write("loader_relo_sym: memory error\n");
|
||||
earlyterm_write("relo_sym: mem error (%d)\n", shdr.sh_size);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
@ -28,7 +32,7 @@ static char *get_shstrtab(FILE *file, Elf32_Ehdr *header)
|
|||
vfs_lseek(file, shdr.sh_offset, SEEK_SET);
|
||||
if (vfs_read(file, shstrtab, shdr.sh_size) != (ssize_t)shdr.sh_size)
|
||||
{
|
||||
earlyterm_write("loader_relo_sym: shstrtab size error\n");
|
||||
earlyterm_write("relo_sym: shstrtab size error\n");
|
||||
pm_free(shstrtab);
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -45,16 +49,16 @@ static int reloc_section(struct process *process, FILE *file, Elf32_Shdr *shdr)
|
|||
for (uint32_t i = 0 ; i < shdr->sh_size / shdr->sh_entsize ; ++i)
|
||||
{
|
||||
// Get relocatable entry
|
||||
vfs_lseek(file, shdr->sh_offset + (i * sizeof(rela)), SEEK_SET);
|
||||
if (vfs_read(file, &rela, sizeof(rela)) != sizeof(rela))
|
||||
vfs_lseek(file, shdr->sh_offset + (i * sizeof(Elf32_Rela)), SEEK_SET);
|
||||
if (vfs_read(file, &rela, sizeof(Elf32_Rela)) != sizeof(Elf32_Rela))
|
||||
{
|
||||
earlyterm_write("reloc_section: reloc section size error\n");
|
||||
earlyterm_write("relo_sym: reloc section size error\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Relocalise symbols
|
||||
//earlyterm_write("* [%d] %p, %#x\n", i, rela.r_offset, rela.r_addend);
|
||||
prog[rela.r_offset >> 2] = rela.r_addend + process->memory.program.start;
|
||||
prog[rela.r_offset >> 2] += (uint32_t)process->memory.program.start;
|
||||
//DBG_WAIT;
|
||||
}
|
||||
return (0);
|
||||
|
@ -69,8 +73,10 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
|
|||
(void)process;
|
||||
|
||||
// DEBUG
|
||||
//earlyterm_write("e_shnum = %d\n", header->e_shnum);
|
||||
//earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx);
|
||||
earlyterm_write("e_shoff = %d\n", header->e_shoff);
|
||||
earlyterm_write("e_shnum = %d\n", header->e_shnum);
|
||||
earlyterm_write("e_shstrndx = %d\n", header->e_shstrndx);
|
||||
//DBG_WAIT;
|
||||
|
||||
|
||||
// Get the shstrtab
|
||||
|
@ -82,10 +88,13 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
|
|||
for (int i = 1 ; i < header->e_shnum ; ++i)
|
||||
{
|
||||
// Get next section header
|
||||
vfs_lseek(file, header->e_shoff + (i * sizeof(shdr)), SEEK_SET);
|
||||
if (vfs_read(file, &shdr, sizeof(shdr)) != sizeof(shdr))
|
||||
vfs_lseek(file, header->e_shoff + (i * sizeof(Elf32_Shdr)), SEEK_SET);
|
||||
if (vfs_read(file, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr))
|
||||
{
|
||||
earlyterm_write("loader_reloc_sym: section header\n");
|
||||
earlyterm_write("loader_reloc_sym: shoff = %#x\n", header->e_shoff);
|
||||
earlyterm_write("loader_reloc_sym: shnum = %#x\n", header->e_shnum);
|
||||
earlyterm_write("loader_reloc_sym: off = %#x\n", header->e_shoff + (i * sizeof(Elf32_Shdr)));
|
||||
return (-2);
|
||||
}
|
||||
|
||||
|
@ -100,8 +109,8 @@ int loader_reloc_sym(struct process *process, FILE *file, Elf32_Ehdr *header)
|
|||
}
|
||||
pm_free(shstrtab);
|
||||
//earlyterm_write("start = %p\n", process->memory.program.start);
|
||||
//DBG_WAIT;
|
||||
//DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
//DBG_WAIT;
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ int sched_add_task(struct process *process)
|
|||
return (-2);
|
||||
}
|
||||
|
||||
// Change process status
|
||||
process->status = PROC_RUNNING;
|
||||
|
||||
// Initialize new task
|
||||
// TODO: update quantum ticks management
|
||||
sched_slot->priority._static = SCHED_QUANTUM_TICKS;
|
||||
|
|
|
@ -19,7 +19,7 @@ void sched_initialize(void)
|
|||
}
|
||||
|
||||
// Initialize internal process informations
|
||||
// @note:
|
||||
// TODO ?
|
||||
// * process_sched_current Used by the kernel to handle
|
||||
// interrupt / exception
|
||||
// * process_user_current Used by the kernel to allow
|
||||
|
|
|
@ -1,20 +1,61 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/memory.h>
|
||||
|
||||
// This function SHOULD NOT be called
|
||||
// without atomic operation !!
|
||||
// TODO: dynamic allocation ?
|
||||
pid_t process_alloc(struct process **process)
|
||||
// TODO: return EAGAIN !!
|
||||
// TODO: return ENOMEM !!
|
||||
struct process *process_alloc(void)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
extern struct process *proc_table;
|
||||
extern uint32_t proc_table_max;
|
||||
uint32_t proc_table_idx;
|
||||
struct process **proc;
|
||||
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Try to find free slot
|
||||
proc = &proc_table;
|
||||
proc_table_idx = -1;
|
||||
while (++proc_table_idx < proc_table_max && *proc != NULL)
|
||||
{
|
||||
if (process_stack[i].status == PROC_UNUSED)
|
||||
{
|
||||
process_stack[i].status = PROC_USED;
|
||||
*process = &process_stack[i].process;
|
||||
return (i);
|
||||
// Check free slot
|
||||
if ((*proc)->status != PROC_DEAD) {
|
||||
proc = &(*proc)->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Indicate init phase, stop atomic
|
||||
// operations and return the process
|
||||
(*proc)->status = PROC_INIT;
|
||||
(*proc)->pgid = 0;
|
||||
atomic_stop();
|
||||
return (*proc);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
// Check error
|
||||
if (proc_table_idx >= proc_table_max) {
|
||||
earlyterm_write("proc_alloc: EAGAIN !\n");
|
||||
atomic_stop();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// Alloc new process manually
|
||||
*proc = (struct process *)pm_alloc(sizeof(struct process));
|
||||
if (*proc == NULL) {
|
||||
earlyterm_write("proc_alloc: ENOMEM !\n");
|
||||
atomic_stop();
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// Init and return the now process
|
||||
(*proc)->status = PROC_INIT;
|
||||
(*proc)->pid = proc_table_idx + 1;
|
||||
(*proc)->pgid = 0;
|
||||
(*proc)->next = NULL;
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
return (*proc);
|
||||
}
|
||||
|
|
|
@ -4,19 +4,14 @@
|
|||
#include <kernel/devices/earlyterm.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
struct process *process_create(const char *name)
|
||||
struct process *process_create(void)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
extern struct dentry *vfs_root_node;
|
||||
struct process *process;
|
||||
pid_t process_pid;
|
||||
|
||||
// Check error
|
||||
if (name == NULL)
|
||||
return (NULL);
|
||||
|
||||
// Try to find free slot.
|
||||
process_pid = process_alloc(&process);
|
||||
process = process_alloc();
|
||||
if (process == NULL)
|
||||
{
|
||||
earlyterm_write("proc_error: alloc error !");
|
||||
|
@ -26,7 +21,7 @@ struct process *process_create(const char *name)
|
|||
|
||||
// Initialize user stack
|
||||
process->memory.stack.size.user = PROCESS_USER_STACK_SIZE;
|
||||
process->memory.stack.user = (uint32_t)pm_alloc(process->memory.stack.size.user);
|
||||
process->memory.stack.user = (void *)pm_alloc(process->memory.stack.size.user);
|
||||
if (process->memory.stack.user == 0x00000000)
|
||||
{
|
||||
earlyterm_write("proc_error: user stack error !");
|
||||
|
@ -34,11 +29,11 @@ struct process *process_create(const char *name)
|
|||
process_free(process);
|
||||
return (NULL);
|
||||
}
|
||||
process->context.reg[15] = process->memory.stack.user + process->memory.stack.size.user;
|
||||
process->context.reg[15] = (uint32_t)process->memory.stack.user + process->memory.stack.size.user;
|
||||
|
||||
// Initialize kernel stack
|
||||
process->memory.stack.size.kernel = PROCESS_KERNEL_STACK_SIZE;
|
||||
process->memory.stack.kernel = (uint32_t)pm_alloc(process->memory.stack.size.kernel);
|
||||
process->memory.stack.kernel = (void *)pm_alloc(process->memory.stack.size.kernel);
|
||||
if (process->memory.stack.kernel == 0x00000000)
|
||||
{
|
||||
earlyterm_write("proc_error: kernel stack error !");
|
||||
|
@ -51,26 +46,23 @@ struct process *process_create(const char *name)
|
|||
|
||||
// initialize "exit" part.
|
||||
uint8_t callexit[8] = {
|
||||
0b00100100, 0b01001010, // xor r4, r4
|
||||
0b01100100, 0b00000011, // mov r0, r4
|
||||
0b11000011, __NR_exit, // trapa #__NR_exit
|
||||
0b10110000, 0b00000100, // bsr PC + 2 - 4
|
||||
0b00000000, 0b00001001 // nop
|
||||
};
|
||||
process->memory.exit.size = 8;
|
||||
process->memory.exit.start = (uint32_t)(pm_alloc(process->memory.exit.size));
|
||||
process->memory.exit.start = (void *)pm_alloc(process->memory.exit.size);
|
||||
if (process->memory.exit.start == 0x00000000)
|
||||
{
|
||||
pm_free((void *)process->memory.stack.user);
|
||||
pm_free((void *)process->memory.stack.kernel);
|
||||
pm_free(process->memory.stack.user);
|
||||
pm_free(process->memory.stack.kernel);
|
||||
process_free(process);
|
||||
return (NULL);
|
||||
}
|
||||
process->context.pr = process->memory.exit.start;
|
||||
process->context.pr = (uint32_t)process->memory.exit.start;
|
||||
memcpy((void *)process->memory.exit.start, callexit, 6);
|
||||
|
||||
// Set process name.
|
||||
strncpy(process->name, name, PROCESS_NAME_LENGHT);
|
||||
|
||||
// Initialize context.
|
||||
for (int i = 0 ; i < 15 ; i = i + 1)
|
||||
process->context.reg[i] = 0x00000000;
|
||||
|
@ -107,7 +99,7 @@ struct process *process_create(const char *name)
|
|||
// The new process will be visible only
|
||||
// when it is registered by the sheduler.
|
||||
process->parent = process_current;
|
||||
process->sibling = NULL;
|
||||
process->child = NULL;
|
||||
process->next = NULL;
|
||||
return (process);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
//TODO: free allocated proc ?
|
||||
int process_free(struct process *process)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
extern struct process *proc_table;
|
||||
extern uint32_t proc_table_max;
|
||||
uint32_t proc_table_idx;
|
||||
struct process *proc;
|
||||
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
proc = proc_table;
|
||||
proc_table_idx = 0;
|
||||
while (proc != NULL && ++proc_table_idx < proc_table_max)
|
||||
{
|
||||
if (&process_stack[i].process == process)
|
||||
if (proc == process)
|
||||
{
|
||||
process_stack[i].status = PROC_UNUSED;
|
||||
proc->status = PROC_DEAD;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,38 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
struct process *process_get_proc(pid_t pid)
|
||||
struct process *process_get(pid_t pid)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
extern struct process *proc_table;
|
||||
struct process *proc;
|
||||
|
||||
// Check error
|
||||
if (pid < 0 || pid >= PROCESS_MAX)
|
||||
if (pid <= 0)
|
||||
return (NULL);
|
||||
|
||||
// Return process.
|
||||
return (&process_stack[pid].process);
|
||||
}
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
pid_t process_get_pid(struct process *target)
|
||||
{
|
||||
extern struct process_stack process_stack[PROCESS_MAX];
|
||||
int i;
|
||||
|
||||
i = -1;
|
||||
while (++i < PROCESS_MAX)
|
||||
// Proess table walk
|
||||
proc = proc_table;
|
||||
while (proc != NULL)
|
||||
{
|
||||
if (&process_stack[i].process == target)
|
||||
return (i);
|
||||
// Check target process
|
||||
if (proc->pid != pid) {
|
||||
proc = proc->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the process is alive
|
||||
if (proc->status == PROC_DEAD)
|
||||
proc = NULL;
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
return (proc);
|
||||
}
|
||||
return (-1);
|
||||
|
||||
// Stop atomic operation
|
||||
atomic_stop();
|
||||
return (NULL);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
#include <kernel/process.h>
|
||||
|
||||
// Create all internal global
|
||||
// used to handle process.
|
||||
struct process_stack process_stack[PROCESS_MAX];
|
||||
// Internal symbols
|
||||
struct process *proc_table;
|
||||
uint32_t proc_table_max;
|
||||
|
||||
__attribute__((constructor))
|
||||
void process_constructor(void)
|
||||
{
|
||||
// Set all process to idle state.
|
||||
for (int i = 0 ; i < PROCESS_MAX ; i = i + 1)
|
||||
{
|
||||
process_stack[i].status = PROC_UNUSED;
|
||||
}
|
||||
// Initialise dynamic process list
|
||||
// TODO:
|
||||
// get the scheduler timing and set the maximal
|
||||
// number of processes which can be running in the
|
||||
// same time.
|
||||
proc_table = NULL;
|
||||
proc_table_max = PROCESS_MAX;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,46 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
|
|||
{
|
||||
extern struct sched_task *sched_task_current;
|
||||
extern struct sched_task *sched_task_queue;
|
||||
struct sched_task *task_current;
|
||||
extern struct process *process_current;
|
||||
struct sched_task *task_next;
|
||||
|
||||
|
||||
// Get the potential next process context
|
||||
task_next = sched_task_queue;
|
||||
if (sched_task_current != NULL && sched_task_current->next != NULL)
|
||||
task_next = sched_task_current->next;
|
||||
|
||||
// Check / update next task
|
||||
while (task_next != sched_task_current)
|
||||
{
|
||||
// Check process validity
|
||||
if (task_next->process->status == PROC_RUNNING)
|
||||
break;
|
||||
|
||||
// Get next task
|
||||
task_next = task_next->next;
|
||||
if (task_next == NULL)
|
||||
task_next = sched_task_queue;
|
||||
}
|
||||
|
||||
// Check error
|
||||
if (task_next == sched_task_current)
|
||||
return (-1);
|
||||
|
||||
// Get contexts
|
||||
*context_current = NULL;
|
||||
if (sched_task_current != NULL)
|
||||
*context_current = &sched_task_current->process->context;
|
||||
*context_next = &task_next->process->context;
|
||||
|
||||
// Update scheduler task / process current
|
||||
sched_task_current = task_next;
|
||||
process_current = sched_task_current->process;
|
||||
return (0);
|
||||
|
||||
|
||||
// Check current task
|
||||
// TODO: check process status !!
|
||||
if (sched_task_current == NULL)
|
||||
/* if (sched_task_current == NULL)
|
||||
{
|
||||
task_current = NULL;
|
||||
task_next = (sched_task_queue != NULL) ? sched_task_queue : NULL;
|
||||
|
@ -28,11 +62,12 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
|
|||
|
||||
// Update internal scheduler task cursor
|
||||
sched_task_current = task_next;
|
||||
process_current = sched_task_current->process;
|
||||
|
||||
// Get context
|
||||
*context_current = (task_current != NULL) ? &task_current->process->context : NULL;
|
||||
*context_next = &task_next->process->context;
|
||||
|
||||
*/
|
||||
// DEBUG !
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "Scheduler_schudele !");
|
||||
|
@ -42,5 +77,5 @@ int sched_schedule(common_context_t **context_current, common_context_t **contex
|
|||
printk(0, 4, "context next = %p", *context_next);
|
||||
kvram_display();
|
||||
DBG_WAIT;*/
|
||||
return (0);
|
||||
//return (0);
|
||||
}
|
||||
|
|
|
@ -1,14 +1,35 @@
|
|||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/memory.h>
|
||||
// TODO: remove / move me ?
|
||||
#include <lib/unistd.h>
|
||||
|
||||
void sys_exit(int status)
|
||||
{
|
||||
// TODO handle status
|
||||
(void)status;
|
||||
extern struct process *process_current;
|
||||
|
||||
// Fow now, just wait manual reset...
|
||||
earlyterm_clear();
|
||||
earlyterm_write("PROCESS EXIT SYSCALL !!!!");
|
||||
earlyterm_write("Wait manual reset...");
|
||||
//earlyterm_clear();
|
||||
//earlyterm_write("PROCESS EXIT SYSCALL !!!!\n");
|
||||
//earlyterm_write("Wait manual reset...");
|
||||
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Generate stat_loc
|
||||
process_current->__stat_loc = __W_EXITCODE(status, 0);
|
||||
|
||||
// Frre'd all allocated space
|
||||
pm_free(process_current->memory.stack.user);
|
||||
pm_free(process_current->memory.stack.kernel);
|
||||
pm_free(process_current->memory.program.start);
|
||||
pm_free(process_current->memory.exit.start);
|
||||
|
||||
// Change process state
|
||||
process_current->status = PROC_ZOMBIE;
|
||||
|
||||
// Stop atomic operation
|
||||
atomic_stop();
|
||||
while (1);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
#include <kernel/devices/earlyterm.h>
|
||||
#include <lib/string.h>
|
||||
|
||||
//TODO
|
||||
//TODO COPY-ON-WRITE !!
|
||||
//TODO
|
||||
static void proc_dump_shared(struct process *child, struct process *parent)
|
||||
{
|
||||
// Dump all opened file
|
||||
|
@ -18,17 +21,20 @@ static void proc_dump_shared(struct process *child, struct process *parent)
|
|||
memcpy(&child->tty, &parent->tty, sizeof(FILE));
|
||||
}
|
||||
|
||||
//TODO
|
||||
//TODO Return EAGAIN if no proc can be created !!
|
||||
//TODO Return ENOMEM if no memories can be allocated !!
|
||||
//TODO
|
||||
pid_t sys_fexecve(const char *pathname)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
struct process *proc;
|
||||
pid_t child_pid;
|
||||
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Try create new process
|
||||
proc = process_create(pathname);
|
||||
proc = process_create();
|
||||
if (proc == NULL)
|
||||
{
|
||||
earlyterm_write("sys_fexecve: process_create error !\n");
|
||||
|
@ -51,6 +57,10 @@ pid_t sys_fexecve(const char *pathname)
|
|||
return (-1);
|
||||
}
|
||||
|
||||
// Release child process
|
||||
proc->sibling = process_current->child;
|
||||
process_current->child = proc;
|
||||
|
||||
// Add new process into task queue
|
||||
if (sched_add_task(proc))
|
||||
{
|
||||
|
@ -61,15 +71,12 @@ pid_t sys_fexecve(const char *pathname)
|
|||
return (-1);
|
||||
}
|
||||
|
||||
// Get child process PID
|
||||
child_pid = process_get_pid(proc);
|
||||
|
||||
// Debug
|
||||
earlyterm_write("New proc sched added !");
|
||||
earlyterm_write("New proc PID = %#x !", child_pid);
|
||||
DBG_WAIT;
|
||||
//earlyterm_write("New proc sched added !\n");
|
||||
///earlyterm_write("New proc PID = %#x !\n", proc->pid);
|
||||
//DBG_WAIT;
|
||||
|
||||
// Stop atomic operations
|
||||
atomic_stop();
|
||||
return (child_pid);
|
||||
return (proc->pid);
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/*#include <kernel/process.h>
|
||||
|
||||
pid_t sys_fork(void)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
struct process *process_new;
|
||||
pid_t process_new_pid;
|
||||
|
||||
// Check error
|
||||
if (process_current == NULL)
|
||||
return (-1);
|
||||
|
||||
// Get the new process slot.
|
||||
new_pid = process_alloc(&process_new);
|
||||
if (new_pid != 0)
|
||||
return (-1);
|
||||
|
||||
// Try to create user stack
|
||||
process_new->memory.stack.size.user = process_current->;
|
||||
process_new->memory.stack.user = (uint32_t)pm_alloc(process_new->memory.stack.size.user);
|
||||
if (process_new->memory.stack.user == 0x00000000)
|
||||
{
|
||||
process_free(process_new);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Try to create kernel stack
|
||||
process_new->memory.stack.size.kernel = process_current->memory.stack.size.kernel;
|
||||
process_new->memory.stack.kernel = (uint32_t)pm_alloc(process_new->memory.stack.size.kernel);
|
||||
if (process_new->memory.stack.kernel == 0x00000000)
|
||||
{
|
||||
pm_free(process_new->memory.stack.user);
|
||||
process_free(process_new);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
//TODO: dump stack data
|
||||
//TODO: dump code data
|
||||
//TODO: Initialize context.
|
||||
return (-1);
|
||||
}*/
|
|
@ -0,0 +1,25 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
pid_t sys_getpgid(void)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
pid_t ret;
|
||||
|
||||
// Start artomic opetations
|
||||
atomic_start();
|
||||
|
||||
// Check error
|
||||
if (process_current == NULL) {
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Get Process Groupe ID
|
||||
ret = process_current->pgid;
|
||||
|
||||
// Stop atomic operation
|
||||
atomic_stop();
|
||||
return (ret);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
pid_t sys_getpid(void)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
pid_t ret;
|
||||
|
||||
// Start artomic opetations
|
||||
atomic_start();
|
||||
|
||||
// Check error
|
||||
if (process_current == NULL) {
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Get Process ID
|
||||
ret = process_current->pid;
|
||||
|
||||
// Stop atomic operation
|
||||
atomic_stop();
|
||||
return (ret);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
pid_t sys_getppid(void)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
pid_t ret;
|
||||
|
||||
// Start artomic opetations
|
||||
atomic_start();
|
||||
|
||||
// Check error
|
||||
if (process_current == NULL) {
|
||||
atomic_stop();
|
||||
return (-1);
|
||||
}
|
||||
|
||||
// Check first process
|
||||
if (process_current->parent == NULL) {
|
||||
atomic_stop();
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Get Parent Process ID
|
||||
ret = process_current->parent->pid;
|
||||
|
||||
// Stop atomic operation
|
||||
atomic_stop();
|
||||
return (ret);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/scheduler.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
int sys_setpgid(pid_t pid, pid_t pgid)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
struct process *proc;
|
||||
|
||||
// Start atomic operations
|
||||
atomic_start();
|
||||
|
||||
// Get the appropriate process
|
||||
proc = process_current;
|
||||
if (pid != 0)
|
||||
proc = process_get(pid);
|
||||
|
||||
// Check error
|
||||
if (proc == NULL)
|
||||
return (-1);
|
||||
|
||||
// Update Proocess Group ID
|
||||
proc->pgid = (pgid == 0) ? process_current->pgid : pgid;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#include <kernel/syscall.h>
|
||||
|
||||
pid_t sys_wait(int *wstatus)
|
||||
{
|
||||
return (sys_waitpid(-1, wstatus, 0));
|
||||
}
|
|
@ -1,6 +1,78 @@
|
|||
#include <kernel/process.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
#include <kernel/util/atomic.h>
|
||||
|
||||
pid_t sys_waitpid(pid_t pid, int *wstatus, int options)
|
||||
{
|
||||
extern struct process *process_current;
|
||||
struct process **proc;
|
||||
pid_t ret;
|
||||
|
||||
|
||||
// Check useless wait
|
||||
if (process_current->child == NULL) {
|
||||
earlyterm_write("waitpid: no child\n");
|
||||
DBG_WAIT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
//TODO: handle options
|
||||
(void)options;
|
||||
|
||||
// Wait util one of its children specified by PID
|
||||
// has changed state
|
||||
while (1)
|
||||
{
|
||||
// Start atomic operation
|
||||
atomic_start();
|
||||
|
||||
// Find childs to check
|
||||
proc = &process_current->child;
|
||||
while (*proc != NULL)
|
||||
{
|
||||
// Check terminated child
|
||||
if ((*proc)->status == PROC_ZOMBIE &&
|
||||
((pid < -1 && (*proc)->pgid == -pid) ||
|
||||
pid == -1 ||
|
||||
(pid == 0 && (*proc)->pgid == process_current->pgid) ||
|
||||
(pid > 0 && (*proc)->pid == pid)))
|
||||
{
|
||||
// Change the child process state
|
||||
(*proc)->status = PROC_DEAD;
|
||||
|
||||
// Get the child process PID and stat_loc
|
||||
ret = (*proc)->pid;
|
||||
*wstatus = (*proc)->__stat_loc;
|
||||
|
||||
// Remove process form the child list
|
||||
*proc = (*proc)->sibling;
|
||||
|
||||
//DEBUG
|
||||
//earlyterm_write("waitpid: find %d\n", ret);
|
||||
//DBG_WAIT;
|
||||
//DBG_WAIT;
|
||||
|
||||
// Stop atomic operation and return
|
||||
atomic_stop();
|
||||
return (ret);
|
||||
}
|
||||
|
||||
// Get next child process
|
||||
proc = &(*proc)->sibling;
|
||||
}
|
||||
|
||||
// Force process to sleep
|
||||
// TODO:
|
||||
// Schedule !! and change the niciess of the
|
||||
// process !!
|
||||
//
|
||||
// Stop atomic operation and wait
|
||||
atomic_stop();
|
||||
__asm__ volatile ("sleep; nop");
|
||||
}
|
||||
|
||||
// Error
|
||||
//earlyterm_write("waitpid: error\n");
|
||||
//DBG_WAIT;
|
||||
return (-1);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/util/unistd_32.h>
|
||||
#include <kernel/devices/earlyterm.h>
|
||||
|
||||
static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
||||
|
@ -12,7 +13,7 @@ static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
|||
DBG_WAIT;
|
||||
}
|
||||
|
||||
static const void *sys_handler[9] = {
|
||||
static const void *sys_handler[__NR_MAX] = {
|
||||
// Kernel Test
|
||||
sys_test, // test
|
||||
|
||||
|
@ -20,6 +21,11 @@ static const void *sys_handler[9] = {
|
|||
sys_exit, // exit
|
||||
sys_fexecve, // fexecve
|
||||
sys_waitpid, // waitpid
|
||||
sys_wait, // wait
|
||||
sys_getpid, // getpid
|
||||
sys_getppid, // getppid
|
||||
sys_getpgid, // getpgid
|
||||
sys_setpgid, // setpgid
|
||||
|
||||
// VFS
|
||||
sys_read, // read
|
||||
|
@ -27,32 +33,18 @@ static const void *sys_handler[9] = {
|
|||
sys_open, // open
|
||||
sys_close, // close
|
||||
sys_lseek, // lseek
|
||||
|
||||
// Display
|
||||
/* kvram_display, // kvram_display
|
||||
kvram_clear, // kvram_clear
|
||||
printk, // printk
|
||||
kvram_ascii, // kvram_ascii
|
||||
kvram_reverse, // kvram_reverse
|
||||
kvram_scroll, // kvram_scroll
|
||||
kvram_clr_str_area // kvram_clr_str_area*/
|
||||
};
|
||||
|
||||
void *sys_get_handler(int sysno)
|
||||
{
|
||||
// Check sysno validity
|
||||
if (sysno < 0 || sysno >= 9)
|
||||
if (sysno < 0 || sysno >= __NR_MAX)
|
||||
return (NULL);
|
||||
|
||||
// DEBUG
|
||||
/*kvram_clear();
|
||||
printk(0, 0, "TRAPA ABI pre_handler !");
|
||||
printk(0, 1, "sysno = %d", sysno);
|
||||
printk(0, 2, "handler = %p", sys_handler[sysno]);
|
||||
kvram_display();
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;
|
||||
DBG_WAIT;*/
|
||||
//earlyterm_write("syscall (%d)!!\n", sysno);
|
||||
//DBG_WAIT;
|
||||
//DBG_WAIT;
|
||||
|
||||
// Return syscall
|
||||
return ((void *)sys_handler[sysno]);
|
||||
|
|
|
@ -46,7 +46,7 @@ TARGET-LIBS-DYNAMIC := $(patsubst %,lib%_dyn.so,$(TARGET-MODULES))
|
|||
#------- --------#
|
||||
all: $(TARGET-LIBS-STATIC) $(TARGET-LIBS-DYNAMIC)
|
||||
|
||||
$(BUILD-STATIC) $(BUILD-DYNAMIC):
|
||||
$(BUILD-STATIC) $(BUILD-DYNAMIC) $(DEBUG-DYNLIB):
|
||||
@ printf "Create $(blue)$@$(nocolor) directory\n"
|
||||
@ mkdir -p $@
|
||||
|
||||
|
@ -69,13 +69,13 @@ endef
|
|||
define rule-src-dynamic
|
||||
$(patsubst %,$(BUILD-DYNAMIC)/%.o,$(subst /,_,$(basename $1))): $1 | $(BUILD-DYNAMIC)
|
||||
@ printf "compiling $(white)$$<$(nocolor)..."
|
||||
@ $(CC) -fPIC $(CFLAGS) -c $$< -o $$@ $(HEADER)
|
||||
@ $(CC) -pie $(CFLAGS) -c $$< -o $$@ $(HEADER)
|
||||
@ printf "$(green)[ok]$(nocolor)\n"
|
||||
endef
|
||||
define rule-link-dynamic
|
||||
$(patsubst %,lib%_dyn.so,$1): $2 | $(DEBUG-DYNLIB)
|
||||
@ printf "Link $(green)$$@$(nocolor) lib\n"
|
||||
$(CC) -shared -o $$@ $$^ -nostdlib -lgcc
|
||||
$(CC) -T user_shared_lib.ld -Wl,-M -pie -o $$@ $$^ -nostdlib -lgcc > $(DEBUG-DYNLIB)/$$@.map
|
||||
endef
|
||||
|
||||
|
||||
|
|
|
@ -1,12 +1 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _dupdate
|
||||
.type _dupdate, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_dupdate:
|
||||
trapa #__NR_kvram_display
|
||||
rts
|
||||
nop
|
||||
.end
|
||||
# TODO screen syscall handling :D
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _fork
|
||||
.type _fork, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_fork:
|
||||
!trapa #__NR_fork
|
||||
mov #-1, r0
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _getpgid
|
||||
.type _getpgid, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_getpgid:
|
||||
trapa #__NR_getpgid
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _getpid
|
||||
.type _getpid, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_getpid:
|
||||
trapa #__NR_getpid
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _getppid
|
||||
.type _getppid, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_getppid:
|
||||
trapa #__NR_getppid
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -0,0 +1,12 @@
|
|||
#include <kernel/util/unistd_32.h>
|
||||
.text
|
||||
.global _setpgid
|
||||
.type _setpgid, @function
|
||||
|
||||
|
||||
.align 2
|
||||
_setpgid:
|
||||
trapa #__NR_setpgid
|
||||
rts
|
||||
nop
|
||||
.end
|
|
@ -9,21 +9,19 @@ int builtin_proc(void)
|
|||
int wstatus;
|
||||
|
||||
puts("proc test entry :)\n");
|
||||
printf("printf test:\n");
|
||||
printf("0#10x: %0#10x\n", 0xabcdef);
|
||||
printf("str: %s\n", "Oui le test oui ! :D");
|
||||
printf("interger: %d\n", 12345);
|
||||
printf("interger: %lld\n", 999999999999999999);
|
||||
printf(" PPID PID PGID\n");
|
||||
printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid());
|
||||
|
||||
// Try to create first child
|
||||
/*child = fexecve("/mnt/casio/VHEX/test.elf");
|
||||
child = fexecve("/mnt/casio/VHEX/test.elf");
|
||||
if (child == -1)
|
||||
{
|
||||
puts("fexecve fail :(\n");
|
||||
printf("fexecve fail :(\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
// Wait child death
|
||||
waitpid(child, &wstatus, WUNTRACED);
|
||||
*/ return (0);
|
||||
waitpid(-1, &wstatus, 0);
|
||||
printf("+++ exited with %d +++\n", WEXITSTATUS(wstatus));
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -7,35 +7,6 @@ int main(void)
|
|||
{
|
||||
char input[12];
|
||||
int cmd_size;
|
||||
//char **argv;
|
||||
//int argc;
|
||||
//int STDOUT_FILENO;
|
||||
|
||||
// Try to open TTY
|
||||
// @note:
|
||||
// We use O_DIRECT to avoid cache
|
||||
// generation because we do not have a
|
||||
// lot of memory.
|
||||
/*STDOUT_FILENO = open("/dev/tty", O_DIRECT);
|
||||
if (STDOUT_FILENO < 0)
|
||||
{
|
||||
// Display error.
|
||||
display_t disp;
|
||||
dopen(&disp, "default");
|
||||
dclear(&disp);
|
||||
dprint(&disp, 0, 0, "User program fail to open TTY");
|
||||
dprint(&disp, 0, 1, "Wait user manual reset...");
|
||||
dupdate(&disp);
|
||||
|
||||
// Wait user manual reset.
|
||||
while (1)
|
||||
{
|
||||
// @note: we can use "sleep" because we
|
||||
// are in privilegied mode.
|
||||
// TODO: use sleep syscall !
|
||||
__asm__ volatile ("sleep");
|
||||
}
|
||||
}*/
|
||||
|
||||
// Shell main loop.
|
||||
write(STDOUT_FILENO, "Boot Complete !\n", 16);
|
||||
|
@ -45,6 +16,10 @@ int main(void)
|
|||
write(STDOUT_FILENO, ">", 1);
|
||||
cmd_size = read(STDIN_FILENO, input, 12);
|
||||
|
||||
// Check no char
|
||||
if (cmd_size == 1)
|
||||
continue;
|
||||
|
||||
// Remove '\n' char.
|
||||
// FIXME: create argc, argv !!
|
||||
input[cmd_size - 1] = '\0';
|
||||
|
@ -54,10 +29,7 @@ int main(void)
|
|||
{
|
||||
write(STDOUT_FILENO, input, cmd_size - 1);
|
||||
write(STDOUT_FILENO, ": command not found\n", 20);
|
||||
} else {
|
||||
write(STDOUT_FILENO, input, cmd_size - 1);
|
||||
write(STDOUT_FILENO, ": command found :D !\n", 21);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ include ../../../global.mk
|
|||
## Static variables
|
||||
##--
|
||||
HEADER := -I../../../include -I../../../include/user
|
||||
LIBS := -L../../lib/ -lunistd -lstdio -lstring -ldisplay -lgcc
|
||||
LIBS := -L../../lib/ -llibc -ldisplay -lgcc
|
||||
BUILD := ../../../build/user/test
|
||||
DEBUG := ../../../debug_bin
|
||||
OUTPUT := ../../../output
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
#include <lib/display.h>
|
||||
#include <lib/stdio.h>
|
||||
#include <lib/unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint32_t counter = 0;
|
||||
while (1)
|
||||
{
|
||||
// Display data
|
||||
// dclr_str_area(0, 2, 20, 1);
|
||||
// dprint(0, 2, "C process: %d", counter);
|
||||
// dupdate();
|
||||
|
||||
// Update counter and "wait"
|
||||
counter = counter + 1;
|
||||
if (counter >= 100)
|
||||
counter = 0;
|
||||
for (int i = 0 ; i < 300000 ; ++i);
|
||||
}
|
||||
setpgid(0, 12);
|
||||
printf("%-6d%-6d%-6d\n", getppid(), getpid(), getpgid());
|
||||
printf("child proc fini...try to exit\n");
|
||||
for(int i = 0 ; i < 3000000 ; ++i);
|
||||
return (84);
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/*.global _test
|
||||
.type _test, @function
|
||||
|
||||
.align 2
|
||||
_test:
|
||||
sts.l pr, @-r15
|
||||
|
||||
mov.l .syscall_vram, r0
|
||||
mov.l .syscall_entry, r1
|
||||
jsr @r1
|
||||
nop
|
||||
tst r0, r0
|
||||
bf _test
|
||||
nop
|
||||
|
||||
lds.l @r15+, pr
|
||||
rts
|
||||
nop
|
||||
|
||||
.align 4
|
||||
.syscall_entry: .long 0xa0010070
|
||||
.syscall_vram: .long 0x00000135
|
||||
.end*/
|
Loading…
Reference in New Issue