Update project organization

This commit is contained in:
Yann MAGNIN 2020-03-15 00:56:31 +01:00
parent aea7368d46
commit da5ff236bb
86 changed files with 1193 additions and 1273 deletions

1
.gitignore vendored
View File

@ -58,3 +58,4 @@ build/
.tests
.old
*.g1a
debug_bin

View File

@ -1,6 +1,6 @@
# Vhex Kernel
Vhex is a kernel which provide development and retro ingenierie environment for fx9860g.
Vhex is a kernel which provide retro ingenierie environment for the fx9860g.
The Casio's OS code is not open-source, but we can read the binary for understand his working.
There are in particular the syscalls, OS's functions that can be called as a library by the add-ins, which are a gold mine of clues about the functioning of the material.
@ -9,6 +9,9 @@ There are in particular the syscalls, OS's functions that can be called as a lib
* Loader ELF
* Scheduler (not prehemptive yet)
* Driver (EEPROM (read), screen, keyboard, timers)
* Syscall
* Virtual File System
* File System Ext2 on RAM
## Building

View File

@ -0,0 +1,39 @@
#ifndef __KERNEL_DEVICES_EARLYTERM_H__
# define __KERNEL_DEVICES_EARLYTERM_H__
#include <stddef.h>
#include <stdint.h>
#include <lib/display.h>
// Wait for debug (dirty)
// TODO: use earlyterm_read() to wait key event ?
#define DBG_WAIT for(int i = 0 ; i < 3000000 ; i++)
// Internal earlyterm device struc
struct earlyterm
{
// Internal object used by the
// drawing lib
display_t display;
// Cursor part, we use only the X
// axis because we scroll the vram when
// the line overflow or new line char
// involved.
struct {
uint8_t x;
uint8_t y;
struct {
uint8_t x;
uint8_t y;
} max;
} cursor;
};
// Primitives
extern int earlyterm_init(void);
extern void earlyterm_clear(void);
extern void earlyterm_write(const char *format, ...);
#endif /*__KERNEL_DEVICES_EARLYTERM_H__*/

View File

@ -5,19 +5,25 @@
#include <stdint.h>
#include <kernel/drivers/screen.h>
#include <kernel/util/types.h>
#include <kernel/util/draw.h>
#include <lib/display.h>
// Define default buffer size.
// TODO: remove me ?
#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3)
#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX)
//#define TTY_BUFFER_LINES (DISPLAY_VCHAR_MAX * 3)
//#define TTY_BUFFER_COLUMNS (DISPLAY_HCHAR_MAX)
// Define TTY major
#define TTY_DEV_MAJOR (4)
struct tty_s
{
char buffer[TTY_BUFFER_LINES + 1][TTY_BUFFER_COLUMNS + 1];
// Internal buffers
struct {
char input[256];
char **output;
} buffers;
// Cursor informations
struct {
int16_t x;
int16_t y;
@ -27,10 +33,9 @@ struct tty_s
} max;
} cursor;
/*struct {
ssize_t (*write)(const void *buffer, size_t count);
ssize_t (*read)(void *buffer, size_t count);
} primitives;*/
// Object used by the drawing library.
// It's store video ram and font informations
display_t disp;
};
// internal strct used by the TTY read primitives

View File

@ -4,8 +4,15 @@
#include <stddef.h>
#include <stdint.h>
// Define screen informations.
#define DISPLAY_SCREEN_WIDTH (128)
#define DISPLAY_SCREEN_HEIGHT (64)
// Internal enumeration for the
// screen getter
typedef enum {
SCREEN_WIDTH,
SCREEN_HEIGHT
} screen_getter_t;
// Internal hardware abstract
extern size_t screen_get(screen_getter_t getter);
extern void (*screen_update)(void *vram);
#endif /*__KERNEL_DRIVERS_SCREEN_H__*/

View File

@ -8,8 +8,8 @@
#include <kernel/util/elf.h>
// Function
extern void *loader(const char *path, struct process *process);
extern int loader(struct process *process, const char *path);
extern int loader_get_header(FILE *file, Elf32_Ehdr *header);
extern void *loader_load_image(FILE *file, Elf32_Ehdr *header, struct process *process);
extern int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header);
#endif /*__KERNEL_LOADER_H__*/

View File

@ -1,14 +0,0 @@
#ifndef __KERNEL_UTIL_DEBUG_H__
# define __KERNEL_UTIL_DEBUG_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/util/draw.h>
// Wait debug (dirty)
#define DBG_WAIT for(int i = 0 ; i < 3000000 ; i++)
// Prototype
void printk(int x, int y, char const *str, ...);
#endif /*__KERNEL_UTIL_DEBUG_H__*/

View File

@ -1,51 +0,0 @@
#ifndef __KERNEL_UTIL_DRAW_H__
# define __KERNEL_UTIL_DRAW_H__
#include <stddef.h>
#include <stdint.h>
#include <kernel/drivers/screen.h>
// Define the (hardcoded) font bitmap informations.
#define KERNEL_FONT_BITMAP_WIDTH (127) // Bitmap width
#define KERNEL_FONT_BITMAP_HEIGHT (23) // Bitmap height
#define KERNEL_FONT_BITMAP_CWIDTH (4) // Character width (bitmap)
#define KERNEL_FONT_BITMAP_CHEIGHT (6) // Character height (bitmap)
#define KERNEL_FONT_REAL_WIDTH (3) // Charater width (real)
#define KERNEL_FONT_REAL_HEIGHT (5) // Character height (real)
#define KERNEL_FONT_NB_CHAR_X ((KERNEL_FONT_BITMAP_WIDTH / KERNEL_FONT_BITMAP_CWIDTH) + 1)
#define KERNEL_FONT_NB_CHAR_Y ((KERNEL_FONT_BITMAP_HEIGHT / KERNEL_FONT_BITMAP_CHEIGHT) + 1)
// Define Number of vertical lines
// and horizontal lines.
// TODO: move me to <kernel/drivers/screen.h> ?
#define DISPLAY_VCHAR_MAX (DISPLAY_SCREEN_HEIGHT / (KERNEL_FONT_REAL_HEIGHT + 1))
#define DISPLAY_HCHAR_MAX (DISPLAY_SCREEN_WIDTH / (KERNEL_FONT_REAL_WIDTH + 1))
// Internal struct used to draw
// the ASCII character.
struct font_block_s
{
int16_t height;
int16_t width;
struct {
uint16_t x;
uint16_t y;
} bitmap;
int16_t x;
int16_t y;
};
// Prototype
extern void kvram_clear(void);
extern void kvram_display(void);
extern void kvram_scroll(int lines);
extern void kvram_reverse(int x, int y, int width, int height);
extern void kvram_clr_str_area(int x, int y, int width, int height);
extern void kvram_print(int x, int y, const char *string, size_t len);
extern void kvram_ascii(int x, int y, char const c);
#endif /*__KERNEL_UTIL_DRAW_H__*/

View File

@ -1,31 +0,0 @@
#ifndef __KERNEL_UTIL_STRING_H__
# define __KERNEL_UTIL_STRING_H__
#include <stddef.h>
#include <stdint.h>
/* memset() - fill memory with a constant byte. */
extern void *memset(void *s, int c, size_t n);
extern void *memcpy(void *dest, const void *src, size_t n);
/* strcat() - concatenate two string */
extern char *strcat(char *dest, char const *src);
/* strcmp() - compare two strings */
extern int strcmp(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, size_t n);
/* strcpy(), strncpy() - copy a string. */
extern char *strncpy(char *dest, char const *str, size_t size);
extern char *strcpy(char *dest, char const *src);
/* strlen - calculate the lenght of a string. */
extern size_t strnlen(char const *str, size_t maxlen);
extern size_t strlen(char const *str);
/* strchr - find the first / last occurent of the char c */
extern char *strchr(const char *s1, int c);
extern char *strchrnul(const char *s1, int c);
extern char *strrchr(const char *s1, int c);
#endif /*__KERNEL_UTIL_STRING_H__*/

View File

@ -4,13 +4,61 @@
#include <stddef.h>
#include <stdint.h>
// Draw primtives
extern void dclear(void);
extern void dclr_str_area(int x, int y, int with, int height);
extern void dprint(int x, int y, char const *str, ...);
extern void dascii(int x, int y, char const c);
extern void dreverse(int x, int y, int width, int height);
extern void dscroll(int line);
extern void dupdate(void);
// Internal struct used in each draw function
typedef struct display_s
{
uint32_t vram[256];
struct font_s *font;
struct {
size_t width;
size_t height;
} display;
// Internal pre-calculated value
int nb_char_width;
} display_t;
// Internal struct used to define font structure object.
// TODO: move me ?
struct font_s
{
// Bitmap informations
struct {
uint8_t width;
uint8_t height;
uint8_t cwidth;
uint8_t cheight;
uint8_t *raw;
} bitmap;
// Character information
struct {
uint8_t width;
uint8_t height;
} font;
};
// Internal struct used to draw
// the ASCII character.
struct font_block_s
{
int16_t height;
int16_t width;
struct {
uint16_t x;
uint16_t y;
} bitmap;
int16_t x;
int16_t y;
};
// Draw primitives
extern int dopen(display_t *disp, const char *fontname);
extern void dclear(display_t *disp);
extern void dascii(display_t *disp, int row, int colomn, char const c);
extern size_t dprint(display_t *disp, int x, int y, char const *str, ...);
extern void dscroll(display_t *disp, int line);
extern void dreverse(display_t *disp, int x, int y, int width, int height);
extern void dupdate(display_t *disp);
#endif /*__LIB_DISPLAY_H__*/

View File

@ -5,21 +5,25 @@
#include <stddef.h>
/* memset() - fill memory with a constant byte. */
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
extern void *memset(void *s, int c, size_t n);
extern void *memcpy(void *dest, const void *src, size_t n);
/* strcat() - concatenate two string */
char *strcat(char *dest, char const *src);
extern char *strcat(char *dest, char const *src);
/* strcmp() - compare two strings */
int strcmp(const char *s1, const char *s2);
extern int strcmp(const char *s1, const char *s2);
extern int strncmp(const char *s1, const char *s2, size_t n);
/* strcpy(), strncpy() - copy a string. */
char *strncpy(char *dest, char const *str, size_t size);
char *strcpy(char *dest, char const *src);
extern char *strncpy(char *dest, char const *str, size_t size);
extern char *strcpy(char *dest, char const *src);
/* strlen - calculate the lenght of a string. */
size_t strnlen(char const *str, size_t maxlen);
size_t strlen(char const *str);
extern size_t strnlen(char const *str, size_t maxlen);
extern size_t strlen(char const *str);
/* strrchr() - find the last occurent of a byte */
extern char *strrchr(const char *s, int c);
#endif /*__STRING_H__*/

View File

@ -20,6 +20,7 @@ NAME := vhex
EXEC := $(OUTPUT)/$(NAME).g1a
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
LIBS := -L../lib -lgcc -lstring -ldisplay
ICON := icon.bmp
@ -46,10 +47,10 @@ OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $(SRC))))
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(OUTPUT) $(EXEC)
all: $(OUTPUT) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc -L../lib -l_display > $(MEMORY_MAP)
$(EXEC): $(OBJ) | $(DEBUG)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) $(LIBS) > $(MEMORY_MAP)
$(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin
$(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON)
@ -84,7 +85,7 @@ sec:
## Automated rules
##---
define rule-src
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $1))): $1
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $1))): $1 | $(BUILD)
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"

View File

@ -1,20 +1,26 @@
#include <stdint.h>
#include <stddef.h>
// Internal helpers
#include <kernel/util/types.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/util/casio.h>
// Modules
#include <kernel/context.h>
#include <kernel/process.h>
#include <kernel/syscall.h>
#include <kernel/scheduler.h>
#include <kernel/loader.h>
// Devices
#include <kernel/devices/tty.h>
#include <kernel/devices/earlyterm.h>
// File System
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/fs/smemfs.h>
#include <kernel/fs/gladfs.h>
#include <kernel/loader.h>
#include <kernel/devices/tty.h>
// Libs
#include <lib/display.h>
#include <lib/string.h>
// Internal symbols
mpu_t current_mpu = MPU_UNKNOWN;
@ -78,7 +84,7 @@ static void rom_explore(volatile void *rom, int32_t size)
/* section_execute() - Used to execute contructors and destructors */
static void section_execute(void *bsection, void *esection)
{
while ((uint32_t)bsection < (uint32_t)esection)
while ((uintptr_t)bsection < (uintptr_t)esection)
{
((void (*)(void))*((uint32_t*)bsection))();
bsection = (void*)((uint32_t)bsection + 4);
@ -90,9 +96,6 @@ static void section_execute(void *bsection, void *esection)
__attribute__((section(".pretext")))
int start(void)
{
extern uint32_t vram[256];
int error;
//--
// Bootstrap part !
//--
@ -120,6 +123,16 @@ int start(void)
// before switching the VBR.
rom_explore(&brom, (int32_t)&srom);
// Start early terminal device
// This device is used by the kernel to display
// some logs on screen
if (earlyterm_init() != 0)
return (-1);
earlyterm_clear();
earlyterm_write("Kernel initialisation...\n");
// Save Casio's hardware context and set
// Vhex hardware context.
// @note:
@ -130,6 +143,7 @@ int start(void)
// And this is why between each `atomic_start`
// and `atomic_end()` the code *SHOULD* be
// exception safe.
earlyterm_write("Environment switch...\n");
atomic_start();
fx9860_context_save(&casio_context);
vhex_context_set();
@ -140,14 +154,17 @@ int start(void)
//---
// Internal FS init !
earlyterm_write("Initialize File System...\n");
gladfs_initialize();
smemfs_initialize();
// Initilize Virtual File System
earlyterm_write("Init. Virtual File System...\n");
vfs_register_filesystem(&gladfs_filesystem);
vfs_register_filesystem(&smemfs_filesystem);
// Creat initial file tree
earlyterm_write("Create Filesystem Hierarchy...\n");
vfs_mount(NULL, NULL, "gladfs", VFS_MOUNT_ROOT, NULL);
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);
@ -156,41 +173,43 @@ int start(void)
vfs_mount(NULL, "/mnt/smemfs", "smemfs", /*MS_RDONLY*/0, NULL);
// Add devices
earlyterm_write("Add devices...\n");
vfs_mknod("/dev/tty", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH,
dev_make_major(TTY_DEV_MAJOR));
// Test mode !
//extern void kernel_test(void);
//kernel_test();
//---
// Start first process !
//---
// Create first process: Vhex.
struct process *vhex_process = process_create("Vhex");
if (vhex_process == NULL)
//earlyterm_write("Create first process...\n");
//struct process *vhex_process = process_create("Vhex");
/*if (vhex_process == NULL)
{
kvram_clear();
printk(0, 0, "Vhex fatal error !");
printk(0, 1, "First process error !");
printk(0, 2, "Wait manual reset...");
kvram_display();
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)&kernel_test;
vhex_process->context.spc = (uint32_t)loader("/mnt/smemfs/VHEX/shell.elf", vhex_process);
if (vhex_process->context.spc == 0x00000000)
//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)
{
// Display message.
kvram_clear();
printk(0, 0, "Vhex fatal error !");
printk(0, 1, "File \"VHEX/shell.elf\" not found !");
printk(0, 2, "Press [MENU key]...");
kvram_display();
earlyterm_clear();
earlyterm_write("Vhex fatal error !\n");
earlyterm_write("Unable to create the first process !\n");
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]...");
// Restore Casio context.
fx9860_context_restore(&casio_context);
@ -200,7 +219,8 @@ int start(void)
// @note: GetKey will call Bdisp_PutDD_VRAM(),
// so save the current internal Video RAM data into
// Casio's VRAM.
memcpy(casio_Bdisp_GetVRAM(), vram, 1024);
extern struct earlyterm earlyterm;
memcpy(casio_Bdisp_GetVRAM(), earlyterm.display.vram, 1024);
// Wait MENU key.
unsigned int key;
@ -210,24 +230,16 @@ int start(void)
}
}
// DEBUG !
kvram_clear();
printk(0, 0, "Initialize scheduler !");
printk(0, 1, "Try to start sceduler...");
kvram_display();
DBG_WAIT;
// Initialize sheduler !!
//---
// Initialize sheduler !!
//---
earlyterm_write("Initialize scheduler...\n");
sched_initialize();
sched_add_task(vhex_process);
sched_start();
// normally the kernel SHOULD / CAN not arrive here.
kvram_clear();
printk(0, 0, "Kernel job fini !");
kvram_display();
while (1)
{
__asm__ volatile ("sleep");
}
earlyterm_write("Kernel job fini !");
while (1) { __asm__ volatile ("sleep"); }
}

View File

@ -0,0 +1,15 @@
#include <kernel/devices/earlyterm.h>
#include <lib/display.h>
/* earlyterm_clear() - clear internal vram and reset cursor position */
void earlyterm_clear(void)
{
extern struct earlyterm earlyterm;
// Clear video ram
dclear(&earlyterm.display);
// Reset cursor
earlyterm.cursor.x = 0;
earlyterm.cursor.y = 0;
}

View File

@ -0,0 +1,25 @@
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/screen.h>
// Internal globals
struct earlyterm earlyterm;
// earlyterm_init()
// Initialize internal early terminal symbols
int earlyterm_init(void)
{
// Get internal vram and font
// TODO: return menu
if (dopen(&earlyterm.display, "default") != 0)
return (-1);
// Generate cursor informations
earlyterm.cursor.x = 0;
earlyterm.cursor.max.x = screen_get(SCREEN_WIDTH);
earlyterm.cursor.max.x /= earlyterm.display.font->font.width + 1;
earlyterm.cursor.max.y = screen_get(SCREEN_HEIGHT);
earlyterm.cursor.max.y /= earlyterm.display.font->font.height + 1;
earlyterm.cursor.y = 0;
return (0);
}

View File

@ -0,0 +1,162 @@
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/screen.h>
#include <kernel/util/atomic.h>
#include <stdarg.h>
/* earlyterm_vertical_update() - Check / update device vertical cursor */
static void earlyterm_vertical_update(struct earlyterm *earlyterm)
{
// Check if we can move the cursor
if (earlyterm->cursor.y + 1 < earlyterm->cursor.max.y) {
earlyterm->cursor.y = earlyterm->cursor.y + 1;
return;
}
// Other wise scroll the vram
dscroll(&earlyterm->display, earlyterm->display.font->font.height + 1);
}
/* earlyterm_horizontal_update() - Check / update earlyterm horizotal cursor */
static int earlyterm_horizontal_update(struct earlyterm *earlyterm)
{
earlyterm->cursor.x = earlyterm->cursor.x + 1;
if (earlyterm->cursor.x >= earlyterm->cursor.max.x)
{
earlyterm_vertical_update(earlyterm);
earlyterm->cursor.x = 0;
return (1);
}
return (0);
}
/* print_base() - display number in base (0~16)*/
static void print_base(struct earlyterm *earlyterm, uint32_t nb,
int base, int digits_min)
{
char hex[] = "0123456789abcdef";
char buffer[16];
int digits;
// Generate string (reverse)
digits = 0;
while (digits < digits_min || nb != 0)
{
buffer[digits++] = hex[nb % base];
nb = nb / base;
}
// Display string.
while (--digits >= 0)
{
dascii(&earlyterm->display, earlyterm->cursor.x,
earlyterm->cursor.y, buffer[digits]);
earlyterm_horizontal_update(earlyterm);
}
}
/* line_discipline() - Check all "special" char */
static int line_discipline(struct earlyterm *earlyterm, char n)
{
// New line
if (n == '\n')
{
earlyterm->cursor.x = 0;
earlyterm_vertical_update(earlyterm);
return (1);
}
return (0);
}
// earlyterm_write() - printf wrapper for early terminal device
// TODO: update me... x_x
void earlyterm_write(const char *format, ...)
{
extern struct earlyterm earlyterm;
int32_t nb;
va_list ap;
int i;
// Atomic start
atomic_start();
// Get starting variable args
va_start(ap, format);
// Walk into string and display character by character
i = -1;
while (format[++i] != '\0')
{
// Check line discipline
if (line_discipline(&earlyterm, format[i]) != 0)
continue;
// String format "simple"
if (format[i] == '%')
{
if (format[i + 1] == 'd' || format[i + 1] == 'x')
{
// Check negative value
// FIXME: negative error (max)
nb = va_arg(ap, int32_t);
if (nb < 0 && format[i + 1] == 'd')
{
nb = 0 - nb;
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '-');
earlyterm_horizontal_update(&earlyterm);
}
print_base(&earlyterm, nb, (format[i + 1] == 'd') ? 10 : 16, 1);
i = i + 1;
continue;
}
if ((format[i + 1] == '#' && format[i + 2] == 'x') || format[i + 1] == 'p')
{
// add @ if 'p' (pointer)
if (format[i + 1] == 'p')
{
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '@');
earlyterm_horizontal_update(&earlyterm);
}
// Add "0x"
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, '0');
earlyterm_horizontal_update(&earlyterm);
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, 'x');
earlyterm_horizontal_update(&earlyterm);
// Get value
nb = va_arg(ap, uint32_t);
print_base(&earlyterm, nb, 16, 8);
// Update cursor
i = (format[i + 1] == '#') ? i + 2 : i + 1;
continue;
}
if (format[i + 1] == 's')
{
nb = va_arg(ap, uint32_t) - 1;
while (*(char*)(++nb) != '\0')
{
if (line_discipline(&earlyterm, *(char*)nb) != 0)
continue;
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, *(char*)nb);
earlyterm_horizontal_update(&earlyterm);
}
i = i + 1;
continue;
}
}
// Default, display character
dascii(&earlyterm.display, earlyterm.cursor.x, earlyterm.cursor.y, format[i]);
earlyterm_horizontal_update(&earlyterm);
}
// Display vram
screen_update(earlyterm.display.vram);
// End of variodic args.
va_end(ap);
// Atomic stop
atomic_stop();
}

View File

@ -7,7 +7,7 @@ DEVICE(tty) = {
.file_op = {
.read = (void *)&tty_read,
.write =(void *)&tty_write,
.ioctl = &tty_ioctl
.ioctl = NULL
},
.close = &tty_close
};

View File

@ -1,51 +0,0 @@
#include <kernel/devices/tty.h>
#include <kernel/util/atomic.h>
#include <stdarg.h>
void tty_ioctl(void *inode, uint32_t cmd, ...)
{
struct tty_s *tty;
va_list ap;
// Start atomic operation
atomic_start();
tty = inode;
va_start(ap, cmd);
switch (cmd)
{
case TTY_IOCTL_GETDX:
{
int *dx = va_arg(ap, int*);
*dx = tty->cursor.x * (KERNEL_FONT_REAL_WIDTH + 1);
break;
}
case TTY_IOCTL_GETDY:
{
int *dy = va_arg(ap, int*);
int start = tty->cursor.y;
int saved_start;
int line = -1;
while (++line < DISPLAY_VCHAR_MAX - 1)
{
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty->cursor.max.y : start - 1;
// Check if the line exist.
if (tty->buffer[start][0] == '\0')
{
start = saved_start;
break;
}
}
*dy = line * (KERNEL_FONT_REAL_HEIGHT + 1);
break;
}
}
va_end(ap);
// Stop atomic operation
atomic_stop();
}

View File

@ -1,7 +1,22 @@
#include <kernel/devices/tty.h>
#include <kernel/memory.h>
int tty_close(void *inode)
{
// Do nothing for now.
struct tty_s *tty;
int line;
// Get tty object
tty = inode;
// Free'd all allocated memory for the
// output buffer
line = tty->cursor.max.y;
while (line >= 0)
pm_free(tty->buffers.output[line]);
pm_free(tty->buffers.output);
// Free'd tty object
pm_free(tty);
return (0);
}

View File

@ -1,29 +1,64 @@
#include <kernel/devices/tty.h>
#include <kernel/util/string.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/screen.h>
#include <kernel/memory.h>
#include <lib/display.h>
#include <lib/string.h>
// Internal TTY object.
static struct tty_s tty;
//TODO: MULTIPLE OPEN !!!!
//TODO: SHARED TTY DEVICE !!!!
void *tty_open(dev_t major, dev_t minor)
{
int lines;
struct tty_s *tty;
int line;
// TODO: handle major / minor ?
// TODO: handle major / minor !!
(void)major;
(void)minor;
// Try to allocate tty object
tty = (struct tty_s*)pm_alloc(sizeof(struct tty_s));
if (tty == NULL)
return (NULL);
// Initialize TTY cursor.
tty.cursor.x = 0;
tty.cursor.y = 0;
tty.cursor.max.x = TTY_BUFFER_COLUMNS;
tty.cursor.max.y = TTY_BUFFER_LINES;
// Get the font used by the tty.
if (dopen(&tty->disp, "default") != 0)
{
pm_free(tty);
return (NULL);
}
// Initialize TTY buffer.
// TODO: user can set dynamicaly the TTY buffer size ?
lines = TTY_BUFFER_LINES;
while (--lines >= 0)
memset(tty.buffer[lines], '\0', TTY_BUFFER_COLUMNS);
return (&tty);
// 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);
tty->cursor.max.y = tty->cursor.max.y * 4;
// Try to alloc new tty output buffer
tty->buffers.output = (char **)pm_alloc(sizeof(char *) * tty->cursor.max.y);
if (tty->buffers.output == NULL)
{
pm_free(tty);
return (NULL);
}
// Try to alloc each line of the output buffer
line = tty->cursor.max.y;
while (--line >= 0)
{
// Try to alloc the line
tty->buffers.output[line] = (char*)pm_alloc(tty->cursor.max.x);
if (tty->buffers.output[line] != NULL) {
memset(tty->buffers.output[line], '\0', tty->cursor.max.x);
continue;
}
// Release all allocated space and return NULL
while (++line < tty->cursor.max.y)
pm_free(tty->buffers.output[line]);
pm_free(tty->buffers.output);
pm_free(tty);
return (NULL);
}
// Initialize default TTY cursor position.
tty->cursor.x = 0;
tty->cursor.y = 0;
return (tty);
}

View File

@ -2,11 +2,10 @@
#include <kernel/drivers/keyboard.h>
#include <kernel/drivers/timer.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/util/casio.h>
#include <kernel/context.h>
#include <kernel/syscall.h>
#include <lib/string.h>
// Intenral functions
static int check_signal(struct keyboard_obj_s *keyboard, key_t key);
@ -20,8 +19,8 @@ static void cursor_callback(struct keyboard_obj_s *keyboard);
ssize_t tty_read(void *inode, void *buffer, size_t count)
{
extern struct keycache_s *keylist;
struct keycache_s *keynode;
struct keyboard_obj_s keyboard;
struct keycache_s *keynode;
int first_key;
int timer_fd;
@ -29,8 +28,6 @@ ssize_t tty_read(void *inode, void *buffer, size_t count)
if (count < 2)
return (0);
// get tty device
// Initialize internal struc.
memset(buffer, '\0', count);
keyboard.buffer.addr = buffer;
@ -305,6 +302,9 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
// Draw cursor if needed
if (keyboard->cvisible == 0)
{
// Force atomic operation
atomic_start();
// Geneate TTY buffer cursor position.
x = keyboard->buffer.cursor + keyboard->saved.tty.cursor.x;
y = x / keyboard->tty->cursor.max.x;
@ -318,19 +318,24 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
keyboard->tty->cursor.x = x;
keyboard->tty->cursor.y = y;
// Get Display X and Y position.
// TODO: remove me / find better way !!
tty_ioctl(keyboard->tty, TTY_IOCTL_GETDX, &x);
tty_ioctl(keyboard->tty, TTY_IOCTL_GETDY, &y);
// Get "real" X and Y position (pixel)
x = x * (keyboard->tty->disp.font->font.width + 1);
y = y * (keyboard->tty->disp.font->font.height + 1);
// Display cursor.
kvram_reverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1));
kvram_display();
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;
keyboard->tty->cursor.y = sttyy;
// Stop atomic operations
atomic_stop();
}
// Update cursor status.
keyboard->cvisible = keyboard->cvisible ^ 1;

View File

@ -1,7 +1,7 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* tty_vertical_update() - Check / update TTY vertical cursor */
static void tty_vertical_update(struct tty_s *tty)
@ -13,7 +13,7 @@ static void tty_vertical_update(struct tty_s *tty)
tty->cursor.y = 0;
// Wipe new line.
memset(tty->buffer[tty->cursor.y], '\0', tty->cursor.max.x);
memset(tty->buffers.output[tty->cursor.y], '\0', tty->cursor.max.x);
}
/* tty_horizontal_update() - Check / update TTY horizotal cursor */
@ -49,7 +49,7 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_
{
if (tty->cursor.x > 0)
tty->cursor.x = tty->cursor.x - 1;
tty->buffer[tty->cursor.y][tty->cursor.x] = '\0';
tty->buffers.output[tty->cursor.y][tty->cursor.x] = '\0';
continue;
}
@ -60,7 +60,7 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_
offset = 5 - (tty->cursor.x - ((tty->cursor.x / 5) * 5));
if (tty->cursor.x + offset < tty->cursor.max.x)
{
memset(&tty->buffer[tty->cursor.y][tty->cursor.x], ' ', offset);
memset(&tty->buffers.output[tty->cursor.y][tty->cursor.x], ' ', offset);
tty->cursor.x = tty->cursor.x + offset;
continue;
}
@ -86,7 +86,7 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_
if (buffer[i] == '\f' || buffer[i] == '\v')
{
tty_vertical_update(tty);
memset(tty->buffer[tty->cursor.y], ' ', tty->cursor.x);
memset(tty->buffers.output[tty->cursor.y], ' ', tty->cursor.x);
continue;
}
@ -94,7 +94,7 @@ static ssize_t tty_buffer_update(struct tty_s *tty, const uint8_t *buffer, size_
if (buffer[i] == '\r') { tty->cursor.x = 0; continue;}
// Update TTY buffer char.
tty->buffer[tty->cursor.y][tty->cursor.x] = buffer[i];
tty->buffers.output[tty->cursor.y][tty->cursor.x] = buffer[i];
tty_horizontal_update(tty);
}
return (i);
@ -117,14 +117,14 @@ static void tty_display(struct tty_s *tty)
// @note: circular buffer.
line = 0;
start = tty->cursor.y;
while (++line < DISPLAY_VCHAR_MAX)
while (++line < tty->cursor.max.y)
{
// Update check line.
saved_start = start;
start = (start - 1 < 0) ? tty->cursor.max.y : start - 1;
start = (start - 1 < 0) ? tty->cursor.max.y - 1 : start - 1;
// Check if the line existe.
if (tty->buffer[start][0] == '\0')
if (tty->buffers.output[start][0] == '\0')
{
start = saved_start;
break;
@ -132,26 +132,23 @@ static void tty_display(struct tty_s *tty)
}
// clear screen
kvram_clear();
dclear(&tty->disp);
// Display "on-screen" string lines.
y = -1;
while (++y < line)
{
// Get / check line lenght.
line_len = strnlen(tty->buffer[start], tty->cursor.max.x);
if (line_len == 0)
continue;
// Display line
line_len = -1;
while (tty->buffers.output[start][++line_len] != '\0')
dascii(&tty->disp, line_len, y, tty->buffers.output[start][line_len]);
// Display line.
kvram_print(0, y, tty->buffer[start], line_len);
// Get "next" line.
start = (start + 1 > tty->cursor.max.y) ? 0 : start + 1;
// Update row index
start = (start + 1 < tty->cursor.max.y) ? start + 1 : 0;
}
// Display on screen.
kvram_display();
(*screen_update)(tty->disp.vram);
// Stop atomic operation
atomic_stop();

View File

@ -0,0 +1,21 @@
#include <kernel/drivers/screen.h>
// Internal drivers
extern void t6k11_variant_lcd_driver(void *vram);
extern void t6k11_lcd_driver(void *vram);
// Primitives
void (*screen_update)(void *vram);
__attribute__((constructor))
static void screen_constructor(void)
{
// Check T6K11 variant which appear during
// the OS >= 03.00.0000
if (*(uint8_t*)0xa0010021 == '3') {
screen_update = (void*)&t6k11_variant_lcd_driver;
return;
}
// Default driver
screen_update = &t6k11_lcd_driver;
}

View File

@ -0,0 +1,12 @@
#include <kernel/drivers/screen.h>
/* screen_get() - Internal screen getter */
size_t screen_get(screen_getter_t getter)
{
switch (getter)
{
case SCREEN_WIDTH: return (128);
case SCREEN_HEIGHT: return (64);
}
return (0);
}

View File

@ -1,4 +1,4 @@
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
void exception_handler(void)
{
@ -18,8 +18,8 @@ void exception_handler(void)
);
// Write exception informations.
kvram_clear();
printk(0, 0,
earlyterm_clear();
earlyterm_write(
"Ho crap ! Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
@ -32,6 +32,5 @@ void exception_handler(void)
ssr,
sr
);
kvram_display();
while (1);
}

View File

@ -1,4 +1,4 @@
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
// Handler prototype.
extern void keysc_handler(void);
@ -24,13 +24,12 @@ void interrupt_handler(void)
}
// Display error.
kvram_clear();
printk(0, 0,
earlyterm_clear();
earlyterm_write(
"Ho crap ! Interrupt error !\n"
"Interrupt ID (%#x)\n"
"Error: handler not foud !\n",
intevt
);
kvram_display();
while (1);
}

View File

@ -1,4 +1,4 @@
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
__attribute__((section(".vhex.tlb"), interrupt_handler))
void tlb_handler(void)
@ -19,8 +19,8 @@ void tlb_handler(void)
);
// Write exception informations.
kvram_clear();
printk(0, 0,
earlyterm_clear();
earlyterm_write(
"Ho crap ! TLB Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
@ -33,6 +33,5 @@ void tlb_handler(void)
ssr,
sr
);
kvram_display();
while (1);
}

View File

@ -1,6 +1,6 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util/atomic.h>
#include <kernel/util/string.h>
#include <lib/string.h>
// Internal helper
extern struct gladfs_fragment_data_s **gladfs_file_pos(off_t *offset, struct gladfs_inode_s *inode, off_t pos);

View File

@ -1,6 +1,6 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util/atomic.h>
#include <kernel/util/string.h>
#include <lib/string.h>
// Internal helper
extern struct gladfs_fragment_data_s **gladfs_file_pos(off_t *offset, struct gladfs_inode_s *inode, off_t pos);

View File

@ -1,6 +1,6 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
/* gladfs_mount() - GladFS mount primitive (sync) */
void *gladfs_mount(void)
@ -18,9 +18,7 @@ void *gladfs_mount(void)
gladfs_superblock.root_inode = gladfs_superblock.super_op.alloc_inode("/", GLADFS_INODE_TYPE_ROOT);
if (gladfs_superblock.root_inode == NULL)
{
kvram_clear();
printk(0, 0, "GladFS: ROOT inode alloc error !");
kvram_display();
earlyterm_write("GladFS: ROOT inode alloc error !");
DBG_WAIT;
}
}

View File

@ -1,6 +1,6 @@
#include <kernel/fs/gladfs.h>
#include <kernel/util/atomic.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* gladfs_get_name() - Dump the name of a file (sync) */
int gladfs_get_name(void *inode, char *name, size_t count)

View File

@ -1,7 +1,7 @@
#include <kernel/fs/gladfs.h>
#include <kernel/memory.h>
#include <kernel/util/atomic.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* gladfs_alloc_inode() - Superblock primitive to alloc "empty" inode (sync) */
struct gladfs_inode_s *gladfs_alloc_inode(const char *name, mode_t mode)

View File

@ -1,7 +1,7 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/file.h>
#include <kernel/util/atomic.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* casio_smem_data_base_address() - Generate the fragmented data address (0xa0000000 + offset) */
static void *casio_smem_get_data_base_address(smemfs_fragdata_t *fragment)
@ -17,7 +17,7 @@ static void *casio_smem_get_data_base_address(smemfs_fragdata_t *fragment)
}
if (block->info.id != fragment->data_block_id)
return (NULL);
return ((void *)(block->offset + fragment->data_offset));
return ((void *)(uint32_t)(block->offset + fragment->data_offset));
}
/* casio_smem_read() - Read the file data (based on internal cursor) */

View File

@ -1,6 +1,6 @@
#include <kernel/fs/smemfs.h>
#include <kernel/fs/filesystem.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
// Kernel FS block
struct file_system_type smemfs_filesystem =
@ -47,19 +47,20 @@ void smemfs_initialize(void)
// Get / check Casio SMEM sector table
// @note:
// Casio SMEM sector table start
// always at 0xa0270000.
// always (?) at 0xa0270000 (tested with OS 1.00.0000).
// TODO: return error !!
smemfs_superblock.sector_table = (void *)0xa0270000;
if (smemfs_superblock.sector_table->magic_start != 0x4200)
{
kvram_clear();
printk(0, 0, "SMEMFS: Casio sector table error !");
printk(0, 1, "Wait manual reset...");
kvram_display();
earlyterm_clear();
earlyterm_write("SMEMFS: Casio sector table error !");
earlyterm_write("Wait manual reset...");
while (1){ __asm__ volatile ("sleep"); }
}
// Casio SMEM inode table start always at the end of the sector table.
// Normaly start at 0xa0270320 but not always (?)
// TODO: return error !!
int i = -1;
while (smemfs_superblock.sector_table[++i].magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC);
smemfs_superblock.inode_table = (void *)&smemfs_superblock.sector_table[i];
@ -68,10 +69,9 @@ void smemfs_initialize(void)
smemfs_superblock.inode_table->parent.id != 0xffff ||
smemfs_superblock.inode_table->parent.type != 0xffff)
{
kvram_clear();
printk(0, 0, "SMEMFS: Casio inode table error !");
printk(0, 1, "Wait manual reset...");
kvram_display();
earlyterm_clear();
earlyterm_write("SMEMFS: Casio inode table error !");
earlyterm_write("Wait manual reset...");
while (1){ __asm__ volatile ("sleep"); }
}
}

View File

@ -1,19 +1,10 @@
#include <kernel/fs/vfs.h>
#include <kernel/process.h>
#include <kernel/util/debug.h>
int sys_open(const char *pathname, int flags, ...)
{
extern struct process *process_current;
// DEBUG !
/*kvram_clear();
printk(0, 0, "Syscall open() !");
printk(0, 1, "path: %s", pathname);
printk(0, 2, "flags: %#x", flags);
kvram_display();
DBG_WAIT;*/
// Get current process
if (process_current == NULL)
return (-1);

View File

@ -1,6 +1,6 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* vfs_dentry_alloc() - Allocate new "empty" dentry */
struct dentry *vfs_dentry_alloc(const char *name, mode_t mode)

View File

@ -1,8 +1,8 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/process.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
static int get_name(int *name_lenght, const char *path, char *name)
{
@ -39,9 +39,7 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
// Check VFS validity
if (vfs_root_node == NULL)
{
kvram_clear();
printk(0, 0, "VFS root error !");
kvram_display();
earlyterm_write("VFS root error !");
DBG_WAIT;
return (NULL);
}
@ -107,13 +105,10 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
next = vfs_dentry_find_next_sibling(next);
if (next == NULL)
{
// Debug !
kvram_clear();
printk(0, 0, "vfs_resolve(): sibling error !");
printk(0, 1, "old next: %s$", tmp->name);
printk(0, 2, "file: %s$", file->name);
printk(0, 3, "name: %s$", name);
kvram_display();
earlyterm_write("vfs_resolve(): sibling error !");
earlyterm_write("* old next: %s$", tmp->name);
earlyterm_write("* file: %s$", file->name);
earlyterm_write("* name: %s$", name);
DBG_WAIT;
return (NULL);
}
@ -129,26 +124,13 @@ struct dentry *vfs_dentry_resolve(const char *path, int mode)
if ((file->mode & __S_IFDIR) == 0)
{
// Debug !
kvram_clear();
printk(0, 0, "vfs_resolve(): dir error !");
kvram_display();
earlyterm_write("vfs_resolve(): dir error !");
DBG_WAIT;
return (NULL);
}
// Try to find first child
next = vfs_dentry_find_first_child(next);
/*if (next != NULL)
{
// Debug !
kvram_clear();
printk(0, 0, "vfs_resolve(): child info !");
printk(0, 1, "file name: %s$", file->name);
printk(0, 2, "next name: %s$", next->name);
printk(0, 3, "name: %s$", name);
kvram_display();
DBG_WAIT;
}*/
// Update name lenght to skip '/' char
name_lenght = name_lenght + 1;

View File

@ -1,20 +1,21 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
/* vfs_open() - Open file named pathname */
int vfs_open(FILE *file, char const *pathname, int flags)
{
struct dentry *dentry;
//TODO: handle flags !!
(void)flags;
// Get target inode.
dentry = vfs_dentry_resolve(pathname, 0);
if (dentry == NULL)
{
kvram_clear();
printk(0, 0, "VFS_open() error !");
printk(0, 1, "path error '%s'", pathname);
kvram_display();
earlyterm_write("VFS_open() error !");
earlyterm_write("* path error '%s'", pathname);
DBG_WAIT;
return (-1);
}
@ -22,22 +23,20 @@ int vfs_open(FILE *file, char const *pathname, int flags)
// Check directory.
if ((dentry->mode & __S_IFDIR) != 0)
{
kvram_clear();
printk(0, 0, "VFS_open(): file type error '%s'", pathname);
kvram_display();
earlyterm_write("VFS_open(): file type error '%s'", pathname);
DBG_WAIT;
return (-2);
}
//TODO: call FS specific open() primitive ?
// Debug
kvram_clear();
printk(0, 0, "vfs_open(): inode found !");
printk(0, 1, "path: %s", pathname);
printk(0, 2, "name: %s", dentry->name);
printk(0, 3, "inode: %p", dentry->inode);
printk(0, 4, "file_op: %p", dentry->dentry_op.file_op);
kvram_display();
DBG_WAIT;
/* earlyterm_write("vfs_open(): inode found !");
earlyterm_write("* path: %s", pathname);
earlyterm_write("* name: %s", dentry->name);
earlyterm_write("* inode: %p", dentry->inode);
earlyterm_write("* file_op: %p", dentry->dentry_op.file_op);
DBG_WAIT;*/
// Update interne dentry counter
dentry->counter = dentry->counter + 1;

View File

@ -1,5 +1,5 @@
#include <kernel/fs/vfs.h>
#include <kernel/util/string.h>
#include <lib/string.h>
ssize_t vfs_read(FILE *file, void *buf, size_t count)
{

View File

@ -1,7 +1,7 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/fs/stat.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* vfs_mkdir() - Attempts to create a directory named pathname */
int vfs_mkdir(const char *pathname, mode_t mode)

View File

@ -1,6 +1,6 @@
#include <kernel/fs/vfs.h>
#include <kernel/fs/stat.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* gevice_get() - Find internal device */
struct device *device_get(dev_t major)
@ -60,7 +60,6 @@ int vfs_mknod(const char *pathname, mode_t mode, dev_t dev)
if (file->inode == NULL)
return (-4);
// Debug !
/*kvram_clear();
printk(0, 0, "New mknod device !");

View File

@ -1,8 +1,8 @@
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/fs/stat.h>
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
// Internal informations
struct dentry *vfs_root_node = NULL;
@ -31,6 +31,10 @@ int vfs_mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data)
{
// TODO: handle source and data !!
(void)source;
(void)data;
// Check error.
if (filesystemtype == NULL)
return (-1);
@ -53,28 +57,19 @@ int vfs_mount(const char *source, const char *target,
return (-1);
// Try to mount the FS.
// TODO: add possibility to return to main menu
vfs_root_node->inode = filesystem->filesystem_operations.mount();
if (vfs_root_node->inode == NULL)
{
kvram_clear();
printk(0, 0, "VFS: Unable to mount ROOT inode !");
printk(0, 1, "VFS: Wait manual reset...");
kvram_display();
earlyterm_clear();
earlyterm_write("VFS: Unable to mount ROOT inode !");
earlyterm_write("Wait manual reset...");
while (1) { __asm__ volatile ("sleep"); }
}
// Get File System primitives
vfs_root_node->dentry_op.file_op = &filesystem->file_operations;
vfs_root_node->dentry_op.inode_op = &filesystem->inode_operations;
// Debug !
/*kvram_clear();
printk(0, 0, "vfs_root_node = %p", vfs_root_node);
printk(0, 1, "vfs_root_node = %s$", vfs_root_node->name);
printk(0, 2, "vfs_root_node = %p", vfs_root_node->child);
printk(0, 3, "vfs_root_node = %p", vfs_root_node->next);
kvram_display();
DBG_WAIT;*/
return (0);
}

View File

@ -1,74 +1,43 @@
#include <kernel/loader.h>
#include <kernel/fs/vfs.h>
#include <kernel/fs/file.h>
#include <kernel/util/debug.h>
#include <kernel/util/elf.h>
#include <kernel/devices/earlyterm.h>
void *loader(const char *path, struct process *process)
//
// TODO: write doc
//
int loader(struct process *process, const char *path)
{
Elf32_Ehdr header;
FILE file;
// Check error.
if (process == NULL)
// Check error and try to open the file.
if (process == NULL || vfs_open(&file, path, O_RDONLY) != 0)
{
kvram_clear();
printk(0, 0, "loader: Fault error !");
printk(0, 1, "path: %s$", path);
printk(0, 2, "process: %p", process);
kvram_display();
earlyterm_write("loader: Fault error !");
earlyterm_write("* path: %s$", path);
earlyterm_write("* process: %p", process);
DBG_WAIT;
return (NULL);
return (-1);
}
// TODO: use VFS !
if (vfs_open(&file, path, O_RDONLY) != 0)
{
kvram_clear();
printk(0, 0, "loader: File open error !");
printk(0, 1, "path: %s$", path);
kvram_display();
DBG_WAIT;
return (NULL);
}
// Debug !
kvram_clear();
printk(0, 0, "File found !!");
printk(0, 1, "inode = %p", file.private);
printk(0, 2, "path = %s", path);
kvram_display();
DBG_WAIT;
//@NOTE: Only ELF supported !!!
//TODO: USE VFS !!
//
// Get / Check ELF header
// FIXME: return the file type (elf, g1a, bin, ...)
if (loader_get_header(&file, &header) != 0)
{
kvram_clear();
printk(0, 0, "loader: ELF file header error !");
kvram_display();
earlyterm_write("loader: ELF file header error !");
DBG_WAIT;
return (NULL);
return (-2);
}
// Get / Check program validity
void *entry = loader_load_image(&file, &header, process);
if (entry == NULL)
if (loader_load_image(process, &file, &header) != 0)
{
kvram_clear();
printk(0, 0, "loader: ELF file image error !");
kvram_display();
earlyterm_write("loader: ELF file image error !");
DBG_WAIT;
return (NULL);
return (-3);
}
// Success !
kvram_clear();
printk(0, 0, "loader: file loaded sucees !!");
printk(0, 1, "loader: Entry at %p", entry);
kvram_display();
DBG_WAIT;
return (entry);
return (0);
}

View File

@ -1,10 +1,10 @@
#include <kernel/loader.h>
#include <kernel/fs/vfs.h>
#include <kernel/memory.h>
#include <kernel/util/string.h>
#include <lib/string.h>
/* loader_load_image() - Load the program into Virtual Memory */
void *loader_load_image(FILE *file, Elf32_Ehdr *header, struct process *process)
int loader_load_image(struct process *process, FILE *file, Elf32_Ehdr *header)
{
Elf32_Phdr program;
uint32_t paddress;
@ -19,11 +19,11 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, struct process *process)
// Read programme header.
vfs_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET);
if (vfs_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr))
return (NULL);
return (-1);
// Check programe type.
if (program.p_type != PT_LOAD)
return (NULL);
return (-2);
// Update program size
process->memory.program.size = process->memory.program.size + program.p_memsz;
@ -33,7 +33,7 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, struct process *process)
// physical memory.
process->memory.program.start = (uint32_t)pm_alloc(process->memory.program.size);
if (process->memory.program.start == 0x00000000)
return (NULL);
return (-3);
// Now, load all program section into
// physical memory.
@ -57,5 +57,6 @@ void *loader_load_image(FILE *file, Elf32_Ehdr *header, struct process *process)
}
// Generate program entry address
return ((void*)(header->e_entry + process->memory.program.start));
process->context.spc = (uint32_t)(header->e_entry + (uint32_t)process->memory.program.start);
return ((process->context.spc == 0x00000000));
}

View File

@ -1,5 +1,5 @@
#include <kernel/memory.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
void pm_free(void *ptr)
{
@ -17,12 +17,10 @@ void pm_free(void *ptr)
// Check misaligned pointer.
if (((uint32_t)ptr % PM_BLOCK_SIZE) != 0)
{
kvram_clear();
printk(0, 0,
earlyterm_write(
"pm_free: Warning, you try to free misaligned"
"pointer address (%p)\n", sptr
);
kvram_display();
DBG_WAIT;
return;
}
@ -49,11 +47,9 @@ void pm_free(void *ptr)
}
// No block found, display error.
kvram_clear();
printk(0, 0,
earlyterm_write(
"pm_free: Warning, you try to free unused"
"allocated memory (%p)", sptr
);
kvram_display();
DBG_WAIT;
}

View File

@ -1,6 +1,6 @@
#include <kernel/context.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
// Test
uint32_t counter = 0;
@ -24,14 +24,13 @@ void sched_debug(common_context_t *context_current, common_context_t *context_ne
//SH7305_TMU.TIMER[1].TCR.UNF = 0;
//SH7305_TMU.TIMER[2].TCR.UNF = 0;
kvram_clear();
printk(0, 0, "Scheduler_schudele !");
printk(0, 1, "context current = %p", context_current);
printk(0, 2, "context next = %p", context_next);
printk(0, 3, "counter = %#x", counter++);
printk(0, 4, "TSTR: %#x", tstr);
printk(0, 5, "TCOR: %#x", tcor);
printk(0, 6, "TCNT: %#x", tcnt);
printk(0, 7, "TCR: %#x", tcr);
kvram_display();
// Display internal data
earlyterm_write("Scheduler_schudele !");
earlyterm_write("context current = %p", context_current);
earlyterm_write("context next = %p", context_next);
earlyterm_write("counter = %#x", counter++);
earlyterm_write("TSTR: %#x", tstr);
earlyterm_write("TCOR: %#x", tcor);
earlyterm_write("TCNT: %#x", tcnt);
earlyterm_write("TCR: %#x", tcr);
}

View File

@ -1,8 +1,8 @@
#include <kernel/process.h>
#include <kernel/util/unistd_32.h>
#include <kernel/memory.h>
#include <kernel/util/debug.h>
#include <kernel/util/string.h>
#include <kernel/devices/earlyterm.h>
#include <lib/string.h>
struct process *process_create(const char *name)
{
@ -19,9 +19,7 @@ struct process *process_create(const char *name)
process_pid = process_alloc(&process);
if (process == NULL)
{
kvram_clear();
printk(0, 0, "proc_error: alloc error !");
kvram_display();
earlyterm_write("proc_error: alloc error !");
DBG_WAIT;
return (NULL);
}
@ -31,9 +29,7 @@ struct process *process_create(const char *name)
process->memory.stack.user = (uint32_t)pm_alloc(process->memory.stack.size.user);
if (process->memory.stack.user == 0x00000000)
{
kvram_clear();
printk(0, 0, "proc_error: user stack error !");
kvram_display();
earlyterm_write("proc_error: user stack error !");
DBG_WAIT;
process_free(process);
return (NULL);
@ -45,9 +41,7 @@ struct process *process_create(const char *name)
process->memory.stack.kernel = (uint32_t)pm_alloc(process->memory.stack.size.kernel);
if (process->memory.stack.kernel == 0x00000000)
{
kvram_clear();
printk(0, 0, "proc_error: kernel stack error !");
kvram_display();
earlyterm_write("proc_error: kernel stack error !");
DBG_WAIT;
pm_free((void *)process->memory.stack.user);
process_free(process);
@ -56,12 +50,14 @@ struct process *process_create(const char *name)
process->stack.kernel = process->memory.stack.kernel + process->memory.stack.size.kernel;
// initialize "exit" part.
uint8_t callexit[6] = {
// FIXME: add xor r4, r4
uint8_t callexit[8] = {
0b00100100, 0b01001010, // xor r4, r4
0b11000011, __NR_exit, // trapa #__NR_exit
0b10110000, 0b00000100, // bsr PC + 2 - 4
0b00000000, 0b00001001 // nop
};
process->memory.exit.size = 6;
process->memory.exit.size = 8;
process->memory.exit.start = (uint32_t)(pm_alloc(process->memory.exit.size));
if (process->memory.exit.start == 0x00000000)
{
@ -99,11 +95,9 @@ struct process *process_create(const char *name)
process->working_dir = vfs_root_node;
// DEBUG !
kvram_clear();
printk(0, 0, "proc_create: success !");
printk(0, 1, "user stack: %p", process->context.reg[15]);
printk(0, 2, "kernel stack: %p", process->memory.stack.kernel);
kvram_display();
earlyterm_write("proc_create: success !\n");
earlyterm_write("* user stack: %p\n", process->context.reg[15]);
earlyterm_write("* kernel stack: %p\n", process->memory.stack.kernel);
DBG_WAIT;
// Link new process with his parent.

View File

@ -1,7 +1,7 @@
#include <kernel/scheduler.h>
#include <kernel/hardware/cpg.h>
#include <kernel/hardware/tmu.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
#include <kernel/drivers/timer.h>
// Internal data used by the scheduler handler
@ -28,13 +28,13 @@ uint32_t sched_timer_tstr_bit = 0;
return;
// Debug
//kvram_clear();
//printk(0, 0, "Scheduler_schudele !");
//printk(0, 1, "context current = %p", context_current);
//printk(0, 2, "context next = %p", context_next);
//kvram_display();
//printk(0, 3, "context switch !");
//kvram_display();
//dclear(&kdisplay);
//earlyterm_write(&kdisplay, 0, 0, "Scheduler_schudele !");
//earlyterm_write(&kdisplay, 0, 1, "context current = %p", context_current);
//earlyterm_write(&kdisplay, 0, 2, "context next = %p", context_next);
//(*screen_update)(kdisplay.vram);
//earlyterm_write(&kdisplay, 0, 3, "context switch !");
//(*screen_update)(kdisplay.vram);
//DBG_WAIT;
// Context switch
@ -71,20 +71,18 @@ void sched_start(void)
// Debug
kvram_clear();
printk(0, 0,
"FLL freq: %d.%d Mhz\n"
"PLL freq: %d.%d Mhz\n"
"CPU freq: %d.%d Mhz\n"
"BUS freq: %d.%d Mhz\n"
"Per freq: %d.%d Mhz",
earlyterm_write(
"* FLL freq: %d.%d Mhz\n"
"* PLL freq: %d.%d Mhz\n"
"* CPU freq: %d.%d Mhz\n"
"* BUS freq: %d.%d Mhz\n"
"* Per freq: %d.%d Mhz\n",
fll_freq / 1000000, (((fll_freq - ((fll_freq / 1000000)) * 1000000)) + 999) / 1000,
pll_freq / 1000000, (((pll_freq - ((pll_freq / 1000000)) * 1000000)) + 999) / 1000,
cpu_freq / 1000000, (((cpu_freq - ((cpu_freq / 1000000)) * 1000000)) + 999) / 1000,
bus_freq / 1000000, (((bus_freq - ((bus_freq / 1000000)) * 1000000)) + 999) / 1000,
per_freq / 1000000, (((per_freq - ((per_freq / 1000000)) * 1000000)) + 999) / 1000
);
kvram_display();
DBG_WAIT;
// Register first process !
@ -100,12 +98,10 @@ void sched_start(void)
sched_timer_tstr_bit = 1 << sched_timer_id;
// Debug
kvram_clear();
printk(0, 0, "timer ID: %d", sched_timer_id);
printk(0, 1, "timer addr: %#x", sched_timer_address);
printk(0, 2, "timer event: %#x", sched_timer_intevt);
printk(0, 3, "timer TSTR: %#x", sched_timer_tstr_bit);
kvram_display();
earlyterm_write("* timer ID: %d\n", sched_timer_id);
earlyterm_write("* timer addr: %#x\n", sched_timer_address);
earlyterm_write("* timer event: %#x\n", sched_timer_intevt);
earlyterm_write("* timer TSTR: %#x\n", sched_timer_tstr_bit);
DBG_WAIT;

View File

@ -1,11 +1,14 @@
#include <kernel/scheduler.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
void sys_exit(int status)
{
kvram_clear();
printk(0, 0, "PROCESS EXIT SYSCALL !!!!");
printk(0, 0, "Wait manual reset...");
kvram_display();
// TODO handle status
(void)status;
// Fow now, just wait manual reset...
earlyterm_clear();
earlyterm_write("PROCESS EXIT SYSCALL !!!!");
earlyterm_write("Wait manual reset...");
while (1);
}

View File

@ -2,7 +2,7 @@
#include <kernel/scheduler.h>
#include <kernel/loader.h>
#include <kernel/util/atomic.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
pid_t sys_fexecve(const char *pathname)
{
@ -17,21 +17,16 @@ pid_t sys_fexecve(const char *pathname)
proc = process_create(pathname);
if (proc == NULL)
{
kvram_clear();
printk(0, 0, "sys_fexecve: alloc error !");
kvram_display();
earlyterm_write("sys_fexecve: alloc error !");
DBG_WAIT;
atomic_stop();
return (-1);
}
// Try to load binary into physical memory
proc->context.spc = (uint32_t)loader(pathname, proc);
if (proc->context.spc == 0x00000000)
if (loader(proc, pathname) != 0)
{
kvram_clear();
printk(0, 0, "sys_fexecve: loader error !");
kvram_display();
earlyterm_write("sys_fexecve: loader error !");
DBG_WAIT;
process_free(proc);
atomic_stop();
@ -39,35 +34,26 @@ pid_t sys_fexecve(const char *pathname)
}
// Debug
kvram_clear();
printk(0, 0, "New proc loaded !");
kvram_display();
earlyterm_write("New proc loaded !");
DBG_WAIT;
// Add new process into task queue
error = sched_add_task(proc);
if (error != 0)
{
kvram_clear();
printk(0, 0, "sys_fexecve: scheduler error !");
kvram_display();
earlyterm_write("sys_fexecve: scheduler error !");
DBG_WAIT;
process_free(proc);
atomic_stop();
return (-1);
}
// Debug
printk(0, 1, "New proc sched added !");
kvram_display();
DBG_WAIT;
// Get child process PID
child_pid = process_get_pid(proc);
// Debug
printk(0, 2, "New proc PID = %#x !", child_pid);
kvram_display();
earlyterm_write("New proc sched added !");
earlyterm_write("New proc PID = %#x !", child_pid);
DBG_WAIT;
// Stop atomic operations

View File

@ -1,14 +1,14 @@
#include <kernel/syscall.h>
#include <kernel/util/debug.h>
#include <kernel/devices/earlyterm.h>
static void sys_test(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
{
kvram_clear();
printk(0, 0, "a = %#x", a);
printk(0, 1, "b = %#x", b);
printk(0, 2, "c = %#x", c);
printk(0, 3, "d = %#x", d);
kvram_display();
earlyterm_clear();
earlyterm_write("Syscall test entry:\n");
earlyterm_write("* a = %#x\n", a);
earlyterm_write("* b = %#x\n", b);
earlyterm_write("* c = %#x\n", c);
earlyterm_write("* d = %#x\n", d);
DBG_WAIT;
}

View File

@ -1,74 +0,0 @@
#include <kernel/fs/vfs.h>
#include <kernel/devices/tty.h>
#include <kernel/memory.h>
#include <kernel/util/debug.h>
#include <kernel/util/draw.h>
#include <kernel/util/string.h>
// Tree-wrapper
static void vfs_test(struct dentry *node, int level)
{
// Check error.
if (node == NULL)
return;
// Space management.
for (int i = 0 ; i < level ; i++)
tty_write(NULL, " ", 1);
// Display name
tty_write(NULL, node->name, strlen(node->name));
tty_write(NULL, "\n", 1);
// Walk into child and sibling
vfs_test(vfs_dentry_find_first_child(node), level + 1);
vfs_test(vfs_dentry_find_next_sibling(node), level);
}
void kernel_test(void)
{
extern struct dentry *vfs_root_node;
char path[] = "/../dev/./../dev/////tty";
FILE file;
// Debug !
kvram_clear();
printk(0, 0, "Kernel test mode entry !");
printk(0, 1, "Check VFS...");
kvram_display();
DBG_WAIT;
// Check root node
printk(0, 2, "vfs_root_node = %p", vfs_root_node);
printk(0, 3, "vfs_root_node = %s$", vfs_root_node->name);
printk(0, 4, "vfs_root_node = %p", vfs_root_node->child);
printk(0, 5, "vfs_root_node = %p", vfs_root_node->next);
kvram_display();
DBG_WAIT;
// VFS test
tty_open(0, 0);
vfs_test(vfs_root_node, 0);
tty_write(NULL, "FINI !\n", 7);
DBG_WAIT;
DBG_WAIT;
// Try to open file using VFS
if (vfs_open(&file, path, 0))
{
kvram_clear();
printk(0, 0, "vfs_open(): error !");
printk(0, 1, "path %s$", path);
kvram_display();
while (1) { __asm__ volatile ("sleep"); }
}
// Display file informations
kvram_clear();
printk(0, 0, "vfs_open: success !");
printk(0, 1, "path: %s$", path);
printk(0, 2, "file->private: %p", file.private);
printk(0, 3, "file->file_op: %p", file.file_op);
kvram_display();
while (1);
}

View File

@ -1,135 +0,0 @@
#include <kernel/util/debug.h>
#include <stdarg.h>
void printk(int x, int y, char const *str, ...)
{
char hex[] = "0123456789abcdef";
char buffer[16];
int default_pos_x;
int starting_x;
int digits;
int32_t nb;
uint8_t base;
va_list ap;
int i;
// Get starting variable args
va_start(ap, str);
// Initialize part
i = -1;
starting_x = x;
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
default_pos_x = x;
// Walk into string and display character by character
while (str[++i] != '\0')
{
// New line
if (str[i] == '\n')
{
y = y + KERNEL_FONT_REAL_HEIGHT + 1;
x = default_pos_x;
continue;
}
// Horizontal tab
if (str[i] == '\t')
{
x = x / (KERNEL_FONT_REAL_WIDTH + 1);
x = (x + (4 - ((x - starting_x) & 3))) * (KERNEL_FONT_REAL_WIDTH + 1);
continue;
}
// String format "simple"
if (str[i] == '%')
{
if (str[i + 1] == 'd' || str[i + 1] == 'x')
{
// Initialise
digits = 0;
nb = va_arg(ap, int32_t);
base = (str[i + 1] == 'd') ? 10 : 16;
// Check negative value
// FIXME: negative error (max)
if (nb < 0 && str[i + 1] == 'd')
{
nb = 0 - nb;
kvram_ascii(x, y, '-');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
// Generate buffer
// @note: generate in LSB mode.
while (digits == 0 || nb != 0)
{
buffer[digits++] = hex[nb % base];
nb = nb / base;
}
// Reverse dans display string
while (--digits >= 0)
{
kvram_ascii(x, y, buffer[digits]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
i = i + 1;
continue;
}
if ((str[i + 1] == '#' && str[i + 2] == 'x') || str[i + 1] == 'p')
{
// add @ if 'p' (pointer)
if (str[i + 1] == 'p')
{
kvram_ascii(x, y, '@');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
// Add "0x"
kvram_ascii(x, y, '0');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
kvram_ascii(x, y, 'x');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
// Get value
digits = 0;
nb = va_arg(ap, uint32_t);
while (digits < 8)
{
buffer[digits++] = hex[nb & 0x0f];
nb = nb >> 4;
}
// Display string.
while (--digits >= 0)
{
kvram_ascii(x, y, buffer[digits]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
// Update cursor
i = (str[i + 1] == '#') ? i + 2 : i + 1;
continue;
}
if (str[i + 1] == 's')
{
digits = 0;
nb = va_arg(ap, uint32_t);
while (((char*)nb)[digits] != '\0')
{
kvram_ascii(x, y, ((char*)nb)[digits++]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
i = i + 1;
continue;
}
}
// Default, display character
kvram_ascii(x, y, str[i]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
// End of variodic args.
va_end(ap);
}

View File

@ -1,140 +0,0 @@
#include <kernel/util/draw.h>
#include <kernel/util/atomic.h>
// Font bitmap.
static const uint8_t kernel_font_bitmap[] = {
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xef, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xad,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x5e, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2a, 0x92, 0x11, 0x11, 0x28, 0x00, 0x00, 0x38, 0xbb, 0xab, 0xbb, 0xbb,
0x80, 0x08, 0x23, 0x02, 0x57, 0x31, 0x52, 0x41, 0x22, 0x00, 0x01, 0x51,
0x11, 0x54, 0x41, 0x55, 0x22, 0x27, 0x21, 0x04, 0x0a, 0xc4, 0x40, 0x82,
0xae, 0x0e, 0x04, 0xa2, 0xee, 0xee, 0xe2, 0xee, 0x00, 0x80, 0x24, 0x00,
0x1c, 0xd1, 0x41, 0x04, 0x08, 0x80, 0x11, 0x45, 0x04, 0x45, 0x45, 0x44,
0x88, 0x9c, 0x80, 0x10, 0x2b, 0x09, 0x81, 0x10, 0x02, 0x01, 0x03, 0x8b,
0xb8, 0xbb, 0x8b, 0xb8, 0x20, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xee,
0xec, 0xee, 0xea, 0xee, 0xa8, 0xae, 0xee, 0xee, 0x6e, 0xaa, 0xaa, 0xae,
0xe0, 0xe4, 0x05, 0x55, 0x15, 0x11, 0x14, 0x89, 0x51, 0xd5, 0x55, 0x55,
0x09, 0x55, 0x55, 0x45, 0x10, 0x54, 0x0b, 0xb2, 0x2b, 0xba, 0xb9, 0x13,
0x22, 0xaa, 0xba, 0xb3, 0x92, 0xaa, 0x91, 0x12, 0x10, 0x80, 0x55, 0x54,
0x54, 0x45, 0x52, 0x25, 0x45, 0x55, 0x47, 0x51, 0x25, 0x57, 0x52, 0x44,
0x11, 0x00, 0xca, 0xee, 0xce, 0x8e, 0xae, 0xca, 0xea, 0xae, 0x8e, 0xac,
0x4e, 0x4a, 0xa4, 0xee, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00,
0x90, 0x9a, 0x11, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19,
0x30, 0x39, 0x14, 0x31, 0x52, 0x54, 0x00, 0x42, 0x76, 0x26, 0x35, 0x37,
0x55, 0x55, 0x57, 0x22, 0x20, 0x70, 0x6c, 0x86, 0xee, 0x6c, 0xc4, 0xa4,
0xea, 0xaa, 0xac, 0xc4, 0xaa, 0xa4, 0xa4, 0x84, 0x26, 0xe1, 0x55, 0x15,
0x08, 0x54, 0x89, 0x89, 0x55, 0x58, 0xd0, 0x49, 0x55, 0xd4, 0x90, 0x88,
0x99, 0xc1, 0xb1, 0x99, 0x93, 0x2b, 0xb2, 0x9a, 0xa9, 0x20, 0xa3, 0x19,
0x92, 0xa9, 0x39, 0x93, 0x03, 0x80
};
static void font_draw_core(struct font_block_s *fblock)
{
extern uint32_t vram[256];
uint8_t vram_offset_y;
uint32_t pixel_cursor;
uint8_t pixel_test;
int x;
int y;
// Calculate VRAM buffer starting position.
// @note:
// The screen width size is always 128 and we
// use 4-aligned Video RAM so 32 pixels per "slot"
// and 128 / 32 = 4.
// y * 4 can be optimised by used shift operator,
// this is why we use y << 2 because 2^2 = 4.
vram_offset_y = fblock->y << 2;
// Start atomic operations
atomic_start();
// Draw character, pixer per pixel... (x_x)
// TODO: update me !!
y = -1;
while (++y < fblock->height)
{
x = -1;
while (++x < fblock->width)
{
// Get bitmap pixel test.
pixel_cursor = fblock->bitmap.x + fblock->bitmap.y + x;
pixel_test = 0x80 >> (pixel_cursor & 0x07);
// Check if the pixel is block or white.
if (pixel_test & kernel_font_bitmap[pixel_cursor >> 3])
{
vram[((fblock->x + x) >> 5) + vram_offset_y] |=
0x80000000 >> ((fblock->x + x) & 31);
}
}
// Update internal offset.
fblock->bitmap.y = fblock->bitmap.y + KERNEL_FONT_BITMAP_WIDTH;
vram_offset_y = vram_offset_y + 4;
}
// Stop atomic operations
atomic_stop();
}
/* kvram_ascii() - Draw ASCII character into Video RAM */
void kvram_ascii(int x, int y, char const c)
{
struct font_block_s fblock;
// Check obvious error.
if (x > DISPLAY_SCREEN_WIDTH || y > DISPLAY_SCREEN_HEIGHT)
return;
// Calculate the charactere position (bitmap)
fblock.bitmap.y = (c / KERNEL_FONT_NB_CHAR_X) * (KERNEL_FONT_BITMAP_WIDTH * KERNEL_FONT_BITMAP_CHEIGHT);
fblock.bitmap.x = (c - ((c / KERNEL_FONT_NB_CHAR_X) * KERNEL_FONT_NB_CHAR_X)) * KERNEL_FONT_BITMAP_CWIDTH;
// Check X axis culling
// and get font "block" width.
if (x < 0)
{
fblock.bitmap.x = fblock.bitmap.x + x;
fblock.width = KERNEL_FONT_REAL_WIDTH + x;
fblock.x = 0;
} else {
fblock.width =
(x + KERNEL_FONT_REAL_WIDTH >= DISPLAY_SCREEN_WIDTH)
? DISPLAY_SCREEN_WIDTH - x - 1
: KERNEL_FONT_REAL_WIDTH;
fblock.x = x;
}
// Check Y axis culling.
// and get font "block" height.
if (y < 0)
{
fblock.height = KERNEL_FONT_REAL_HEIGHT + y;
fblock.bitmap.y = fblock.bitmap.y + ((-y) * KERNEL_FONT_BITMAP_WIDTH);
fblock.y = 0;
} else {
fblock.height =
(y + KERNEL_FONT_REAL_HEIGHT >= DISPLAY_SCREEN_HEIGHT)
? DISPLAY_SCREEN_HEIGHT - y - 1
: KERNEL_FONT_REAL_HEIGHT;
fblock.y = y;
}
// Check useless draw.
if (fblock.width < 0 || fblock.height < 0)
return;
// Draw ASCII character.
font_draw_core(&fblock);
}

View File

@ -1,26 +0,0 @@
#include <kernel/util/draw.h>
#include <kernel/util/atomic.h>
// Internal Video RAM
uint32_t vram[256];
/* kvram_clear() - Wipe the Video RAM */
void kvram_clear(void)
{
int i;
// The Video RAM is shared between each
// process and the kernel, so we should
// use atomic operation when we use it.
atomic_start();
// Wipe Video RAM
// @note: here, we suppose that the VRAM is
// 4-aligned
i = 256;
while (--i >= 0)
vram[i] = 0x00000000;
// End of atomic operation
atomic_stop();
}

View File

@ -1,43 +0,0 @@
//#include <kernel/util/draw.h>
//#include <kernel/devices/display.h>
//#include <kernel/atomic.h>
/* kvram_clr_str_area() - Clear area based on kernel font size on Video RAM */
//FIXME: secure (DO NOT USE IT !!!!!!)
/*void kvram_clr_str_area(int x, int y, int width, int height)
{
uint32_t vram_offset_y;
int cur_x;
int cur_y;
// Initialize part
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
width = width * (KERNEL_FONT_REAL_WIDTH + 1);
height = height * (KERNEL_FONT_REAL_HEIGHT + 1);
// Get VRAM offset
vram_offset_y = y << 2;
// Start atomic operations
atomic_start();
// Clear area, pixel per pixel x____x
// TODO: update me !!!!
cur_y = -1;
while (++cur_y < height)
{
cur_x = -1;
while (++cur_x < width)
{
vram[((x + cur_x) >> 5) + vram_offset_y] &=
~(0x80000000 >> ((x + cur_x) & 31));
}
// update internal counter
vram_offset_y = vram_offset_y + 4;
}
// Stop atomic operations
atomic_stop();
}*/

View File

@ -1,16 +0,0 @@
#include <kernel/util/draw.h>
/* kvram_display() - Disaplay Video RAM into screen */
void kvram_display(void)
{
extern void t6k11_variant_lcd_driver(void *vram);
extern void t6k11_lcd_driver(void *vram);
extern uint32_t vram[256];
//TODO: handle screen hadware !
//TODO: load dynamically screen driver during the boot
if (*(uint8_t*)0xa0010021 == '3')
t6k11_variant_lcd_driver((void*)vram);
else
t6k11_lcd_driver(vram);
}

View File

@ -1,20 +0,0 @@
#include <kernel/util/draw.h>
void kvram_print(int x, int y, char const *string, size_t len)
{
size_t i;
// Generate pixel positions
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
i = -1;
while (++i < len)
{
// display ASCII char
kvram_ascii(x, y, string[i]);
// Update X position.
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
}

View File

@ -1,38 +0,0 @@
#include <kernel/util/draw.h>
#include <kernel/util/atomic.h>
/* kvram_scroll() - Scroll up the Video RAM */
//FIXME: This part is hardware specific (128x64px)!!
void kvram_scroll(int lines)
{
extern uint32_t vram[256];
int i;
// The Video RAM is shared between each
// process and the kernel, so we should
// use atomic operation when we use it.
atomic_start();
// Scoll n lines
i = 0;
while ((i >> 2) < 63 - lines)
{
vram[i + 0] = vram[i + (lines << 2) + 0];
vram[i + 1] = vram[i + (lines << 2) + 1];
vram[i + 2] = vram[i + (lines << 2) + 2];
vram[i + 3] = vram[i + (lines << 2) + 3];
i = i + 4;
}
// Clear last n lines
while ((i >> 2) < 64)
{
vram[i + 0] = 0x00000000;
vram[i + 1] = 0x00000000;
vram[i + 2] = 0x00000000;
vram[i + 3] = 0x00000000;
i = i + 4;
}
// End of atomic operation
atomic_stop();
}

View File

@ -1,9 +0,0 @@
#include <kernel/util/string.h>
//TODO: update me !!
void *memcpy(void *dest, const void *src, size_t count)
{
for (size_t i = 0 ; i < count ; i = i + 1)
((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
return (dest);
}

View File

@ -1,9 +0,0 @@
#include <kernel/util/string.h>
//TODO: update me :(
void *memset(void *s, int c, size_t n)
{
while ((int)--n >= 0)
((uint8_t*)s)[n] = c;
return (s);
}

View File

@ -1,17 +0,0 @@
#include <kernel/util/string.h>
char *strcat(char *dest, char const *src)
{
size_t i;
size_t start;
if (src == NULL || dest == NULL)
return (0);
i = -1;
start = -1;
while (dest[++start] != '\0');
while (src[++i] != '\0')
dest[start + i] = src[i];
dest[i + start] = '\0';
return (dest);
}

View File

@ -1,31 +0,0 @@
#include <kernel/util/string.h>
//TODO: asm ?
char *strchr(const char *s1, int c)
{
int i = -1;
while (s1[++i] != '\0' && s1[i] != c);
return ((s1[i] == '\0') ? NULL : (void*)&s1[i]);
}
//TODO: asm ?
char *strchrnul(const char *s1, int c)
{
int i = -1;
while (s1[++i] != '\0' && s1[i] != c);
return ((void*)&s1[i]);
}
//TODO asm ?
char *strrchr(const char *s1, int c)
{
void *saved;
saved = NULL;
for (int i = 0 ; s1[i] != '\0' ; i++)
{
if (s1[i] == c)
saved = (void *)&s1[i];
}
return (saved);
}

View File

@ -1,22 +0,0 @@
#include <kernel/util/string.h>
int strcmp(const char *s1, const char *s2)
{
if (s1 == NULL || s2 == NULL)
return (0);
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
{
s1 += 1;
s2 += 1;
}
return (*s1 - *s2);
}
int strncmp(const char *s1, const char *s2, size_t n)
{
if (s1 == NULL || s2 == NULL || n == 0)
return (0);
size_t i = -1;
while (++i < n - 1 && s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i]);
return (s1[i] - s2[i]);
}

View File

@ -1,27 +0,0 @@
#include <kernel/util/string.h>
char *strcpy(char *dest, char const *src)
{
size_t i;
if (src == NULL || dest == NULL)
return (0);
i = -1;
while (src[++i] != '\0')
dest[i] = src[i];
dest[i] = '\0';
return (dest);
}
char *strncpy(char *dest, char const *str, size_t size)
{
size_t i;
if (str == NULL || dest == NULL)
return (0);
i = -1;
while (++i < size && str[i] != '\0')
dest[i] = str[i];
dest[i] = '\0';
return (dest);
}

View File

@ -1,23 +0,0 @@
#include <kernel/util/string.h>
size_t strlen(char const *str)
{
size_t i;
if (str == NULL)
return (0);
i = -1;
while (str[++i] != '\0');
return (i);
}
size_t strnlen(char const *str, size_t maxlen)
{
size_t i;
if (str == NULL)
return (0);
i = -1;
while (str[++i] != '\0' && (size_t)i < maxlen);
return (i);
}

View File

@ -28,7 +28,7 @@ $(foreach mod,$(TARGET-MODULES),$(eval \
target-$(mod)-obj := $$(subst /,_,$$(basename $$(target-$(mod)-src))) $n\
target-$(mod)-obj := $$(patsubst %,$(BUILD)%.o,$$(target-$(mod)-obj)) $n\
))
TARGET-LIBS := $(patsubst %,lib_%.a,$(TARGET-MODULES))
TARGET-LIBS := $(patsubst %,lib%.a,$(TARGET-MODULES))
@ -36,7 +36,7 @@ TARGET-LIBS := $(patsubst %,lib_%.a,$(TARGET-MODULES))
#------- --------#
# Generic rules #
#------- --------#
all: | $(BUILD) $(TARGET-LIBS)
all: $(TARGET-LIBS)
$(BUILD):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ -56,13 +56,13 @@ debug:
# Rule functions #
#------- --------#
define rule-src
$(patsubst %,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1
$(patsubst %,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1 | $(BUILD)
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -c $$< -o $$@ $(HEADER)
@ printf "$(green)[ok]$(nocolor)\n"
endef
define rule-link
$(patsubst %,lib_%.a,$1): $2
$(patsubst %,lib%.a,$1): $2
@ printf "Link $(green)$$@$(nocolor) lib\n"
$(AR) crs $$@ $$^
endef

View File

@ -1,12 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _dascii
.type _dascii, @function
.align 2
_dascii:
trapa #__NR_kvram_ascii
rts
nop
.end

99
src/lib/display/dascii.c Normal file
View File

@ -0,0 +1,99 @@
#include <lib/display.h>
#include <kernel/drivers/screen.h>
static void font_draw_core(uint32_t *vram, struct font_s *font, struct font_block_s *fblock)
{
uint8_t vram_offset_y;
uint32_t pixel_cursor;
uint8_t pixel_test;
int x;
int y;
// Calculate VRAM buffer starting position.
// @note:
// The screen width size is always 128 and we
// use 4-aligned Video RAM so 32 pixels per "slot"
// and 128 / 32 = 4.
// y * 4 can be optimised by used shift operator,
// this is why we use y << 2 because 2^2 = 4.
vram_offset_y = fblock->y << 2;
// Draw character, pixer per pixel... (x_x)
// TODO: update me !!
y = -1;
while (++y < fblock->height)
{
x = -1;
while (++x < fblock->width)
{
// Get bitmap pixel test.
pixel_cursor = fblock->bitmap.x + fblock->bitmap.y + x;
pixel_test = 0x80 >> (pixel_cursor & 0x07);
// Check if the pixel is block or white.
if (pixel_test & font->bitmap.raw[pixel_cursor >> 3])
{
vram[((fblock->x + x) >> 5) + vram_offset_y] |=
0x80000000 >> ((fblock->x + x) & 31);
}
}
// Update internal offset.
fblock->bitmap.y = fblock->bitmap.y + font->bitmap.width;
vram_offset_y = vram_offset_y + 4;
}
}
/* dascii() - Draw ASCII character into Video RAM */
void dascii(display_t *disp, int x, int y, char const c)
{
struct font_block_s fblock;
// Check obvious error.
if (x > (int)disp->display.width || y > (int)disp->display.height)
return;
// Calculate the charactere position (bitmap)
fblock.bitmap.y = (c / disp->nb_char_width) * (disp->font->bitmap.width * disp->font->bitmap.cheight);
fblock.bitmap.x = (c - ((c / disp->nb_char_width) * disp->nb_char_width)) * disp->font->bitmap.cwidth;
// Calculate real pixel position
x = x * (disp->font->font.width + 1);
y = y * (disp->font->font.height + 1);
// Check X axis culling
// and get font "block" width.
if (x < 0)
{
fblock.bitmap.x = fblock.bitmap.x + x;
fblock.width = disp->font->font.width + x;
fblock.x = 0;
} else {
fblock.width = disp->font->font.width;
if (x + (int)disp->font->font.width >= (int)disp->display.width)
fblock.width = disp->display.width - x - 1;
fblock.x = x;
}
// Check Y axis culling.
// and get font "block" height.
if (y < 0)
{
fblock.height = disp->font->font.height + y;
fblock.bitmap.y = fblock.bitmap.y + ((-y) * disp->font->bitmap.width);
fblock.y = 0;
} else {
fblock.height = disp->font->font.height;
if (y + (int)disp->font->font.height >= (int)disp->display.height)
fblock.height = disp->display.height - y - 1;
fblock.y = y;
}
// Check useless draw.
if (fblock.width < 0 || fblock.height < 0)
return;
// Draw ASCII character.
font_draw_core(disp->vram, disp->font, &fblock);
}

View File

@ -1,12 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _dclear
.type _dclear, @function
.align 2
_dclear:
trapa #__NR_kvram_clear
rts
nop
.end

15
src/lib/display/dclear.c Normal file
View File

@ -0,0 +1,15 @@
#include <lib/display.h>
/* dclear() - Wipe the Video RAM */
void dclear(display_t *disp)
{
int i;
// Wipe Video RAM
// @note: here, we suppose that the VRAM
// is 4-aligned.
i = 256;
while (--i >= 0)
disp->vram[i] = 0x00000000;
}

View File

@ -1,12 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _dclr_str_area
.type _dclr_str_area, @function
.align 2
_dclr_str_area:
trapa #__NR_kvram_clr_str_area
rts
nop
.end

19
src/lib/display/dopen.c Normal file
View File

@ -0,0 +1,19 @@
#include <lib/display.h>
int dopen(display_t *disp, const char *fontname)
{
extern struct font_s default5x3;
// TODO: handle font name
(void)fontname;
disp->font = &default5x3;
// Display size is hardcoded for now
disp->display.width = 128;
disp->display.height = 64;
// Pre-calculate internal value used to draw
disp->nb_char_width = disp->font->bitmap.width + disp->font->bitmap.cwidth - 1;
disp->nb_char_width = disp->nb_char_width / disp->font->bitmap.cwidth;
return (0);
}

View File

@ -1,12 +0,0 @@
#include "kernel/util/unistd_32.h"
.text
.global _dprint
.type _dprint, @function
.align 2
_dprint:
trapa #__NR_kvram_print
rts
nop
.end

237
src/lib/display/dprint.c Normal file
View File

@ -0,0 +1,237 @@
#include <lib/display.h>
#include <stdarg.h>
// Structure used to store
// internal data
struct dintern_s
{
display_t *disp;
size_t counter;
va_list ap;
int x;
int y;
int force;
};
// Internal functions
static void disp_char(struct dintern_s *intern, char n);
static void dchar(struct dintern_s *intern, char spec);
static void dstr(struct dintern_s *intern, char spec);
static void duint(struct dintern_s *intern, char spec);
static void dint(struct dintern_s *intern, char spec);
static void dptr(struct dintern_s *intern, char spec);
// Internal actions list
void (*actions_list[26])(struct dintern_s *intern, char spec) = {
NULL, NULL, dchar, dint,
NULL, NULL, NULL, NULL,
dint, NULL, NULL, NULL,
NULL, NULL, duint, dptr,
NULL, NULL, dstr, NULL,
duint, NULL, NULL, duint,
NULL, NULL,
};
/* dchar() - display only one char */
static void dchar(struct dintern_s *intern, char spec)
{
(void)spec;
disp_char(intern, (char)va_arg(intern->ap, int));
}
/* dstr() - display string */
static void dstr(struct dintern_s *intern, char spec)
{
char *str;
(void)spec;
str = va_arg(intern->ap, char *);
while (*str != '\0')
{
disp_char(intern, *str);
str = str + 1;
}
}
/* dint() - Display unsigned interger */
static void duint(struct dintern_s *intern, char spec)
{
const char hexa[] = "0123456789abcdef";
char buffer[32];
uint32_t num;
int digits;
int base;
// Get appropriate base
base = (spec == 'x') ? 16 : 10;
// TODO: handle size
num = va_arg(intern->ap, uint32_t);
// Generate number (reverse)
digits = 0;
while (num != 0 || digits == 0) {
buffer[digits++] = hexa[num % base];
num = num / base;
}
while (--digits >= 0) {
disp_char(intern, buffer[digits]);
}
}
/* dptr() - Display pointer address */
static void dptr(struct dintern_s *intern, char spec)
{
const char hexa[] = "0123456789abcdef";
char buffer[32];
uint32_t num;
int digits;
// Avoid unused parameter error
(void)spec;
// Display default string
disp_char(intern, '@');
disp_char(intern, '0');
disp_char(intern, 'x');
// TODO: handle size
num = va_arg(intern->ap, uint32_t);
// Generate number (reverse)
digits = 0;
while (num != 0 || digits < 8) {
buffer[digits++] = hexa[num & 15];
num = num >> 4;
}
while (--digits >= 0) {
disp_char(intern, buffer[digits]);
}
}
/* dint() - Display signed number (base 10) */
static void dint(struct dintern_s *intern, char spec)
{
char buffer[32];
int32_t num;
int digits;
// Avoid unused parameters
(void)spec;
// TODO: handle size
num = va_arg(intern->ap, int32_t);
// Check negative value
// FIXME: maximum negative value !!!!!!
if (num < 0) {
disp_char(intern, '-');
num = -num;
}
// Generate number (reverse)
digits = 0;
while (num != 0 || digits == 0) {
buffer[digits++] = (num % 10) + '0';
num = num / 10;
}
while (--digits >= 0) {
disp_char(intern, buffer[digits]);
}
}
/* line_discipline() - small line discipline */
static int line_discipline(struct dintern_s *intern, char n)
{
// New line
if (n == '\n')
{
intern->y = intern->y + intern->disp->font->font.height + 1;
intern->x = 0;
return (0);
}
// Horizontal tab
if (n == '\t')
{
intern->x = intern->x / (intern->disp->font->font.width + 1);
intern->x = (intern->x + (4 - (intern->x & 3)));
intern->x = intern->x * (intern->disp->font->font.width + 1);
return (0);
}
return (1);
}
/* disp_char() - display on character and update internal data */
static void disp_char(struct dintern_s *intern, char n)
{
dascii(intern->disp, intern->x, intern->y, n);
intern->x = intern->x + (intern->disp->font->font.width + 1);
intern->counter = intern->counter + 1;
intern->force = intern->force - 1;
}
/* dprint() - printf wrapper */
size_t dprint(display_t *disp, int x, int y, const char *format, ...)
{
void (*action)(struct dintern_s *intern, char spec);
struct dintern_s intern;
void *sformat;
// Get variable args entry
va_start(intern.ap, format);
// Generate pixel positions
intern.x = x * (disp->font->font.width + 1);
intern.y = y * (disp->font->font.height + 1);
// Initialise internal data
intern.counter = 0;
intern.force = 0;
// Display string char by char...
format = format - 1;
while (*(++format) != '\0')
{
// Check line discipline character
if (line_discipline(&intern, *format) != 0)
continue;
// Check general character or forced character
if (*format != '%' || intern.force > 0) {
disp_char(&intern, *format);
continue;
}
// Check "%%" format
if (format[1] == '%') {
disp_char(&intern, '%');
format = format + 1;
continue;
}
// Get format options
// TODO: get options
sformat = (void *)format;
if (!(*format >= 'A' && *format <= 'Z') &&
!(*format >= 'a' && *format <= 'z')) {
intern.force = (uint32_t)format - (uint32_t)sformat;
format = sformat;
continue;
}
// Get action if possible
action = actions_list[(*format | 0x20) - 'a'];
if (action == NULL) {
intern.force = (uint32_t)format - (uint32_t)sformat;
format = sformat;
continue;
}
// Call actions
(*action)(&intern, *format);
}
return (intern.counter);
}

View File

@ -1,12 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _dreverse
.type _dreverse, @function
.align 2
_dreverse:
trapa #__NR_kvram_reverse
rts
nop
.end

View File

@ -1,10 +1,8 @@
#include <kernel/util/draw.h>
#include <kernel/util/atomic.h>
#include <lib/display.h>
/* kvram_reverse() - Reverse Video RAM area */
void kvram_reverse(int x, int y, int width, int height)
/* dreverse() - Reverse Video RAM area */
void dreverse(display_t *disp, int x, int y, int width, int height)
{
extern uint32_t vram[256];
int vram_offset_y;
int j;
@ -18,8 +16,8 @@ void kvram_reverse(int x, int y, int width, int height)
width = width + x;
x = 0;
} else {
if (x + width >= DISPLAY_SCREEN_WIDTH)
width = DISPLAY_SCREEN_WIDTH - x;
if (x + width >= (int)disp->display.width)
width = disp->display.width - x;
}
// Get "real" Y position and area height.
@ -28,8 +26,8 @@ void kvram_reverse(int x, int y, int width, int height)
height = height + x;
y = 0;
} else {
if (y + height >= DISPLAY_SCREEN_HEIGHT)
height = DISPLAY_SCREEN_HEIGHT - x;
if (y + height >= (int)disp->display.height)
height = disp->display.height - x;
}
// Check potential error.
@ -47,23 +45,14 @@ void kvram_reverse(int x, int y, int width, int height)
// this is why we use y << 2 because 2^2 = 4.
vram_offset_y = (y + height - 1) << 2;
// The Video RAM is sheared between each
// process and the kernel, so we should
// use atomic operation when we use it.
atomic_start();
// Reverse area
while (--height >= 0)
{
j = width + x;
while (--j >= x)
{
vram[(j >> 5) + vram_offset_y] ^= 0x80000000 >> (j & 31);
disp->vram[(j >> 5) + vram_offset_y] ^= 0x80000000 >> (j & 31);
}
vram_offset_y = vram_offset_y - 4;
}
// End of atomic operation
atomic_stop();
}

View File

@ -1,12 +0,0 @@
#include <kernel/util/unistd_32.h>
.text
.global _dscroll
.type _dscroll, @function
.align 2
_dclear:
trapa #__NR_kvram_scroll
rts
nop
.end

28
src/lib/display/dscroll.c Normal file
View File

@ -0,0 +1,28 @@
#include <lib/display.h>
/* dscroll() - Scroll up the Video RAM */
//FIXME: This part is hardware specific (128x64px)!!
void dscroll(display_t *disp, int lines)
{
int i;
// Scoll n lines
i = 0;
while ((i >> 2) < 63 - lines)
{
disp->vram[i + 0] = disp->vram[i + (lines << 2) + 0];
disp->vram[i + 1] = disp->vram[i + (lines << 2) + 1];
disp->vram[i + 2] = disp->vram[i + (lines << 2) + 2];
disp->vram[i + 3] = disp->vram[i + (lines << 2) + 3];
i = i + 4;
}
// Clear last n lines
while ((i >> 2) < 64)
{
disp->vram[i + 0] = 0x00000000;
disp->vram[i + 1] = 0x00000000;
disp->vram[i + 2] = 0x00000000;
disp->vram[i + 3] = 0x00000000;
i = i + 4;
}
}

View File

@ -0,0 +1,59 @@
#include <lib/display.h>
// Define the (hardcoded) font bitmap informations.
#define DEFAULT_FONT_BITMAP_WIDTH (127) // Bitmap width
#define DEFAULT_FONT_BITMAP_HEIGHT (23) // Bitmap height
#define DEFAULT_FONT_BITMAP_CWIDTH (4) // Character width (bitmap)
#define DEFAULT_FONT_BITMAP_CHEIGHT (6) // Character height (bitmap)
#define DEFAULT_FONT_REAL_WIDTH (3) // Charater width (real)
#define DEFAULT_FONT_REAL_HEIGHT (5) // Character height (real)
// Font bitmap (raw).
static const uint8_t default_font_bitmap[] = {
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xef, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x56, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xad,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x5e, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
0x2a, 0x92, 0x11, 0x11, 0x28, 0x00, 0x00, 0x38, 0xbb, 0xab, 0xbb, 0xbb,
0x80, 0x08, 0x23, 0x02, 0x57, 0x31, 0x52, 0x41, 0x22, 0x00, 0x01, 0x51,
0x11, 0x54, 0x41, 0x55, 0x22, 0x27, 0x21, 0x04, 0x0a, 0xc4, 0x40, 0x82,
0xae, 0x0e, 0x04, 0xa2, 0xee, 0xee, 0xe2, 0xee, 0x00, 0x80, 0x24, 0x00,
0x1c, 0xd1, 0x41, 0x04, 0x08, 0x80, 0x11, 0x45, 0x04, 0x45, 0x45, 0x44,
0x88, 0x9c, 0x80, 0x10, 0x2b, 0x09, 0x81, 0x10, 0x02, 0x01, 0x03, 0x8b,
0xb8, 0xbb, 0x8b, 0xb8, 0x20, 0x82, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xee,
0xec, 0xee, 0xea, 0xee, 0xa8, 0xae, 0xee, 0xee, 0x6e, 0xaa, 0xaa, 0xae,
0xe0, 0xe4, 0x05, 0x55, 0x15, 0x11, 0x14, 0x89, 0x51, 0xd5, 0x55, 0x55,
0x09, 0x55, 0x55, 0x45, 0x10, 0x54, 0x0b, 0xb2, 0x2b, 0xba, 0xb9, 0x13,
0x22, 0xaa, 0xba, 0xb3, 0x92, 0xaa, 0x91, 0x12, 0x10, 0x80, 0x55, 0x54,
0x54, 0x45, 0x52, 0x25, 0x45, 0x55, 0x47, 0x51, 0x25, 0x57, 0x52, 0x44,
0x11, 0x00, 0xca, 0xee, 0xce, 0x8e, 0xae, 0xca, 0xea, 0xae, 0x8e, 0xac,
0x4e, 0x4a, 0xa4, 0xee, 0x0e, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00,
0x90, 0x9a, 0x11, 0x23, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x19,
0x30, 0x39, 0x14, 0x31, 0x52, 0x54, 0x00, 0x42, 0x76, 0x26, 0x35, 0x37,
0x55, 0x55, 0x57, 0x22, 0x20, 0x70, 0x6c, 0x86, 0xee, 0x6c, 0xc4, 0xa4,
0xea, 0xaa, 0xac, 0xc4, 0xaa, 0xa4, 0xa4, 0x84, 0x26, 0xe1, 0x55, 0x15,
0x08, 0x54, 0x89, 0x89, 0x55, 0x58, 0xd0, 0x49, 0x55, 0xd4, 0x90, 0x88,
0x99, 0xc1, 0xb1, 0x99, 0x93, 0x2b, 0xb2, 0x9a, 0xa9, 0x20, 0xa3, 0x19,
0x92, 0xa9, 0x39, 0x93, 0x03, 0x80
};
// Internal global font object
struct font_s default5x3 = {
.bitmap = {
.width = DEFAULT_FONT_BITMAP_WIDTH,
.height = DEFAULT_FONT_BITMAP_HEIGHT,
.cwidth = DEFAULT_FONT_BITMAP_CWIDTH,
.cheight = DEFAULT_FONT_BITMAP_CHEIGHT,
.raw = (void*)default_font_bitmap
},
.font = {
.width = DEFAULT_FONT_REAL_WIDTH,
.height = DEFAULT_FONT_REAL_HEIGHT
}
};

View File

@ -11,3 +11,12 @@ int strcmp(const char *s1, const char *s2)
}
return (*s1 - *s2);
}
int strncmp(const char *s1, const char *s2, size_t n)
{
if (s1 == NULL || s2 == NULL || n == 0)
return (0);
size_t i = -1;
while (++i < n - 1 && s1[i] != '\0' && s2[i] != '\0' && s1[i] == s2[i]);
return (s1[i] - s2[i]);
}

View File

@ -9,7 +9,6 @@ include ../../../global.mk
## Static variables
##--
HEADER := -I../../../include -I../../../include/user
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
BUILD := ../../../build/user/shell
DEBUG := ../../../debug_bin
OUTPUT := ../../../output
@ -18,6 +17,7 @@ NAME := shell
EXEC := $(OUTPUT)/$(NAME).elf
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
LIBS := -L../../lib -lstring -ldisplay -lunistd -lgcc
@ -42,10 +42,10 @@ OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(EXEC)
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) -lgcc > $(MEMORY_MAP)
$(EXEC): $(OBJ) | $(DEBUG)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) > $(MEMORY_MAP)
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
rm -f $(DEBUG)/$(NAME).elf.big
@ -75,7 +75,7 @@ sec:
## Automated rules
##---
define rule-src
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1 | $(BUILD)
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"

View File

@ -4,12 +4,12 @@
int builtin_proc(void)
{
pid_t child;
// pid_t child;
// Debug
dclear();
dprint(0, 0, "Proc builtin !");
dupdate();
// dclear();
// dprint(0, 0, "Proc builtin !");
// dupdate();
for (int i = 0 ; i < 3000000 ; i++);
// Try to create first child

View File

@ -11,8 +11,8 @@ int main(void)
{
char input[12];
int cmd_size;
char **argv;
int argc;
//char **argv;
//int argc;
int fd;
// Try to open TTY
@ -24,10 +24,12 @@ int main(void)
if (fd < 0)
{
// Display error.
dclear();
dprint(0, 0, "User program fail to open TTY");
dprint(0, 1, "Wait user manual reset...");
dupdate();
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)

View File

@ -23,7 +23,7 @@ int check_builtin(char *cmd)
{
// Process test
dclear();
/* dclear();
dprint(0, 0, "Process Load Test !");
// Load process test
@ -52,7 +52,7 @@ int check_builtin(char *cmd)
//int wstatus;
//pid_t pid;
//int i;
*/
// Try to find builtin
/* for (int i = 0 ; i < 1 ; i++)
{
@ -85,4 +85,4 @@ int check_builtin(char *cmd)
// }
// }
// return (1);
}
}

View File

@ -9,7 +9,7 @@ include ../../../global.mk
## Static variables
##--
HEADER := -I../../../include -I../../../include/user
LIBS := -L../../lib/ -l_unistd -l_stdio -l_string -l_display
LIBS := -L../../lib/ -lunistd -lstdio -lstring -ldisplay -lgcc
BUILD := ../../../build/user/test
DEBUG := ../../../debug_bin
OUTPUT := ../../../output
@ -45,7 +45,7 @@ OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))
all: | $(BUILD) $(DEBUG) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) -lgcc > $(MEMORY_MAP)
$(CC) -fPIC -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) > $(MEMORY_MAP)
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
rm -f $(DEBUG)/$(NAME).elf.big